Rebase LZMA SDK on 16.04 stable

This was downloaded from http://www.7-zip.org/a/lzma1604.7z
The bin folder was excluded like in previous updates

All files were deleted and replaced with those from the SDK.
The embedded projects Tukaani, xz-embedded and android build
files where not touched.

The changelog since the 9.38 beta is:

16.04          2016-10-04
-------------------------
- The bug was fixed in DllSecur.c.

16.03          2016-09-28
-------------------------
- SFX modules now use some protection against DLL preloading attack.
- Some bugs in 7z code were fixed.

16.02          2016-05-21
-------------------------
- The BUG in 16.00 - 16.01 was fixed:
  Split Handler (SplitHandler.cpp) returned incorrect
  total size value (kpidSize) for split archives.

16.01          2016-05-19
-------------------------
- Some internal changes to reduce the number of compiler warnings.

16.00          2016-05-10
-------------------------
- Some bugs were fixed.

15.12          2015-11-19
-------------------------
- The BUG in C version of 7z decoder was fixed:
  7zDec.c : SzDecodeLzma2()
  7z decoder could mistakenly report about decoding error for some 7z
archives
  that use LZMA2 compression method.
  The probability to get that mistaken decoding error report was about
  one error per 16384 solid blocks for solid blocks larger than 16 KB
(compressed size).
- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:
  7zArcIn.c : SzReadHeader2()
  7z decoder worked incorrectly for 7z archives that contain
  empty solid blocks, that can be placed to 7z archive, if some file is
  unavailable for reading during archive creation.

15.09 beta     2015-10-16
-------------------------
- The BUG in LZMA / LZMA2 encoding code was fixed.
  The BUG in LzFind.c::MatchFinder_ReadBlock() function.
  If input data size is larger than (4 GiB - dictionary_size),
  the following code worked incorrectly:
  -  LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions
     for compressing from memory to memory.
     That BUG is not related to LZMA encoder version that works via
streams.
  -  LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly,
if
     default value of chunk size (CLzma2EncProps::blockSize) is changed
     to value larger than (4 GiB - dictionary_size).

Change-Id: I6b3974015c605fba3c0d4d897fab5a166174f441
diff --git a/C/7z.h b/C/7z.h
index dc25f53..216f381 100644
--- a/C/7z.h
+++ b/C/7z.h
@@ -1,5 +1,5 @@
 /* 7z.h -- 7z interface

-2013-01-18 : Igor Pavlov : Public domain */

+2015-11-18 : Igor Pavlov : Public domain */

 

 #ifndef __7Z_H

 #define __7Z_H

@@ -11,7 +11,7 @@
 #define k7zStartHeaderSize 0x20

 #define k7zSignatureSize 6

 

-extern Byte k7zSignature[k7zSignatureSize];

+extern const Byte k7zSignature[k7zSignatureSize];

 

 typedef struct

 {

@@ -25,8 +25,7 @@
 {

   size_t PropsOffset;

   UInt32 MethodID;

-  Byte NumInStreams;

-  Byte NumOutStreams;

+  Byte NumStreams;

   Byte PropsSize;

 } CSzCoderInfo;

 

@@ -34,37 +33,25 @@
 {

   UInt32 InIndex;

   UInt32 OutIndex;

-} CSzBindPair;

+} CSzBond;

 

 #define SZ_NUM_CODERS_IN_FOLDER_MAX 4

-#define SZ_NUM_BINDS_IN_FOLDER_MAX 3

+#define SZ_NUM_BONDS_IN_FOLDER_MAX 3

 #define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4

-#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4

 

 typedef struct

 {

   UInt32 NumCoders;

-  UInt32 NumBindPairs;

+  UInt32 NumBonds;

   UInt32 NumPackStreams;

-  UInt32 MainOutStream;

+  UInt32 UnpackStream;

   UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];

-  CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX];

+  CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];

   CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];

-  UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];

 } CSzFolder;

 

-/*

-typedef struct

-{

-  size_t CodersDataOffset;

-  size_t UnpackSizeDataOffset;

-  // UInt32 StartCoderUnpackSizesIndex;

-  UInt32 StartPackStreamIndex;

-  // UInt32 IndexOfMainOutStream;

-} CSzFolder2;

-*/

 

-SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes);

+SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);

 

 typedef struct

 {

@@ -94,47 +81,25 @@
   UInt32 NumPackStreams;

   UInt32 NumFolders;

 

-  UInt64 *PackPositions; // NumPackStreams + 1

-  CSzBitUi32s FolderCRCs;

+  UInt64 *PackPositions;          // NumPackStreams + 1

+  CSzBitUi32s FolderCRCs;         // NumFolders

 

-  size_t *FoCodersOffsets;

-  size_t *FoSizesOffsets;

-  // UInt32 StartCoderUnpackSizesIndex;

-  UInt32 *FoStartPackStreamIndex;

+  size_t *FoCodersOffsets;        // NumFolders + 1

+  UInt32 *FoStartPackStreamIndex; // NumFolders + 1

+  UInt32 *FoToCoderUnpackSizes;   // NumFolders + 1

+  Byte *FoToMainUnpackSizeIndex;  // NumFolders

+  UInt64 *CoderUnpackSizes;       // for all coders in all folders

 

-  // CSzFolder2 *Folders;  // +1 item for sum values

   Byte *CodersData;

-  Byte *UnpackSizesData;

-  size_t UnpackSizesDataSize;

-  // UInt64 *CoderUnpackSizes;

 } CSzAr;

 

+UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);

 

 SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

     ILookInStream *stream, UInt64 startPos,

     Byte *outBuffer, size_t outSize,

     ISzAlloc *allocMain);

 

-/*

-  SzExtract extracts file from archive

-

-  *outBuffer must be 0 before first call for each new archive.

-

-  Extracting cache:

-    If you need to decompress more than one file, you can send

-    these values from previous call:

-      *blockIndex,

-      *outBuffer,

-      *outBufferSize

-    You can consider "*outBuffer" as cache of solid block. If your archive is solid,

-    it will increase decompression speed.

-  

-    If you use external function, you can declare these 3 cache variables

-    (blockIndex, outBuffer, outBufferSize) as static in that external function.

-    

-    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.

-*/

-

 typedef struct

 {

   CSzAr db;

@@ -144,7 +109,7 @@
   

   UInt32 NumFiles;

 

-  UInt64 *UnpackPositions;

+  UInt64 *UnpackPositions;  // NumFiles + 1

   // Byte *IsEmptyFiles;

   Byte *IsDirs;

   CSzBitUi32s CRCs;

@@ -154,9 +119,8 @@
   CSzBitUi64s MTime;

   CSzBitUi64s CTime;

 

-  // UInt32 *FolderStartPackStreamIndex;

-  UInt32 *FolderStartFileIndex; // + 1

-  UInt32 *FileIndexToFolderIndexMap;

+  UInt32 *FolderToFile;   // NumFolders + 1

+  UInt32 *FileToFolder;   // NumFiles

 

   size_t *FileNameOffsets; /* in 2-byte steps */

   Byte *FileNames;  /* UTF-16-LE */

@@ -184,6 +148,28 @@
 UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);

 */

 

+

+

+/*

+  SzArEx_Extract extracts file from archive

+

+  *outBuffer must be 0 before first call for each new archive.

+

+  Extracting cache:

+    If you need to decompress more than one file, you can send

+    these values from previous call:

+      *blockIndex,

+      *outBuffer,

+      *outBufferSize

+    You can consider "*outBuffer" as cache of solid block. If your archive is solid,

+    it will increase decompression speed.

+  

+    If you use external function, you can declare these 3 cache variables

+    (blockIndex, outBuffer, outBufferSize) as static in that external function.

+    

+    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.

+*/

+

 SRes SzArEx_Extract(

     const CSzArEx *db,

     ILookInStream *inStream,

diff --git a/C/7zAlloc.c b/C/7zAlloc.c
index 698071c..360da05 100644
--- a/C/7zAlloc.c
+++ b/C/7zAlloc.c
@@ -1,5 +1,5 @@
 /* 7zAlloc.c -- Allocation functions

-2010-10-29 : Igor Pavlov : Public domain */

+2015-11-09 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -22,11 +22,11 @@
 

 void *SzAlloc(void *p, size_t size)

 {

-  p = p;

+  UNUSED_VAR(p);

   if (size == 0)

     return 0;

   #ifdef _SZ_ALLOC_DEBUG

-  fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);

+  fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount);

   g_allocCount++;

   #endif

   return malloc(size);

@@ -34,7 +34,7 @@
 

 void SzFree(void *p, void *address)

 {

-  p = p;

+  UNUSED_VAR(p);

   #ifdef _SZ_ALLOC_DEBUG

   if (address != 0)

   {

@@ -47,11 +47,11 @@
 

 void *SzAllocTemp(void *p, size_t size)

 {

-  p = p;

+  UNUSED_VAR(p);

   if (size == 0)

     return 0;

   #ifdef _SZ_ALLOC_DEBUG

-  fprintf(stderr, "\nAlloc_temp %10d bytes;  count = %10d", size, g_allocCountTemp);

+  fprintf(stderr, "\nAlloc_temp %10u bytes;  count = %10d", (unsigned)size, g_allocCountTemp);

   g_allocCountTemp++;

   #ifdef _WIN32

   return HeapAlloc(GetProcessHeap(), 0, size);

@@ -62,7 +62,7 @@
 

 void SzFreeTemp(void *p, void *address)

 {

-  p = p;

+  UNUSED_VAR(p);

   #ifdef _SZ_ALLOC_DEBUG

   if (address != 0)

   {

diff --git a/C/7zAlloc.h b/C/7zAlloc.h
index 860f116..4d7502f 100644
--- a/C/7zAlloc.h
+++ b/C/7zAlloc.h
@@ -1,15 +1,23 @@
 /* 7zAlloc.h -- Allocation functions

-2010-10-29 : Igor Pavlov : Public domain */

+2013-03-25 : Igor Pavlov : Public domain */

 

 #ifndef __7Z_ALLOC_H

 #define __7Z_ALLOC_H

 

 #include <stdlib.h>

 

+#ifdef __cplusplus

+extern "C" {

+#endif

+

 void *SzAlloc(void *p, size_t size);

 void SzFree(void *p, void *address);

 

 void *SzAllocTemp(void *p, size_t size);

 void SzFreeTemp(void *p, void *address);

 

+#ifdef __cplusplus

+}

+#endif

+

 #endif

diff --git a/C/7zArcIn.c b/C/7zArcIn.c
index 5fd4f6b..c324c37 100644
--- a/C/7zArcIn.c
+++ b/C/7zArcIn.c
@@ -1,5 +1,5 @@
 /* 7zArcIn.c -- 7z Input functions

-2014-06-16 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -10,8 +10,16 @@
 #include "7zCrc.h"

 #include "CpuArch.h"

 

-#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \

-  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }

+#define MY_ALLOC(T, p, size, alloc) { \

+  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }

+

+#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }

+

+#define MY_ALLOC_AND_CPY(to, size, from, alloc) \

+  { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }

+

+#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \

+  { if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }

 

 #define k7zMajorVersion 0

 

@@ -48,75 +56,69 @@
   // k7zIsReal

 };

 

-Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

+const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

 

-#define NUM_FOLDER_CODERS_MAX 32

-#define NUM_CODER_STREAMS_MAX 32

-

-/*

-static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex)

-{

-  UInt32 i;

-  for (i = 0; i < p->NumBindPairs; i++)

-    if (p->BindPairs[i].InIndex == inStreamIndex)

-      return i;

-  return -1;

-}

-*/

-

-#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }

+#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }

 

 static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)

 {

-  MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);

-  MY_ALLOC(UInt32, p->Vals, num, alloc);

+  if (num == 0)

+  {

+    p->Defs = NULL;

+    p->Vals = NULL;

+  }

+  else

+  {

+    MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);

+    MY_ALLOC(UInt32, p->Vals, num, alloc);

+  }

   return SZ_OK;

 }

 

 void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc)

 {

-  IAlloc_Free(alloc, p->Defs); p->Defs = 0;

-  IAlloc_Free(alloc, p->Vals); p->Vals = 0;

+  IAlloc_Free(alloc, p->Defs); p->Defs = NULL;

+  IAlloc_Free(alloc, p->Vals); p->Vals = NULL;

 }

 

-#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }

+#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }

 

 void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)

 {

-  IAlloc_Free(alloc, p->Defs); p->Defs = 0;

-  IAlloc_Free(alloc, p->Vals); p->Vals = 0;

+  IAlloc_Free(alloc, p->Defs); p->Defs = NULL;

+  IAlloc_Free(alloc, p->Vals); p->Vals = NULL;

 }

 

+

 static void SzAr_Init(CSzAr *p)

 {

   p->NumPackStreams = 0;

   p->NumFolders = 0;

-  p->PackPositions = 0;

+  

+  p->PackPositions = NULL;

   SzBitUi32s_Init(&p->FolderCRCs);

-  // p->Folders = 0;

-  p->FoCodersOffsets = 0;

-  p->FoSizesOffsets = 0;

-  p->FoStartPackStreamIndex = 0;

 

-  p->CodersData = 0;

-  // p->CoderUnpackSizes = 0;

-  p->UnpackSizesData = 0;

+  p->FoCodersOffsets = NULL;

+  p->FoStartPackStreamIndex = NULL;

+  p->FoToCoderUnpackSizes = NULL;

+  p->FoToMainUnpackSizeIndex = NULL;

+  p->CoderUnpackSizes = NULL;

+

+  p->CodersData = NULL;

 }

 

 static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)

 {

-  IAlloc_Free(alloc, p->UnpackSizesData);

-  IAlloc_Free(alloc, p->CodersData);

-  // IAlloc_Free(alloc, p->CoderUnpackSizes);

-

   IAlloc_Free(alloc, p->PackPositions);

- 

-  // IAlloc_Free(alloc, p->Folders);

-  IAlloc_Free(alloc, p->FoCodersOffsets);

-  IAlloc_Free(alloc, p->FoSizesOffsets);

-  IAlloc_Free(alloc, p->FoStartPackStreamIndex);

-  

   SzBitUi32s_Free(&p->FolderCRCs, alloc);

+ 

+  IAlloc_Free(alloc, p->FoCodersOffsets);

+  IAlloc_Free(alloc, p->FoStartPackStreamIndex);

+  IAlloc_Free(alloc, p->FoToCoderUnpackSizes);

+  IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);

+  IAlloc_Free(alloc, p->CoderUnpackSizes);

+  

+  IAlloc_Free(alloc, p->CodersData);

 

   SzAr_Init(p);

 }

@@ -125,18 +127,19 @@
 void SzArEx_Init(CSzArEx *p)

 {

   SzAr_Init(&p->db);

+  

   p->NumFiles = 0;

   p->dataPos = 0;

-  // p->Files = 0;

-  p->UnpackPositions = 0;

-  // p->IsEmptyFiles = 0;

-  p->IsDirs = 0;

-  // p->FolderStartPackStreamIndex = 0;

-  // p->PackStreamStartPositions = 0;

-  p->FolderStartFileIndex = 0;

-  p->FileIndexToFolderIndexMap = 0;

-  p->FileNameOffsets = 0;

-  p->FileNames = 0;

+  

+  p->UnpackPositions = NULL;

+  p->IsDirs = NULL;

+  

+  p->FolderToFile = NULL;

+  p->FileToFolder = NULL;

+  

+  p->FileNameOffsets = NULL;

+  p->FileNames = NULL;

+  

   SzBitUi32s_Init(&p->CRCs);

   SzBitUi32s_Init(&p->Attribs);

   // SzBitUi32s_Init(&p->Parents);

@@ -146,47 +149,36 @@
 

 void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)

 {

-  // IAlloc_Free(alloc, p->FolderStartPackStreamIndex);

-  // IAlloc_Free(alloc, p->PackStreamStartPositions);

-  IAlloc_Free(alloc, p->FolderStartFileIndex);

-  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);

+  IAlloc_Free(alloc, p->UnpackPositions);

+  IAlloc_Free(alloc, p->IsDirs);

+

+  IAlloc_Free(alloc, p->FolderToFile);

+  IAlloc_Free(alloc, p->FileToFolder);

 

   IAlloc_Free(alloc, p->FileNameOffsets);

   IAlloc_Free(alloc, p->FileNames);

 

-  SzBitUi64s_Free(&p->CTime, alloc);

-  SzBitUi64s_Free(&p->MTime, alloc);

   SzBitUi32s_Free(&p->CRCs, alloc);

-  // SzBitUi32s_Free(&p->Parents, alloc);

   SzBitUi32s_Free(&p->Attribs, alloc);

-  IAlloc_Free(alloc, p->IsDirs);

-  // IAlloc_Free(alloc, p->IsEmptyFiles);

-  IAlloc_Free(alloc, p->UnpackPositions);

-  // IAlloc_Free(alloc, p->Files);

-

+  // SzBitUi32s_Free(&p->Parents, alloc);

+  SzBitUi64s_Free(&p->MTime, alloc);

+  SzBitUi64s_Free(&p->CTime, alloc);

+  

   SzAr_Free(&p->db, alloc);

   SzArEx_Init(p);

 }

 

-static int TestSignatureCandidate(Byte *testBytes)

+

+static int TestSignatureCandidate(const Byte *testBytes)

 {

-  size_t i;

+  unsigned i;

   for (i = 0; i < k7zSignatureSize; i++)

     if (testBytes[i] != k7zSignature[i])

       return 0;

   return 1;

 }

 

-#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; }

-

-static SRes SzReadByte(CSzData *sd, Byte *b)

-{

-  if (sd->Size == 0)

-    return SZ_ERROR_ARCHIVE;

-  sd->Size--;

-  *b = *sd->Data++;

-  return SZ_OK;

-}

+#define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; }

 

 #define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++;

 #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)

@@ -224,7 +216,7 @@
     Byte b;

     if ((firstByte & mask) == 0)

     {

-      UInt64 highPart = firstByte & (mask - 1);

+      UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);

       *value |= (highPart << (8 * i));

       return SZ_OK;

     }

@@ -235,57 +227,6 @@
   return SZ_OK;

 }

 

-/*

-static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num)

-{

-  for (; num != 0; num--)

-  {

-    Byte firstByte;

-    Byte mask;

-

-    unsigned i;

-    UInt32 v;

-    UInt64 value;

-   

-    if (data == dataLim)

-      return NULL;

-    firstByte = *data++;

-

-    if ((firstByte & 0x80) == 0)

-    {

-      *values++ = firstByte;

-      continue;

-    }

-    if (data == dataLim)

-      return NULL;

-    v = *data++;

-    if ((firstByte & 0x40) == 0)

-    {

-      *values++ = (((UInt32)firstByte & 0x3F) << 8) | v;

-      continue;

-    }

-    if (data == dataLim)

-      return NULL;

-    value = v | ((UInt32)*data++ << 8);

-    mask = 0x20;

-    for (i = 2; i < 8; i++)

-    {

-      if ((firstByte & mask) == 0)

-      {

-        UInt64 highPart = firstByte & (mask - 1);

-        value |= (highPart << (8 * i));

-        break;

-      }

-      if (data == dataLim)

-        return NULL;

-      value |= ((UInt64)*data++ << (8 * i));

-      mask >>= 1;

-    }

-    *values++ = value;

-  }

-  return data;

-}

-*/

 

 static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)

 {

@@ -322,7 +263,7 @@
   return SZ_OK;

 }

 

-static SRes WaitId(CSzData *sd, UInt64 id)

+static SRes WaitId(CSzData *sd, UInt32 id)

 {

   for (;;)

   {

@@ -361,29 +302,29 @@
     m--;

     sum += ((b >> m) & 1);

   }

-  return sum ;

+  return sum;

 }

 

 static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)

 {

   Byte allAreDefined;

-  UInt32 i;

   Byte *v2;

   UInt32 numBytes = (numItems + 7) >> 3;

-  RINOK(SzReadByte(sd, &allAreDefined));

+  *v = NULL;

+  SZ_READ_BYTE(allAreDefined);

+  if (numBytes == 0)

+    return SZ_OK;

   if (allAreDefined == 0)

   {

     if (numBytes > sd->Size)

       return SZ_ERROR_ARCHIVE;

-    MY_ALLOC(Byte, *v, numBytes, alloc);

-    memcpy(*v, sd->Data, numBytes);

+    MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc);

     SKIP_DATA(sd, numBytes);

     return SZ_OK;

   }

   MY_ALLOC(Byte, *v, numBytes, alloc);

   v2 = *v;

-  for (i = 0; i < numBytes; i++)

-    v2[i] = 0xFF;

+  memset(v2, 0xFF, (size_t)numBytes);

   {

     unsigned numBits = (unsigned)numItems & 7;

     if (numBits != 0)

@@ -398,7 +339,7 @@
   CSzData sd;

   UInt32 *vals;

   const Byte *defs;

-  MY_ALLOC(UInt32, crcs->Vals, numItems, alloc);

+  MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc);

   sd = *sd2;

   defs = crcs->Defs;

   vals = crcs->Vals;

@@ -424,7 +365,7 @@
 {

   Byte allAreDefined;

   UInt32 numDefined = numItems;

-  RINOK(SzReadByte(sd, &allAreDefined));

+  SZ_READ_BYTE(allAreDefined);

   if (!allAreDefined)

   {

     size_t numBytes = (numItems + 7) >> 3;

@@ -486,19 +427,22 @@
 }

 */

 

-#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16

+#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)

 

-SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)

+SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)

 {

-  UInt32 numCoders, numBindPairs, numPackStreams, i;

-  UInt32 numInStreams = 0, numOutStreams = 0;

+  UInt32 numCoders, i;

+  UInt32 numInStreams = 0;

   const Byte *dataStart = sd->Data;

-  Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX];

+

+  f->NumCoders = 0;

+  f->NumBonds = 0;

+  f->NumPackStreams = 0;

+  f->UnpackStream = 0;

   

   RINOK(SzReadNumber32(sd, &numCoders));

-  if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)

+  if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)

     return SZ_ERROR_UNSUPPORTED;

-  f->NumCoders = numCoders;

   

   for (i = 0; i < numCoders; i++)

   {

@@ -506,9 +450,11 @@
     CSzCoderInfo *coder = f->Coders + i;

     unsigned idSize, j;

     UInt64 id;

-    RINOK(SzReadByte(sd, &mainByte));

+    

+    SZ_READ_BYTE(mainByte);

     if ((mainByte & 0xC0) != 0)

       return SZ_ERROR_UNSUPPORTED;

+    

     idSize = (unsigned)(mainByte & 0xF);

     if (idSize > sizeof(id))

       return SZ_ERROR_UNSUPPORTED;

@@ -525,109 +471,131 @@
       return SZ_ERROR_UNSUPPORTED;

     coder->MethodID = (UInt32)id;

     

-    coder->NumInStreams = 1;

-    coder->NumOutStreams = 1;

+    coder->NumStreams = 1;

     coder->PropsOffset = 0;

     coder->PropsSize = 0;

     

     if ((mainByte & 0x10) != 0)

     {

       UInt32 numStreams;

+      

       RINOK(SzReadNumber32(sd, &numStreams));

-      if (numStreams > NUM_CODER_STREAMS_MAX)

+      if (numStreams > k_NumCodersStreams_in_Folder_MAX)

         return SZ_ERROR_UNSUPPORTED;

-      coder->NumInStreams = (Byte)numStreams;

+      coder->NumStreams = (Byte)numStreams;

+

       RINOK(SzReadNumber32(sd, &numStreams));

-      if (numStreams > NUM_CODER_STREAMS_MAX)

+      if (numStreams != 1)

         return SZ_ERROR_UNSUPPORTED;

-      coder->NumOutStreams = (Byte)numStreams;

     }

+

+    numInStreams += coder->NumStreams;

+

+    if (numInStreams > k_NumCodersStreams_in_Folder_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+

     if ((mainByte & 0x20) != 0)

     {

       UInt32 propsSize = 0;

       RINOK(SzReadNumber32(sd, &propsSize));

-      if (propsSize >= 0x40)

-        return SZ_ERROR_UNSUPPORTED;

       if (propsSize > sd->Size)

         return SZ_ERROR_ARCHIVE;

+      if (propsSize >= 0x80)

+        return SZ_ERROR_UNSUPPORTED;

       coder->PropsOffset = sd->Data - dataStart;

       coder->PropsSize = (Byte)propsSize;

       sd->Data += (size_t)propsSize;

       sd->Size -= (size_t)propsSize;

     }

-    numInStreams += coder->NumInStreams;

-    numOutStreams += coder->NumOutStreams;

   }

 

-  if (numOutStreams == 0)

-    return SZ_ERROR_UNSUPPORTED;

-

-  f->NumBindPairs = numBindPairs = numOutStreams - 1;

-  if (numInStreams < numBindPairs)

-    return SZ_ERROR_ARCHIVE;

-  if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX)

-    return SZ_ERROR_UNSUPPORTED;

-  f->MainOutStream = 0;

-  f->NumPackStreams = numPackStreams = numInStreams - numBindPairs;

-  if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)

-    return SZ_ERROR_UNSUPPORTED;

-  for (i = 0; i < numInStreams; i++)

-    inStreamUsed[i] = False;

-  if (numBindPairs != 0)

+  /*

+  if (numInStreams == 1 && numCoders == 1)

   {

-    Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];

-

-    if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX)

-      return SZ_ERROR_UNSUPPORTED;

-

-    for (i = 0; i < numOutStreams; i++)

-      outStreamUsed[i] = False;

-

-    for (i = 0; i < numBindPairs; i++)

-    {

-      CSzBindPair *bp = f->BindPairs + i;

-      RINOK(SzReadNumber32(sd, &bp->InIndex));

-      if (bp->InIndex >= numInStreams)

-        return SZ_ERROR_ARCHIVE;

-      inStreamUsed[bp->InIndex] = True;

-      RINOK(SzReadNumber32(sd, &bp->OutIndex));

-      if (bp->OutIndex >= numInStreams)

-        return SZ_ERROR_ARCHIVE;

-      outStreamUsed[bp->OutIndex] = True;

-    }

-    for (i = 0; i < numOutStreams; i++)

-      if (!outStreamUsed[i])

-      {

-        f->MainOutStream = i;

-        break;

-      }

-    if (i == numOutStreams)

-      return SZ_ERROR_ARCHIVE;

-  }

-

-  if (numPackStreams == 1)

-  {

-    for (i = 0; i < numInStreams; i++)

-      if (!inStreamUsed[i])

-        break;

-    if (i == numInStreams)

-      return SZ_ERROR_ARCHIVE;

-    f->PackStreams[0] = i;

+    f->NumPackStreams = 1;

+    f->PackStreams[0] = 0;

   }

   else

-    for (i = 0; i < numPackStreams; i++)

-    {

-      RINOK(SzReadNumber32(sd, f->PackStreams + i));

-    }

-

-  for (i = 0; i < numOutStreams; i++)

+  */

   {

-    RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i));

-  }

+    Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];

+    UInt32 numBonds, numPackStreams;

+    

+    numBonds = numCoders - 1;

+    if (numInStreams < numBonds)

+      return SZ_ERROR_ARCHIVE;

+    if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+    f->NumBonds = numBonds;

+    

+    numPackStreams = numInStreams - numBonds;

+    if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+    f->NumPackStreams = numPackStreams;

   

+    for (i = 0; i < numInStreams; i++)

+      streamUsed[i] = False;

+    

+    if (numBonds != 0)

+    {

+      Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];

+

+      for (i = 0; i < numCoders; i++)

+        coderUsed[i] = False;

+      

+      for (i = 0; i < numBonds; i++)

+      {

+        CSzBond *bp = f->Bonds + i;

+        

+        RINOK(SzReadNumber32(sd, &bp->InIndex));

+        if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])

+          return SZ_ERROR_ARCHIVE;

+        streamUsed[bp->InIndex] = True;

+        

+        RINOK(SzReadNumber32(sd, &bp->OutIndex));

+        if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])

+          return SZ_ERROR_ARCHIVE;

+        coderUsed[bp->OutIndex] = True;

+      }

+      

+      for (i = 0; i < numCoders; i++)

+        if (!coderUsed[i])

+        {

+          f->UnpackStream = i;

+          break;

+        }

+      

+      if (i == numCoders)

+        return SZ_ERROR_ARCHIVE;

+    }

+    

+    if (numPackStreams == 1)

+    {

+      for (i = 0; i < numInStreams; i++)

+        if (!streamUsed[i])

+          break;

+      if (i == numInStreams)

+        return SZ_ERROR_ARCHIVE;

+      f->PackStreams[0] = i;

+    }

+    else

+      for (i = 0; i < numPackStreams; i++)

+      {

+        UInt32 index;

+        RINOK(SzReadNumber32(sd, &index));

+        if (index >= numInStreams || streamUsed[index])

+          return SZ_ERROR_ARCHIVE;

+        streamUsed[index] = True;

+        f->PackStreams[i] = index;

+      }

+  }

+

+  f->NumCoders = numCoders;

+

   return SZ_OK;

 }

 

+

 static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)

 {

   CSzData sd;

@@ -658,24 +626,27 @@
   return SZ_OK;

 }

 

-#define k_InStreamUsed_MAX 64

-#define k_OutStreamUsed_MAX 64

+

+#define k_Scan_NumCoders_MAX 64

+#define k_Scan_NumCodersStreams_in_Folder_MAX 64

+

 

 static SRes ReadUnpackInfo(CSzAr *p,

     CSzData *sd2,

-    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,

+    UInt32 numFoldersMax,

+    const CBuf *tempBufs, UInt32 numTempBufs,

     ISzAlloc *alloc)

 {

   CSzData sd;

-  Byte inStreamUsed[k_InStreamUsed_MAX];

-  Byte outStreamUsed[k_OutStreamUsed_MAX];

+  

   UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;

   const Byte *startBufPtr;

   Byte external;

   

   RINOK(WaitId(sd2, k7zIdFolder));

+  

   RINOK(SzReadNumber32(sd2, &numFolders));

-  if (p->NumFolders > numFoldersMax)

+  if (numFolders > numFoldersMax)

     return SZ_ERROR_UNSUPPORTED;

   p->NumFolders = numFolders;

 

@@ -685,7 +656,7 @@
   else

   {

     UInt32 index;

-    SzReadNumber32(sd2, &index);

+    RINOK(SzReadNumber32(sd2, &index));

     if (index >= numTempBufs)

       return SZ_ERROR_ARCHIVE;

     sd.Data = tempBufs[index].data;

@@ -693,8 +664,9 @@
   }

   

   MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);

-  MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc);

   MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);

+  MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc);

+  MY_ALLOC(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc);

   

   startBufPtr = sd.Data;

   

@@ -703,18 +675,19 @@
 

   for (fo = 0; fo < numFolders; fo++)

   {

-    UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0;

+    UInt32 numCoders, ci, numInStreams = 0;

     

     p->FoCodersOffsets[fo] = sd.Data - startBufPtr;

+    

     RINOK(SzReadNumber32(&sd, &numCoders));

-    if (numCoders > NUM_FOLDER_CODERS_MAX)

+    if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)

       return SZ_ERROR_UNSUPPORTED;

     

     for (ci = 0; ci < numCoders; ci++)

     {

       Byte mainByte;

       unsigned idSize;

-      UInt32 coderInStreams, coderOutStreams;

+      UInt32 coderInStreams;

       

       SZ_READ_BYTE_2(mainByte);

       if ((mainByte & 0xC0) != 0)

@@ -727,17 +700,18 @@
       SKIP_DATA2(sd, idSize);

       

       coderInStreams = 1;

-      coderOutStreams = 1;

+      

       if ((mainByte & 0x10) != 0)

       {

+        UInt32 coderOutStreams;

         RINOK(SzReadNumber32(&sd, &coderInStreams));

         RINOK(SzReadNumber32(&sd, &coderOutStreams));

-        if (coderInStreams > NUM_CODER_STREAMS_MAX ||

-            coderOutStreams > NUM_CODER_STREAMS_MAX)

+        if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)

           return SZ_ERROR_UNSUPPORTED;

       }

+      

       numInStreams += coderInStreams;

-      numOutStreams += coderOutStreams;

+

       if ((mainByte & 0x20) != 0)

       {

         UInt32 propsSize;

@@ -751,75 +725,82 @@
     {

       UInt32 indexOfMainStream = 0;

       UInt32 numPackStreams = 1;

-      if (numOutStreams != 1 || numInStreams != 1)

+      

+      if (numCoders != 1 || numInStreams != 1)

       {

+        Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];

+        Byte coderUsed[k_Scan_NumCoders_MAX];

+    

         UInt32 i;

-        UInt32 numBindPairs = numOutStreams - 1;

-        if (numOutStreams == 0 || numInStreams < numBindPairs)

+        UInt32 numBonds = numCoders - 1;

+        if (numInStreams < numBonds)

           return SZ_ERROR_ARCHIVE;

         

-        if (numInStreams > k_InStreamUsed_MAX ||

-            numOutStreams > k_OutStreamUsed_MAX)

+        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)

           return SZ_ERROR_UNSUPPORTED;

         

         for (i = 0; i < numInStreams; i++)

-          inStreamUsed[i] = False;

-        for (i = 0; i < numOutStreams; i++)

-          outStreamUsed[i] = False;

+          streamUsed[i] = False;

+        for (i = 0; i < numCoders; i++)

+          coderUsed[i] = False;

         

-        for (i = 0; i < numBindPairs; i++)

+        for (i = 0; i < numBonds; i++)

         {

           UInt32 index;

+          

           RINOK(SzReadNumber32(&sd, &index));

-          if (index >= numInStreams || inStreamUsed[index])

+          if (index >= numInStreams || streamUsed[index])

             return SZ_ERROR_ARCHIVE;

-          inStreamUsed[index] = True;

+          streamUsed[index] = True;

+          

           RINOK(SzReadNumber32(&sd, &index));

-          if (index >= numInStreams || outStreamUsed[index])

+          if (index >= numCoders || coderUsed[index])

             return SZ_ERROR_ARCHIVE;

-          outStreamUsed[index] = True;

+          coderUsed[index] = True;

         }

         

-        numPackStreams = numInStreams - numBindPairs;

+        numPackStreams = numInStreams - numBonds;

         

         if (numPackStreams != 1)

           for (i = 0; i < numPackStreams; i++)

           {

-            UInt32 temp;

-            RINOK(SzReadNumber32(&sd, &temp));

-            if (temp >= numInStreams)

+            UInt32 index;

+            RINOK(SzReadNumber32(&sd, &index));

+            if (index >= numInStreams || streamUsed[index])

               return SZ_ERROR_ARCHIVE;

+            streamUsed[index] = True;

           }

           

-        for (i = 0; i < numOutStreams; i++)

-          if (!outStreamUsed[i])

+        for (i = 0; i < numCoders; i++)

+          if (!coderUsed[i])

           {

             indexOfMainStream = i;

             break;

           }

  

-        if (i == numOutStreams)

+        if (i == numCoders)

           return SZ_ERROR_ARCHIVE;

       }

+      

       p->FoStartPackStreamIndex[fo] = packStreamIndex;

-      p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream;

-      numCodersOutStreams += numOutStreams;

-      if (numCodersOutStreams < numOutStreams)

+      p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;

+      p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;

+      numCodersOutStreams += numCoders;

+      if (numCodersOutStreams < numCoders)

         return SZ_ERROR_UNSUPPORTED;

-      packStreamIndex += numPackStreams;

-      if (packStreamIndex < numPackStreams)

-        return SZ_ERROR_UNSUPPORTED;

-      if (packStreamIndex > p->NumPackStreams)

+      if (numPackStreams > p->NumPackStreams - packStreamIndex)

         return SZ_ERROR_ARCHIVE;

+      packStreamIndex += numPackStreams;

     }

   }

+

+  p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;

   

   {

     size_t dataSize = sd.Data - startBufPtr;

     p->FoStartPackStreamIndex[fo] = packStreamIndex;

     p->FoCodersOffsets[fo] = dataSize;

-    MY_ALLOC(Byte, p->CodersData, dataSize, alloc);

-    memcpy(p->CodersData, startBufPtr, dataSize);

+    MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);

   }

   

   if (external != 0)

@@ -831,28 +812,13 @@
   

   RINOK(WaitId(&sd, k7zIdCodersUnpackSize));

   

-  // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);

+  MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);

   {

-    size_t dataSize = sd.Size;

-    /*

     UInt32 i;

     for (i = 0; i < numCodersOutStreams; i++)

     {

-    RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));

+      RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));

     }

-    */

-    RINOK(SkipNumbers(&sd, numCodersOutStreams));

-    dataSize -= sd.Size;

-    MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc);

-    memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize);

-    p->UnpackSizesDataSize = dataSize;

-    /*

-    const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams);

-    if (data == NULL)

-    return SZ_ERROR_ARCHIVE;

-    sd.Size = sd.Data + sd.Size - data;

-    sd.Data = data;

-    */

   }

 

   for (;;)

@@ -873,6 +839,13 @@
   }

 }

 

+

+UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)

+{

+  return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];

+}

+

+

 typedef struct

 {

   UInt32 NumTotalSubStreams;

@@ -882,12 +855,10 @@
   CSzData sdCRCs;

 } CSubStreamInfo;

 

-#define SzUi32IndexMax (((UInt32)1 << 31) - 2)

 

 static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)

 {

   UInt64 type = 0;

-  UInt32 i;

   UInt32 numSubDigests = 0;

   UInt32 numFolders = p->NumFolders;

   UInt32 numUnpackStreams = numFolders;

@@ -898,6 +869,7 @@
     RINOK(ReadID(sd, &type));

     if (type == k7zIdNumUnpackStream)

     {

+      UInt32 i;

       ssi->sdNumSubStreams.Data = sd->Data;

       numUnpackStreams = 0;

       numSubDigests = 0;

@@ -1009,7 +981,6 @@
   UInt64 dataStartPos;

   UInt32 fo;

   CSubStreamInfo ssi;

-  CSzData sdCodersUnpSizes;

 

   RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));

   

@@ -1017,49 +988,26 @@
   if (p->NumFolders == 0)

     return SZ_ERROR_ARCHIVE;

  

-  sdCodersUnpSizes.Data = p->UnpackSizesData;

-  sdCodersUnpSizes.Size = p->UnpackSizesDataSize;

   for (fo = 0; fo < p->NumFolders; fo++)

     Buf_Init(tempBufs + fo);

+  

   for (fo = 0; fo < p->NumFolders; fo++)

   {

     CBuf *tempBuf = tempBufs + fo;

-    // folder = p->Folders;

-    // unpackSize = SzAr_GetFolderUnpackSize(p, 0);

-    UInt32 mix = (UInt32)p->FoSizesOffsets[fo];

-    UInt32 mainIndex = mix & 0xFF;

-    UInt32 numOutStreams = mix >> 8;

-    UInt32 si;

-    UInt64 unpackSize = 0;

-    p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;

-    for (si = 0; si < numOutStreams; si++)

-    {

-      UInt64 curSize;

-      RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));

-      if (si == mainIndex)

-      {

-        unpackSize = curSize;

-        break;

-      }

-    }

-    if (si == numOutStreams)

-      return SZ_ERROR_FAIL;

+    UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);

     if ((size_t)unpackSize != unpackSize)

       return SZ_ERROR_MEM;

     if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))

       return SZ_ERROR_MEM;

   }

-  p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;

-    

+  

   for (fo = 0; fo < p->NumFolders; fo++)

   {

     const CBuf *tempBuf = tempBufs + fo;

     RINOK(LookInStream_SeekTo(inStream, dataStartPos));

     RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));

-    if (SzBitWithVals_Check(&p->FolderCRCs, fo))

-      if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo])

-        return SZ_ERROR_CRC;

   }

+  

   return SZ_OK;

 }

 

@@ -1069,6 +1017,8 @@
   *offsets++ = 0;

   if (numFiles == 0)

     return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;

+  if (size < 2)

+    return SZ_ERROR_ARCHIVE;

   if (data[size - 2] != 0 || data[size - 1] != 0)

     return SZ_ERROR_ARCHIVE;

   do

@@ -1100,20 +1050,23 @@
   CNtfsFileTime *vals;

   Byte *defs;

   Byte external;

+  

   RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));

-  RINOK(SzReadByte(sd2, &external));

+  

+  SZ_READ_BYTE_SD(sd2, external);

   if (external == 0)

     sd = *sd2;

   else

   {

     UInt32 index;

-    SzReadNumber32(sd2, &index);

+    RINOK(SzReadNumber32(sd2, &index));

     if (index >= numTempBufs)

       return SZ_ERROR_ARCHIVE;

     sd.Data = tempBufs[index].data;

     sd.Size = tempBufs[index].size;

   }

-  MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc);

+  

+  MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc);

   vals = p->Vals;

   defs = p->Defs;

   for (i = 0; i < num; i++)

@@ -1127,34 +1080,31 @@
     }

     else

       vals[i].High = vals[i].Low = 0;

+  

   if (external == 0)

     *sd2 = sd;

+  

   return SZ_OK;

 }

 

+

 #define NUM_ADDITIONAL_STREAMS_MAX 8

 

+

 static SRes SzReadHeader2(

     CSzArEx *p,   /* allocMain */

     CSzData *sd,

-    // Byte **emptyStreamVector, /* allocTemp */

-    // Byte **emptyFileVector,   /* allocTemp */

-    // Byte **lwtVector,         /* allocTemp */

     ILookInStream *inStream,

-    CBuf *tempBufs,

-    UInt32 *numTempBufs,

+    CBuf *tempBufs, UInt32 *numTempBufs,

     ISzAlloc *allocMain,

     ISzAlloc *allocTemp

     )

 {

-  UInt64 type;

-  UInt32 numFiles = 0;

-  UInt32 numEmptyStreams = 0;

-  UInt32 i;

   CSubStreamInfo ssi;

-  const Byte *emptyStreams = 0;

-  const Byte *emptyFiles = 0;

 

+{

+  UInt64 type;

+  

   SzData_Clear(&ssi.sdSizes);

   SzData_Clear(&ssi.sdCRCs);

   SzData_Clear(&ssi.sdNumSubStreams);

@@ -1168,31 +1118,28 @@
   {

     for (;;)

     {

-      UInt64 type;

-      RINOK(ReadID(sd, &type));

-      if (type == k7zIdEnd)

+      UInt64 type2;

+      RINOK(ReadID(sd, &type2));

+      if (type2 == k7zIdEnd)

         break;

       RINOK(SkipData(sd));

     }

     RINOK(ReadID(sd, &type));

   }

 

-  // if (type == k7zIdAdditionalStreamsInfo)     return SZ_ERROR_UNSUPPORTED;

-

   if (type == k7zIdAdditionalStreamsInfo)

   {

     CSzAr tempAr;

     SRes res;

-    UInt32 numTempFolders;

     

     SzAr_Init(&tempAr);

     res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,

         p->startPosAfterHeader, &tempAr, allocTemp);

-    numTempFolders = tempAr.NumFolders;

+    *numTempBufs = tempAr.NumFolders;

     SzAr_Free(&tempAr, allocTemp);

+    

     if (res != SZ_OK)

       return res;

-    *numTempBufs = numTempFolders;

     RINOK(ReadID(sd, &type));

   }

 

@@ -1206,11 +1153,18 @@
 

   if (type == k7zIdEnd)

   {

-    // *sd2 = sd;

     return SZ_OK;

   }

+

   if (type != k7zIdFilesInfo)

     return SZ_ERROR_ARCHIVE;

+}

+

+{

+  UInt32 numFiles = 0;

+  UInt32 numEmptyStreams = 0;

+  const Byte *emptyStreams = NULL;

+  const Byte *emptyFiles = NULL;

   

   RINOK(SzReadNumber32(sd, &numFiles));

   p->NumFiles = numFiles;

@@ -1225,11 +1179,12 @@
     RINOK(ReadNumber(sd, &size));

     if (size > sd->Size)

       return SZ_ERROR_ARCHIVE;

-    if ((UInt64)(int)type != type)

+    

+    if (type >= ((UInt32)1 << 8))

     {

       SKIP_DATA(sd, size);

     }

-    else switch((int)type)

+    else switch ((unsigned)type)

     {

       case k7zIdName:

       {

@@ -1246,7 +1201,7 @@
         else

         {

           UInt32 index;

-          SzReadNumber32(sd, &index);

+          RINOK(SzReadNumber32(sd, &index));

           if (index >= *numTempBufs)

             return SZ_ERROR_ARCHIVE;

           namesData = (tempBufs)[index].data;

@@ -1255,9 +1210,8 @@
 

         if ((namesSize & 1) != 0)

           return SZ_ERROR_ARCHIVE;

-        MY_ALLOC(Byte, p->FileNames, namesSize, allocMain);

         MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);

-        memcpy(p->FileNames, namesData, namesSize);

+        MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);

         RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))

         if (external == 0)

         {

@@ -1269,6 +1223,7 @@
       {

         RINOK(RememberBitVector(sd, numFiles, &emptyStreams));

         numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);

+        emptyFiles = NULL;

         break;

       }

       case k7zIdEmptyFile:

@@ -1290,7 +1245,7 @@
         else

         {

           UInt32 index;

-          SzReadNumber32(sd, &index);

+          RINOK(SzReadNumber32(sd, &index));

           if (index >= *numTempBufs)

             return SZ_ERROR_ARCHIVE;

           sdSwitch.Data = (tempBufs)[index].data;

@@ -1332,35 +1287,31 @@
   }

 

   {

+    UInt32 i;

     UInt32 emptyFileIndex = 0;

-

     UInt32 folderIndex = 0;

-    UInt32 indexInFolder = 0;

+    UInt32 remSubStreams = 0;

+    UInt32 numSubStreams = 0;

     UInt64 unpackPos = 0;

-    const Byte *digestsDefs = 0;

-    const Byte *digestsVals = 0;

+    const Byte *digestsDefs = NULL;

+    const Byte *digestsVals = NULL;

     UInt32 digestsValsIndex = 0;

     UInt32 digestIndex;

     Byte allDigestsDefined = 0;

-    UInt32 curNumSubStreams = (UInt32)(Int32)-1;

     Byte isDirMask = 0;

     Byte crcMask = 0;

     Byte mask = 0x80;

-    // size_t unpSizesOffset = 0;

-    CSzData sdCodersUnpSizes;

-    sdCodersUnpSizes.Data = p->db.UnpackSizesData;

-    sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize;

     

-    MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain);

-    MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain);

+    MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain);

+    MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain);

     MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);

-    MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);

+    MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);

 

     RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));

 

     if (ssi.sdCRCs.Size != 0)

     {

-      RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined));

+      SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);

       if (allDigestsDefined)

         digestsVals = ssi.sdCRCs.Data;

       else

@@ -1372,6 +1323,7 @@
     }

 

     digestIndex = 0;

+    

     for (i = 0; i < numFiles; i++, mask >>= 1)

     {

       if (mask == 0)

@@ -1386,79 +1338,66 @@
 

       p->UnpackPositions[i] = unpackPos;

       p->CRCs.Vals[i] = 0;

-      // p->CRCs.Defs[i] = 0;

-      if (emptyStreams && SzBitArray_Check(emptyStreams , i))

+      

+      if (emptyStreams && SzBitArray_Check(emptyStreams, i))

       {

-        if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex))

-          isDirMask |= mask;

-        emptyFileIndex++;

-        if (indexInFolder == 0)

+        if (emptyFiles)

         {

-          p->FileIndexToFolderIndexMap[i] = (UInt32)-1;

+          if (!SzBitArray_Check(emptyFiles, emptyFileIndex))

+            isDirMask |= mask;

+          emptyFileIndex++;

+        }

+        else

+          isDirMask |= mask;

+        if (remSubStreams == 0)

+        {

+          p->FileToFolder[i] = (UInt32)-1;

           continue;

         }

       }

-      if (indexInFolder == 0)

+      

+      if (remSubStreams == 0)

       {

-        /*

-        v3.13 incorrectly worked with empty folders

-        v4.07: Loop for skipping empty folders

-        */

         for (;;)

         {

           if (folderIndex >= p->db.NumFolders)

             return SZ_ERROR_ARCHIVE;

-          p->FolderStartFileIndex[folderIndex] = i;

-          if (curNumSubStreams == (UInt32)(Int32)-1);

+          p->FolderToFile[folderIndex] = i;

+          numSubStreams = 1;

+          if (ssi.sdNumSubStreams.Data)

           {

-            curNumSubStreams = 1;

-            if (ssi.sdNumSubStreams.Data != 0)

-            {

-              RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams));

-            }

+            RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));

           }

-          if (curNumSubStreams != 0)

+          remSubStreams = numSubStreams;

+          if (numSubStreams != 0)

             break;

-          curNumSubStreams = (UInt32)(Int32)-1;

-          folderIndex++; // check it

+          {

+            UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+            unpackPos += folderUnpackSize;

+            if (unpackPos < folderUnpackSize)

+              return SZ_ERROR_ARCHIVE;

+          }

+

+          folderIndex++;

         }

       }

-      p->FileIndexToFolderIndexMap[i] = folderIndex;

-      if (emptyStreams && SzBitArray_Check(emptyStreams , i))

+      

+      p->FileToFolder[i] = folderIndex;

+      

+      if (emptyStreams && SzBitArray_Check(emptyStreams, i))

         continue;

       

-      indexInFolder++;

-      if (indexInFolder >= curNumSubStreams)

+      if (--remSubStreams == 0)

       {

-        UInt64 folderUnpackSize = 0;

-        UInt64 startFolderUnpackPos;

-        {

-          UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex];

-          UInt32 mainIndex = mix & 0xFF;

-          UInt32 numOutStreams = mix >> 8;

-          UInt32 si;

-          p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;

-          for (si = 0; si < numOutStreams; si++)

-          {

-            UInt64 curSize;

-            RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));

-            if (si == mainIndex)

-            {

-              folderUnpackSize = curSize;

-              break;

-            }

-          }

-          if (si == numOutStreams)

-            return SZ_ERROR_FAIL;

-        }

-

-        // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

-        startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];

+        UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+        UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];

         if (folderUnpackSize < unpackPos - startFolderUnpackPos)

           return SZ_ERROR_ARCHIVE;

         unpackPos = startFolderUnpackPos + folderUnpackSize;

+        if (unpackPos < folderUnpackSize)

+          return SZ_ERROR_ARCHIVE;

 

-        if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))

+        if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))

         {

           p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];

           crcMask |= mask;

@@ -1469,14 +1408,16 @@
           digestsValsIndex++;

           crcMask |= mask;

         }

+        

         folderIndex++;

-        indexInFolder = 0;

       }

       else

       {

         UInt64 v;

         RINOK(ReadNumber(&ssi.sdSizes, &v));

         unpackPos += v;

+        if (unpackPos < v)

+          return SZ_ERROR_ARCHIVE;

         if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))

         {

           p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);

@@ -1485,30 +1426,55 @@
         }

       }

     }

+

     if (mask != 0x80)

     {

       UInt32 byteIndex = (i - 1) >> 3;

       p->IsDirs[byteIndex] = isDirMask;

       p->CRCs.Defs[byteIndex] = crcMask;

     }

+    

     p->UnpackPositions[i] = unpackPos;

-    p->FolderStartFileIndex[folderIndex] = i;

-    p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;

+

+    if (remSubStreams != 0)

+      return SZ_ERROR_ARCHIVE;

+

+    for (;;)

+    {

+      p->FolderToFile[folderIndex] = i;

+      if (folderIndex >= p->db.NumFolders)

+        break;

+      if (!ssi.sdNumSubStreams.Data)

+        return SZ_ERROR_ARCHIVE;

+      RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));

+      if (numSubStreams != 0)

+        return SZ_ERROR_ARCHIVE;

+      /*

+      {

+        UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+        unpackPos += folderUnpackSize;

+        if (unpackPos < folderUnpackSize)

+          return SZ_ERROR_ARCHIVE;

+      }

+      */

+      folderIndex++;

+    }

+

+    if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)

+      return SZ_ERROR_ARCHIVE;

   }

+}

   return SZ_OK;

 }

 

+

 static SRes SzReadHeader(

     CSzArEx *p,

     CSzData *sd,

     ILookInStream *inStream,

-    ISzAlloc *allocMain

-    ,ISzAlloc *allocTemp

-    )

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

 {

-  // Byte *emptyStreamVector = 0;

-  // Byte *emptyFileVector = 0;

-  // Byte *lwtVector = 0;

   UInt32 i;

   UInt32 numTempBufs = 0;

   SRes res;

@@ -1516,55 +1482,22 @@
 

   for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)

     Buf_Init(tempBufs + i);

-  // SzBitUi32s_Init(&digests);

   

-  res = SzReadHeader2(p, sd,

-      // &emptyStreamVector,

-      // &emptyFileVector,

-      // &lwtVector,

-      inStream,

+  res = SzReadHeader2(p, sd, inStream,

       tempBufs, &numTempBufs,

-      allocMain, allocTemp

-      );

+      allocMain, allocTemp);

   

-  for (i = 0; i < numTempBufs; i++)

+  for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)

     Buf_Free(tempBufs + i, allocTemp);

 

-  // IAlloc_Free(allocTemp, emptyStreamVector);

-  // IAlloc_Free(allocTemp, emptyFileVector);

-  // IAlloc_Free(allocTemp, lwtVector);

-

   RINOK(res);

-  {

-    if (sd->Size != 0)

-      return SZ_ERROR_FAIL;

-  }

+

+  if (sd->Size != 0)

+    return SZ_ERROR_FAIL;

 

   return res;

 }

 

-/*

-static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)

-{

-  const CSzFolder2 *f = p->Folders + folderIndex;

-

-  // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream];

-

-  UInt32 si;

-  CSzData sdCodersUnpSizes;

-  sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset;

-  sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset;

-  for (si = 0; si < numOutStreams; si++)

-  {

-    UInt64 curSize;

-    ReadNumber(&sdCodersUnpSizes, &curSize);

-    if (si == mainIndex)

-      return curSize;

-  }

-  return 0;

-}

-*/

-

 static SRes SzArEx_Open2(

     CSzArEx *p,

     ILookInStream *inStream,

@@ -1622,6 +1555,7 @@
     return SZ_ERROR_MEM;

 

   res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);

+  

   if (res == SZ_OK)

   {

     res = SZ_ERROR_ARCHIVE;

@@ -1631,7 +1565,9 @@
       UInt64 type;

       sd.Data = buf.data;

       sd.Size = buf.size;

+      

       res = ReadID(&sd, &type);

+      

       if (res == SZ_OK && type == k7zIdEncodedHeader)

       {

         CSzAr tempAr;

@@ -1656,35 +1592,35 @@
           res = ReadID(&sd, &type);

         }

       }

+  

       if (res == SZ_OK)

       {

         if (type == k7zIdHeader)

         {

+          /*

           CSzData sd2;

-          int ttt;

-          for (ttt = 0; ttt < 1; ttt++)

-          // for (ttt = 0; ttt < 40000; ttt++)

+          unsigned ttt;

+          for (ttt = 0; ttt < 40000; ttt++)

           {

             SzArEx_Free(p, allocMain);

             sd2 = sd;

-            res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp

-              );

+            res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);

             if (res != SZ_OK)

               break;

           }

-

-          // res = SzReadHeader(p, &sd, allocMain, allocTemp);

+          */

+          res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);

         }

         else

           res = SZ_ERROR_UNSUPPORTED;

       }

     }

   }

+ 

   Buf_Free(&buf, allocTemp);

   return res;

 }

 

-// #include <stdio.h>

 

 SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,

     ISzAlloc *allocMain, ISzAlloc *allocTemp)

@@ -1692,10 +1628,10 @@
   SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);

   if (res != SZ_OK)

     SzArEx_Free(p, allocMain);

-  // printf ("\nrrr=%d\n", rrr);

   return res;

 }

 

+

 SRes SzArEx_Extract(

     const CSzArEx *p,

     ILookInStream *inStream,

@@ -1708,34 +1644,36 @@
     ISzAlloc *allocMain,

     ISzAlloc *allocTemp)

 {

-  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];

+  UInt32 folderIndex = p->FileToFolder[fileIndex];

   SRes res = SZ_OK;

+  

   *offset = 0;

   *outSizeProcessed = 0;

+  

   if (folderIndex == (UInt32)-1)

   {

     IAlloc_Free(allocMain, *tempBuf);

     *blockIndex = folderIndex;

-    *tempBuf = 0;

+    *tempBuf = NULL;

     *outBufferSize = 0;

     return SZ_OK;

   }

 

-  if (*tempBuf == 0 || *blockIndex != folderIndex)

+  if (*tempBuf == NULL || *blockIndex != folderIndex)

   {

-    // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+    UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+    /*

     UInt64 unpackSizeSpec =

-        p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] -

-        p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];

+        p->UnpackPositions[p->FolderToFile[folderIndex + 1]] -

+        p->UnpackPositions[p->FolderToFile[folderIndex]];

+    */

     size_t unpackSize = (size_t)unpackSizeSpec;

 

     if (unpackSize != unpackSizeSpec)

       return SZ_ERROR_MEM;

     *blockIndex = folderIndex;

     IAlloc_Free(allocMain, *tempBuf);

-    *tempBuf = 0;

-    

-    // RINOK(LookInStream_SeekTo(inStream, startOffset));

+    *tempBuf = NULL;

     

     if (res == SZ_OK)

     {

@@ -1743,36 +1681,30 @@
       if (unpackSize != 0)

       {

         *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize);

-        if (*tempBuf == 0)

+        if (*tempBuf == NULL)

           res = SZ_ERROR_MEM;

       }

+  

       if (res == SZ_OK)

       {

         res = SzAr_DecodeFolder(&p->db, folderIndex,

-          inStream,

-          p->dataPos,

-          *tempBuf, unpackSize, allocTemp);

-        if (res == SZ_OK)

-        {

-          if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))

-          {

-            if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex])

-              res = SZ_ERROR_CRC;

-          }

-        }

+            inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);

       }

     }

   }

+

   if (res == SZ_OK)

   {

     UInt64 unpackPos = p->UnpackPositions[fileIndex];

-    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]);

+    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);

     *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);

     if (*offset + *outSizeProcessed > *outBufferSize)

       return SZ_ERROR_FAIL;

-    if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])

-      res = SZ_ERROR_CRC;

+    if (SzBitWithVals_Check(&p->CRCs, fileIndex))

+      if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])

+        res = SZ_ERROR_CRC;

   }

+

   return res;

 }

 

diff --git a/C/7zBuf2.c b/C/7zBuf2.c
index 9633796..8e3fe92 100644
--- a/C/7zBuf2.c
+++ b/C/7zBuf2.c
@@ -1,5 +1,5 @@
 /* 7zBuf2.c -- Byte Buffer

-2013-11-12 : Igor Pavlov : Public domain */

+2014-08-22 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -34,8 +34,11 @@
     alloc->Free(alloc, p->data);

     p->data = data;

   }

-  memcpy(p->data + p->pos, buf, size);

-  p->pos += size;

+  if (size != 0)

+  {

+    memcpy(p->data + p->pos, buf, size);

+    p->pos += size;

+  }

   return 1;

 }

 

diff --git a/C/7zCrc.c b/C/7zCrc.c
index 161d4d1..607db34 100644
--- a/C/7zCrc.c
+++ b/C/7zCrc.c
@@ -1,5 +1,5 @@
 /* 7zCrc.c -- CRC32 init

-2013-11-12 : Igor Pavlov : Public domain */

+2015-03-10 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -8,24 +8,28 @@
 

 #define kCrcPoly 0xEDB88320

 

-#ifdef MY_CPU_X86_OR_AMD64

+#ifdef MY_CPU_LE

   #define CRC_NUM_TABLES 8

-  UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);

-#elif defined(MY_CPU_LE)

-  #define CRC_NUM_TABLES 4

 #else

-  #define CRC_NUM_TABLES 5

+  #define CRC_NUM_TABLES 9

+

   #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))

+

   UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);

+  UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);

 #endif

 

 #ifndef MY_CPU_BE

   UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);

+  UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);

 #endif

 

 typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);

 

+CRC_FUNC g_CrcUpdateT4;

+CRC_FUNC g_CrcUpdateT8;

 CRC_FUNC g_CrcUpdate;

+

 UInt32 g_CrcTable[256 * CRC_NUM_TABLES];

 

 UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)

@@ -38,6 +42,17 @@
   return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;

 }

 

+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

+UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)

+{

+  const Byte *p = (const Byte *)data;

+  const Byte *pEnd = p + size;

+  for (; p != pEnd; p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

 void MY_FAST_CALL CrcGenerateTable()

 {

   UInt32 i;

@@ -54,22 +69,43 @@
     UInt32 r = g_CrcTable[i - 256];

     g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);

   }

+

+  #if CRC_NUM_TABLES < 4

   

+  g_CrcUpdate = CrcUpdateT1;

+  

+  #else

+ 

   #ifdef MY_CPU_LE

 

-  g_CrcUpdate = CrcUpdateT4;

+    g_CrcUpdateT4 = CrcUpdateT4;

+    g_CrcUpdate = CrcUpdateT4;

+

+    #if CRC_NUM_TABLES >= 8

+      g_CrcUpdateT8 = CrcUpdateT8;

   

-  #if CRC_NUM_TABLES == 8

-  if (!CPU_Is_InOrder())

-    g_CrcUpdate = CrcUpdateT8;

-  #endif

+      #ifdef MY_CPU_X86_OR_AMD64

+      if (!CPU_Is_InOrder())

+        g_CrcUpdate = CrcUpdateT8;

+      #endif

+    #endif

 

   #else

   {

     #ifndef MY_CPU_BE

-    UInt32 k = 1;

-    if (*(const Byte *)&k == 1)

+    UInt32 k = 0x01020304;

+    const Byte *p = (const Byte *)&k;

+    if (p[0] == 4 && p[1] == 3)

+    {

+      g_CrcUpdateT4 = CrcUpdateT4;

       g_CrcUpdate = CrcUpdateT4;

+      #if CRC_NUM_TABLES >= 8

+      g_CrcUpdateT8 = CrcUpdateT8;

+      // g_CrcUpdate = CrcUpdateT8;

+      #endif

+    }

+    else if (p[0] != 1 || p[1] != 2)

+      g_CrcUpdate = CrcUpdateT1;

     else

     #endif

     {

@@ -78,8 +114,15 @@
         UInt32 x = g_CrcTable[i - 256];

         g_CrcTable[i] = CRC_UINT32_SWAP(x);

       }

+      g_CrcUpdateT4 = CrcUpdateT1_BeT4;

       g_CrcUpdate = CrcUpdateT1_BeT4;

+      #if CRC_NUM_TABLES >= 8

+      g_CrcUpdateT8 = CrcUpdateT1_BeT8;

+      // g_CrcUpdate = CrcUpdateT1_BeT8;

+      #endif

     }

   }

   #endif

+

+  #endif

 }

diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
index 48b0136..58628ef 100644
--- a/C/7zCrcOpt.c
+++ b/C/7zCrcOpt.c
@@ -1,14 +1,14 @@
 /* 7zCrcOpt.c -- CRC32 calculation

-2013-11-12 : Igor Pavlov : Public domain */

+2015-03-01 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

 #include "CpuArch.h"

 

-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

-

 #ifndef MY_CPU_BE

 

+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

 UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)

 {

   const Byte *p = (const Byte *)data;

@@ -18,10 +18,10 @@
   {

     v ^= *(const UInt32 *)p;

     v =

-      table[0x300 + (v & 0xFF)] ^

-      table[0x200 + ((v >> 8) & 0xFF)] ^

-      table[0x100 + ((v >> 16) & 0xFF)] ^

-      table[0x000 + ((v >> 24))];

+          table[0x300 + ((v      ) & 0xFF)]

+        ^ table[0x200 + ((v >>  8) & 0xFF)]

+        ^ table[0x100 + ((v >> 16) & 0xFF)]

+        ^ table[0x000 + ((v >> 24))];

   }

   for (; size > 0; size--, p++)

     v = CRC_UPDATE_BYTE_2(v, *p);

@@ -30,7 +30,28 @@
 

 UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)

 {

-  return CrcUpdateT4(v, data, size, table);

+  const Byte *p = (const Byte *)data;

+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  for (; size >= 8; size -= 8, p += 8)

+  {

+    UInt32 d;

+    v ^= *(const UInt32 *)p;

+    v =

+          table[0x700 + ((v      ) & 0xFF)]

+        ^ table[0x600 + ((v >>  8) & 0xFF)]

+        ^ table[0x500 + ((v >> 16) & 0xFF)]

+        ^ table[0x400 + ((v >> 24))];

+    d = *((const UInt32 *)p + 1);

+    v ^=

+          table[0x300 + ((d      ) & 0xFF)]

+        ^ table[0x200 + ((d >>  8) & 0xFF)]

+        ^ table[0x100 + ((d >> 16) & 0xFF)]

+        ^ table[0x000 + ((d >> 24))];

+  }

+  for (; size > 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

 }

 

 #endif

@@ -40,27 +61,55 @@
 

 #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))

 

+#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))

+

 UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)

 {

   const Byte *p = (const Byte *)data;

-  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)

-    v = CRC_UPDATE_BYTE_2(v, *p);

-  v = CRC_UINT32_SWAP(v);

   table += 0x100;

+  v = CRC_UINT32_SWAP(v);

+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

   for (; size >= 4; size -= 4, p += 4)

   {

     v ^= *(const UInt32 *)p;

     v =

-      table[0x000 + (v & 0xFF)] ^

-      table[0x100 + ((v >> 8) & 0xFF)] ^

-      table[0x200 + ((v >> 16) & 0xFF)] ^

-      table[0x300 + ((v >> 24))];

+          table[0x000 + ((v      ) & 0xFF)]

+        ^ table[0x100 + ((v >>  8) & 0xFF)]

+        ^ table[0x200 + ((v >> 16) & 0xFF)]

+        ^ table[0x300 + ((v >> 24))];

   }

-  table -= 0x100;

-  v = CRC_UINT32_SWAP(v);

   for (; size > 0; size--, p++)

-    v = CRC_UPDATE_BYTE_2(v, *p);

-  return v;

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

+  return CRC_UINT32_SWAP(v);

+}

+

+UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)

+{

+  const Byte *p = (const Byte *)data;

+  table += 0x100;

+  v = CRC_UINT32_SWAP(v);

+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

+  for (; size >= 8; size -= 8, p += 8)

+  {

+    UInt32 d;

+    v ^= *(const UInt32 *)p;

+    v =

+          table[0x400 + ((v      ) & 0xFF)]

+        ^ table[0x500 + ((v >>  8) & 0xFF)]

+        ^ table[0x600 + ((v >> 16) & 0xFF)]

+        ^ table[0x700 + ((v >> 24))];

+    d = *((const UInt32 *)p + 1);

+    v ^=

+          table[0x000 + ((d      ) & 0xFF)]

+        ^ table[0x100 + ((d >>  8) & 0xFF)]

+        ^ table[0x200 + ((d >> 16) & 0xFF)]

+        ^ table[0x300 + ((d >> 24))];

+  }

+  for (; size > 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

+  return CRC_UINT32_SWAP(v);

 }

 

 #endif

diff --git a/C/7zDec.c b/C/7zDec.c
index 1c363a5..e39b4ff 100644
--- a/C/7zDec.c
+++ b/C/7zDec.c
@@ -1,5 +1,5 @@
 /* 7zDec.c -- Decoding from 7z folder

-2014-06-16 : Igor Pavlov : Public domain */

+2015-11-18 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -8,10 +8,12 @@
 /* #define _7ZIP_PPMD_SUPPPORT */

 

 #include "7z.h"

+#include "7zCrc.h"

 

 #include "Bcj2.h"

 #include "Bra.h"

 #include "CpuArch.h"

+#include "Delta.h"

 #include "LzmaDec.h"

 #include "Lzma2Dec.h"

 #ifdef _7ZIP_PPMD_SUPPPORT

@@ -19,14 +21,17 @@
 #endif

 

 #define k_Copy 0

+#define k_Delta 3

 #define k_LZMA2 0x21

 #define k_LZMA  0x30101

-#define k_BCJ   0x03030103

-#define k_PPC   0x03030205

-#define k_ARM   0x03030501

-#define k_ARMT  0x03030701

-#define k_SPARC 0x03030805

-#define k_BCJ2  0x0303011B

+#define k_BCJ   0x3030103

+#define k_BCJ2  0x303011B

+#define k_PPC   0x3030205

+#define k_IA64  0x3030401

+#define k_ARM   0x3030501

+#define k_ARMT  0x3030701

+#define k_SPARC 0x3030805

+

 

 #ifdef _7ZIP_PPMD_SUPPPORT

 

@@ -140,11 +145,11 @@
 

   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;

 

@@ -156,14 +161,23 @@
       inSize -= inProcessed;

       if (res != SZ_OK)

         break;

-      if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))

+

+      if (status == LZMA_STATUS_FINISHED_WITH_MARK)

       {

-        if (state.dicBufSize != outSize || lookahead != 0 ||

-            (status != LZMA_STATUS_FINISHED_WITH_MARK &&

-             status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))

+        if (outSize != state.dicPos || inSize != 0)

           res = SZ_ERROR_DATA;

         break;

       }

+

+      if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)

+        break;

+

+      if (inProcessed == 0 && dicPos == state.dicPos)

+      {

+        res = SZ_ERROR_DATA;

+        break;

+      }

+

       res = inStream->Skip((void *)inStream, inProcessed);

       if (res != SZ_OK)

         break;

@@ -174,6 +188,9 @@
   return res;

 }

 

+

+#ifndef _7Z_NO_METHOD_LZMA2

+

 static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,

     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

 {

@@ -190,11 +207,11 @@
 

   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;

 

@@ -206,13 +223,20 @@
       inSize -= inProcessed;

       if (res != SZ_OK)

         break;

-      if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))

+

+      if (status == LZMA_STATUS_FINISHED_WITH_MARK)

       {

-        if (state.decoder.dicBufSize != outSize || lookahead != 0 ||

-            (status != LZMA_STATUS_FINISHED_WITH_MARK))

+        if (outSize != state.decoder.dicPos || inSize != 0)

           res = SZ_ERROR_DATA;

         break;

       }

+

+      if (inProcessed == 0 && dicPos == state.decoder.dicPos)

+      {

+        res = SZ_ERROR_DATA;

+        break;

+      }

+

       res = inStream->Skip((void *)inStream, inProcessed);

       if (res != SZ_OK)

         break;

@@ -223,15 +247,18 @@
   return res;

 }

 

+#endif

+

+

 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);

@@ -248,7 +275,9 @@
   {

     case k_Copy:

     case k_LZMA:

+    #ifndef _7Z_NO_METHOD_LZMA2

     case k_LZMA2:

+    #endif

     #ifdef _7ZIP_PPMD_SUPPPORT

     case k_PPMD:

     #endif

@@ -260,13 +289,12 @@
 static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)

 {

   return

-      c->NumInStreams == 1 &&

-      c->NumOutStreams == 1 &&

-      /* c->MethodID <= (UInt32)0xFFFFFFFF && */

-      IS_MAIN_METHOD((UInt32)c->MethodID);

+      c->NumStreams == 1

+      /* && c->MethodID <= (UInt32)0xFFFFFFFF */

+      && IS_MAIN_METHOD((UInt32)c->MethodID);

 }

 

-#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)

+#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)

 

 static SRes CheckSupportedFolder(const CSzFolder *f)

 {

@@ -276,51 +304,64 @@
     return SZ_ERROR_UNSUPPORTED;

   if (f->NumCoders == 1)

   {

-    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)

+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)

       return SZ_ERROR_UNSUPPORTED;

     return SZ_OK;

   }

+  

+  

+  #ifndef _7Z_NO_METHODS_FILTERS

+

   if (f->NumCoders == 2)

   {

     const CSzCoderInfo *c = &f->Coders[1];

     if (

         /* c->MethodID > (UInt32)0xFFFFFFFF || */

-        c->NumInStreams != 1 ||

-        c->NumOutStreams != 1 ||

-        f->NumPackStreams != 1 ||

-        f->PackStreams[0] != 0 ||

-        f->NumBindPairs != 1 ||

-        f->BindPairs[0].InIndex != 1 ||

-        f->BindPairs[0].OutIndex != 0)

+        c->NumStreams != 1

+        || f->NumPackStreams != 1

+        || f->PackStreams[0] != 0

+        || f->NumBonds != 1

+        || f->Bonds[0].InIndex != 1

+        || f->Bonds[0].OutIndex != 0)

       return SZ_ERROR_UNSUPPORTED;

     switch ((UInt32)c->MethodID)

     {

+      case k_Delta:

       case k_BCJ:

+      case k_PPC:

+      case k_IA64:

+      case k_SPARC:

       case k_ARM:

+      case k_ARMT:

         break;

       default:

         return SZ_ERROR_UNSUPPORTED;

     }

     return SZ_OK;

   }

+

+  #endif

+

+  

   if (f->NumCoders == 4)

   {

-    if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||

-        !IS_SUPPORTED_CODER(&f->Coders[2]) ||

-        !IS_BCJ2(&f->Coders[3]))

+    if (!IS_SUPPORTED_CODER(&f->Coders[1])

+        || !IS_SUPPORTED_CODER(&f->Coders[2])

+        || !IS_BCJ2(&f->Coders[3]))

       return SZ_ERROR_UNSUPPORTED;

-    if (f->NumPackStreams != 4 ||

-        f->PackStreams[0] != 2 ||

-        f->PackStreams[1] != 6 ||

-        f->PackStreams[2] != 1 ||

-        f->PackStreams[3] != 0 ||

-        f->NumBindPairs != 3 ||

-        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||

-        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||

-        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)

+    if (f->NumPackStreams != 4

+        || f->PackStreams[0] != 2

+        || f->PackStreams[1] != 6

+        || f->PackStreams[2] != 1

+        || f->PackStreams[3] != 0

+        || f->NumBonds != 3

+        || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0

+        || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1

+        || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)

       return SZ_ERROR_UNSUPPORTED;

     return SZ_OK;

   }

+  

   return SZ_ERROR_UNSUPPORTED;

 }

 

@@ -364,7 +405,7 @@
           if (outSizeCur != unpackSize)

             return SZ_ERROR_MEM;

           temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);

-          if (temp == 0 && outSizeCur != 0)

+          if (!temp && outSizeCur != 0)

             return SZ_ERROR_MEM;

           outBufCur = tempBuf[1 - ci] = temp;

           tempSizes[1 - ci] = outSizeCur;

@@ -393,66 +434,118 @@
       {

         RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

       }

+      #ifndef _7Z_NO_METHOD_LZMA2

       else if (coder->MethodID == k_LZMA2)

       {

         RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

       }

-      else

+      #endif

+      #ifdef _7ZIP_PPMD_SUPPPORT

+      else if (coder->MethodID == k_PPMD)

       {

-        #ifdef _7ZIP_PPMD_SUPPPORT

         RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

-        #else

-        return SZ_ERROR_UNSUPPORTED;

-        #endif

       }

+      #endif

+      else

+        return SZ_ERROR_UNSUPPORTED;

     }

     else if (coder->MethodID == k_BCJ2)

     {

       UInt64 offset = packPositions[1];

       UInt64 s3Size = packPositions[2] - offset;

-      SRes res;

+      

       if (ci != 3)

         return SZ_ERROR_UNSUPPORTED;

-      RINOK(LookInStream_SeekTo(inStream, startPos + offset));

+      

       tempSizes[2] = (SizeT)s3Size;

       if (tempSizes[2] != s3Size)

         return SZ_ERROR_MEM;

       tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);

-      if (tempBuf[2] == 0 && tempSizes[2] != 0)

+      if (!tempBuf[2] && tempSizes[2] != 0)

         return SZ_ERROR_MEM;

-      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);

-      RINOK(res)

+      

+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));

+      RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));

 

-      res = Bcj2_Decode(

-          tempBuf3, tempSize3,

-          tempBuf[0], tempSizes[0],

-          tempBuf[1], tempSizes[1],

-          tempBuf[2], tempSizes[2],

-          outBuffer, outSize);

-      RINOK(res)

-    }

-    else

-    {

-      if (ci != 1)

-        return SZ_ERROR_UNSUPPORTED;

-      switch (coder->MethodID)

+      if ((tempSizes[0] & 3) != 0 ||

+          (tempSizes[1] & 3) != 0 ||

+          tempSize3 + tempSizes[0] + tempSizes[1] != outSize)

+        return SZ_ERROR_DATA;

+

       {

-        case k_BCJ:

+        CBcj2Dec p;

+        

+        p.bufs[0] = tempBuf3;   p.lims[0] = tempBuf3 + tempSize3;

+        p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];

+        p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];

+        p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];

+        

+        p.dest = outBuffer;

+        p.destLim = outBuffer + outSize;

+        

+        Bcj2Dec_Init(&p);

+        RINOK(Bcj2Dec_Decode(&p));

+

         {

-          UInt32 state;

-          x86_Convert_Init(state);

-          x86_Convert(outBuffer, outSize, 0, &state, 0);

-          break;

+          unsigned i;

+          for (i = 0; i < 4; i++)

+            if (p.bufs[i] != p.lims[i])

+              return SZ_ERROR_DATA;

+          

+          if (!Bcj2Dec_IsFinished(&p))

+            return SZ_ERROR_DATA;

+

+          if (p.dest != p.destLim

+             || p.state != BCJ2_STREAM_MAIN)

+            return SZ_ERROR_DATA;

         }

-        CASE_BRA_CONV(ARM)

-        default:

-          return SZ_ERROR_UNSUPPORTED;

       }

     }

+    #ifndef _7Z_NO_METHODS_FILTERS

+    else if (ci == 1)

+    {

+      if (coder->MethodID == k_Delta)

+      {

+        if (coder->PropsSize != 1)

+          return SZ_ERROR_UNSUPPORTED;

+        {

+          Byte state[DELTA_STATE_SIZE];

+          Delta_Init(state);

+          Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);

+        }

+      }

+      else

+      {

+        if (coder->PropsSize != 0)

+          return SZ_ERROR_UNSUPPORTED;

+        switch (coder->MethodID)

+        {

+          case k_BCJ:

+          {

+            UInt32 state;

+            x86_Convert_Init(state);

+            x86_Convert(outBuffer, outSize, 0, &state, 0);

+            break;

+          }

+          CASE_BRA_CONV(PPC)

+          CASE_BRA_CONV(IA64)

+          CASE_BRA_CONV(SPARC)

+          CASE_BRA_CONV(ARM)

+          CASE_BRA_CONV(ARMT)

+          default:

+            return SZ_ERROR_UNSUPPORTED;

+        }

+      }

+    }

+    #endif

+    else

+      return SZ_ERROR_UNSUPPORTED;

   }

+

   return SZ_OK;

 }

 

+

 SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

     ILookInStream *inStream, UInt64 startPos,

     Byte *outBuffer, size_t outSize,

@@ -461,33 +554,38 @@
   SRes res;

   CSzFolder folder;

   CSzData sd;

-  CSzData sdSizes;

   

   const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];

   sd.Data = data;

   sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];

   

-  sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex];

-  sdSizes.Size =

-      p->FoSizesOffsets[folderIndex + 1] -

-      p->FoSizesOffsets[folderIndex];

-

-  res = SzGetNextFolderItem(&folder, &sd, &sdSizes);

+  res = SzGetNextFolderItem(&folder, &sd);

   

   if (res != SZ_OK)

     return res;

 

-  if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream])

+  if (sd.Size != 0

+      || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]

+      || outSize != SzAr_GetFolderUnpackSize(p, folderIndex))

     return SZ_ERROR_FAIL;

   {

-    int i;

+    unsigned i;

     Byte *tempBuf[3] = { 0, 0, 0};

-    res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,

+

+    res = SzFolder_Decode2(&folder, data,

+        &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],

         p->PackPositions + p->FoStartPackStreamIndex[folderIndex],

         inStream, startPos,

         outBuffer, (SizeT)outSize, allocMain, tempBuf);

+    

     for (i = 0; i < 3; i++)

       IAlloc_Free(allocMain, tempBuf[i]);

+

+    if (res == SZ_OK)

+      if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))

+        if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])

+          res = SZ_ERROR_CRC;

+

     return res;

   }

 }

diff --git a/C/7zVersion.h b/C/7zVersion.h
index feedd30..acb67a9 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,10 +1,19 @@
-#define MY_VER_MAJOR 9

-#define MY_VER_MINOR 38

-#define MY_VER_BUILD 00

-#define MY_VERSION "9.38 beta"

-// #define MY_7ZIP_VERSION "9.38"

-#define MY_DATE "2015-01-03"

+#define MY_VER_MAJOR 16

+#define MY_VER_MINOR 04

+#define MY_VER_BUILD 0

+#define MY_VERSION_NUMBERS "16.04"

+#define MY_VERSION "16.04"

+#define MY_DATE "2016-10-04"

 #undef MY_COPYRIGHT

 #undef MY_VERSION_COPYRIGHT_DATE

-#define MY_COPYRIGHT ": Igor Pavlov : Public domain"

-#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

+#define MY_AUTHOR_NAME "Igor Pavlov"

+#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"

+#define MY_COPYRIGHT_CR "Copyright (c) 1999-2016 Igor Pavlov"

+

+#ifdef USE_COPYRIGHT_CR

+  #define MY_COPYRIGHT MY_COPYRIGHT_CR

+#else

+  #define MY_COPYRIGHT MY_COPYRIGHT_PD

+#endif

+

+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE

diff --git a/C/Aes.c b/C/Aes.c
index 06bf9d3..8e658e7 100644
--- a/C/Aes.c
+++ b/C/Aes.c
@@ -1,5 +1,5 @@
 /* Aes.c -- AES encryption / decryption

-2013-11-12 : Igor Pavlov : Public domain */

+2016-05-21 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -7,7 +7,7 @@
 #include "CpuArch.h"

 

 static UInt32 T[256 * 4];

-static Byte Sbox[256] = {

+static const Byte Sbox[256] = {

   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,

   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,

   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,

@@ -40,7 +40,7 @@
 static UInt32 D[256 * 4];

 static Byte InvS[256];

 

-static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };

+static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };

 

 #define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)

 

@@ -56,6 +56,7 @@
   unsigned i;

   for (i = 0; i < 256; i++)

     InvS[Sbox[i]] = (Byte)i;

+  

   for (i = 0; i < 256; i++)

   {

     {

@@ -82,9 +83,11 @@
       D[0x300 + i] = Ui32(a9, aD, aB, aE);

     }

   }

+  

   g_AesCbc_Encode = AesCbc_Encode;

   g_AesCbc_Decode = AesCbc_Decode;

   g_AesCtr_Code = AesCtr_Code;

+  

   #ifdef MY_CPU_X86_OR_AMD64

   if (CPU_Is_Aes_Supported())

   {

@@ -95,34 +98,38 @@
   #endif

 }

 

+

 #define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]

+

 #define HT4(m, i, s, p) m[i] = \

     HT(i, 0, s) ^ \

     HT(i, 1, s) ^ \

     HT(i, 2, s) ^ \

     HT(i, 3, s) ^ w[p + i]

-/* such order (2031) in HT16 is for VC6/K8 speed optimization) */

+

 #define HT16(m, s, p) \

-    HT4(m, 2, s, p); \

     HT4(m, 0, s, p); \

-    HT4(m, 3, s, p); \

     HT4(m, 1, s, p); \

+    HT4(m, 2, s, p); \

+    HT4(m, 3, s, p); \

 

 #define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]

 #define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];

 

+

 #define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]

+

 #define HD4(m, i, s, p) m[i] = \

     HD(i, 0, s) ^ \

     HD(i, 1, s) ^ \

     HD(i, 2, s) ^ \

     HD(i, 3, s) ^ w[p + i];

-/* such order (0231) in HD16 is for VC6/K8 speed optimization) */

+

 #define HD16(m, s, p) \

     HD4(m, 0, s, p); \

+    HD4(m, 1, s, p); \

     HD4(m, 2, s, p); \

     HD4(m, 3, s, p); \

-    HD4(m, 1, s, p); \

 

 #define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]

 #define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];

@@ -160,16 +167,16 @@
   {

     UInt32 r = w[i];

     w[i] =

-      D[        Sbox[gb0(r)]] ^

-      D[0x100 + Sbox[gb1(r)]] ^

-      D[0x200 + Sbox[gb2(r)]] ^

-      D[0x300 + Sbox[gb3(r)]];

+      D[        (unsigned)Sbox[gb0(r)]] ^

+      D[0x100 + (unsigned)Sbox[gb1(r)]] ^

+      D[0x200 + (unsigned)Sbox[gb2(r)]] ^

+      D[0x300 + (unsigned)Sbox[gb3(r)]];

   }

 }

 

 /* Aes_Encode and Aes_Decode functions work with little-endian words.

   src and dest are pointers to 4 UInt32 words.

-  arc and dest can point to same block */

+  src and dest can point to same block */

 

 static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)

 {

@@ -271,13 +278,17 @@
     UInt32 temp[4];

     Byte buf[16];

     int i;

+

     if (++p[0] == 0)

       p[1]++;

+    

     Aes_Encode(p + 4, temp, p);

+    

     SetUi32(buf,      temp[0]);

     SetUi32(buf + 4,  temp[1]);

     SetUi32(buf + 8,  temp[2]);

     SetUi32(buf + 12, temp[3]);

+    

     for (i = 0; i < 16; i++)

       *data++ ^= buf[i];

   }

diff --git a/C/Alloc.c b/C/Alloc.c
index 8e2839a..9f1d036 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,5 +1,5 @@
 /* Alloc.c -- Memory allocation functions

-2013-11-12 : Igor Pavlov : Public domain */

+2015-02-21 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -125,3 +125,12 @@
 }

 

 #endif

+

+

+static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }

+static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }

+ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }

+static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }

+ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

diff --git a/C/Alloc.h b/C/Alloc.h
index 6b3f034..73b282a 100644
--- a/C/Alloc.h
+++ b/C/Alloc.h
@@ -1,14 +1,12 @@
 /* Alloc.h -- Memory allocation functions

-2009-02-07 : Igor Pavlov : Public domain */

+2015-02-21 : Igor Pavlov : Public domain */

 

 #ifndef __COMMON_ALLOC_H

 #define __COMMON_ALLOC_H

 

-#include <stddef.h>

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 void *MyAlloc(size_t size);

 void MyFree(void *address);

@@ -31,8 +29,9 @@
 

 #endif

 

-#ifdef __cplusplus

-}

-#endif

+extern ISzAlloc g_Alloc;

+extern ISzAlloc g_BigAlloc;

+

+EXTERN_C_END

 

 #endif

diff --git a/C/Android.bp b/C/Android.bp
index 1ee4798..69cb5b6 100644
--- a/C/Android.bp
+++ b/C/Android.bp
@@ -58,6 +58,13 @@
         },
         windows: {
             enabled: true,
+            srcs: [
+                "Bcj2Enc.c",
+                "DllSecur.c",
+                "LzFindMt.c",
+                "MtCoder.c",
+                "Threads.c",
+            ],
         },
     },
 }
diff --git a/C/Bcj2.c b/C/Bcj2.c
index ac4ca0c..707362a 100644
--- a/C/Bcj2.c
+++ b/C/Bcj2.c
@@ -1,134 +1,256 @@
-/* Bcj2.c -- Converter for x86 code (BCJ2)

-2008-10-04 : Igor Pavlov : Public domain */

+/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)

+2015-08-01 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

 #include "Bcj2.h"

+#include "CpuArch.h"

 

-#ifdef _LZMA_PROB32

-#define CProb UInt32

-#else

 #define CProb UInt16

-#endif

 

-#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)

-#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))

-

-#define kNumTopBits 24

-#define kTopValue ((UInt32)1 << kNumTopBits)

-

-#define kNumBitModelTotalBits 11

-#define kBitModelTotal (1 << kNumBitModelTotalBits)

+#define kTopValue ((UInt32)1 << 24)

+#define kNumModelBits 11

+#define kBitModelTotal (1 << kNumModelBits)

 #define kNumMoveBits 5

 

-#define RC_READ_BYTE (*buffer++)

-#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }

-#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \

-  { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}

+#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)

+#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));

+#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));

 

-#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }

-

-#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)

-#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;

-#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;

-

-int Bcj2_Decode(

-    const Byte *buf0, SizeT size0,

-    const Byte *buf1, SizeT size1,

-    const Byte *buf2, SizeT size2,

-    const Byte *buf3, SizeT size3,

-    Byte *outBuf, SizeT outSize)

+void Bcj2Dec_Init(CBcj2Dec *p)

 {

-  CProb p[256 + 2];

-  SizeT inPos = 0, outPos = 0;

+  unsigned i;

 

-  const Byte *buffer, *bufferLim;

-  UInt32 range, code;

-  Byte prevByte = 0;

+  p->state = BCJ2_DEC_STATE_OK;

+  p->ip = 0;

+  p->temp[3] = 0;

+  p->range = 0;

+  p->code = 0;

+  for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)

+    p->probs[i] = kBitModelTotal >> 1;

+}

 

-  unsigned int i;

-  for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)

-    p[i] = kBitModelTotal >> 1;

+SRes Bcj2Dec_Decode(CBcj2Dec *p)

+{

+  if (p->range <= 5)

+  {

+    p->state = BCJ2_DEC_STATE_OK;

+    for (; p->range != 5; p->range++)

+    {

+      if (p->range == 1 && p->code != 0)

+        return SZ_ERROR_DATA;

+      

+      if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])

+      {

+        p->state = BCJ2_STREAM_RC;

+        return SZ_OK;

+      }

 

-  buffer = buf3;

-  bufferLim = buffer + size3;

-  RC_INIT2

+      p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;

+    }

+    

+    if (p->code == 0xFFFFFFFF)

+      return SZ_ERROR_DATA;

+    

+    p->range = 0xFFFFFFFF;

+  }

+  else if (p->state >= BCJ2_DEC_STATE_ORIG_0)

+  {

+    while (p->state <= BCJ2_DEC_STATE_ORIG_3)

+    {

+      Byte *dest = p->dest;

+      if (dest == p->destLim)

+        return SZ_OK;

+      *dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];

+      p->dest = dest + 1;

+    }

+  }

 

-  if (outSize == 0)

-    return SZ_OK;

+  /*

+  if (BCJ2_IS_32BIT_STREAM(p->state))

+  {

+    const Byte *cur = p->bufs[p->state];

+    if (cur == p->lims[p->state])

+      return SZ_OK;

+    p->bufs[p->state] = cur + 4;

+    

+    {

+      UInt32 val;

+      Byte *dest;

+      SizeT rem;

+      

+      p->ip += 4;

+      val = GetBe32(cur) - p->ip;

+      dest = p->dest;

+      rem = p->destLim - dest;

+      if (rem < 4)

+      {

+        SizeT i;

+        SetUi32(p->temp, val);

+        for (i = 0; i < rem; i++)

+          dest[i] = p->temp[i];

+        p->dest = dest + rem;

+        p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;

+        return SZ_OK;

+      }

+      SetUi32(dest, val);

+      p->temp[3] = (Byte)(val >> 24);

+      p->dest = dest + 4;

+      p->state = BCJ2_DEC_STATE_OK;

+    }

+  }

+  */

 

   for (;;)

   {

-    Byte b;

-    CProb *prob;

-    UInt32 bound;

-    UInt32 ttt;

-

-    SizeT limit = size0 - inPos;

-    if (outSize - outPos < limit)

-      limit = outSize - outPos;

-    while (limit != 0)

-    {

-      Byte b = buf0[inPos];

-      outBuf[outPos++] = b;

-      if (IsJ(prevByte, b))

-        break;

-      inPos++;

-      prevByte = b;

-      limit--;

-    }

-

-    if (limit == 0 || outPos == outSize)

-      break;

-

-    b = buf0[inPos++];

-

-    if (b == 0xE8)

-      prob = p + prevByte;

-    else if (b == 0xE9)

-      prob = p + 256;

-    else

-      prob = p + 257;

-

-    IF_BIT_0(prob)

-    {

-      UPDATE_0(prob)

-      prevByte = b;

-    }

+    if (BCJ2_IS_32BIT_STREAM(p->state))

+      p->state = BCJ2_DEC_STATE_OK;

     else

     {

-      UInt32 dest;

-      const Byte *v;

-      UPDATE_1(prob)

-      if (b == 0xE8)

+      if (p->range < kTopValue)

       {

-        v = buf1;

-        if (size1 < 4)

-          return SZ_ERROR_DATA;

-        buf1 += 4;

-        size1 -= 4;

+        if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])

+        {

+          p->state = BCJ2_STREAM_RC;

+          return SZ_OK;

+        }

+        p->range <<= 8;

+        p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;

       }

-      else

+

       {

-        v = buf2;

-        if (size2 < 4)

-          return SZ_ERROR_DATA;

-        buf2 += 4;

-        size2 -= 4;

+        const Byte *src = p->bufs[BCJ2_STREAM_MAIN];

+        const Byte *srcLim;

+        Byte *dest;

+        SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;

+        

+        if (num == 0)

+        {

+          p->state = BCJ2_STREAM_MAIN;

+          return SZ_OK;

+        }

+        

+        dest = p->dest;

+        if (num > (SizeT)(p->destLim - dest))

+        {

+          num = p->destLim - dest;

+          if (num == 0)

+          {

+            p->state = BCJ2_DEC_STATE_ORIG;

+            return SZ_OK;

+          }

+        }

+       

+        srcLim = src + num;

+

+        if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)

+          *dest = src[0];

+        else for (;;)

+        {

+          Byte b = *src;

+          *dest = b;

+          if (b != 0x0F)

+          {

+            if ((b & 0xFE) == 0xE8)

+              break;

+            dest++;

+            if (++src != srcLim)

+              continue;

+            break;

+          }

+          dest++;

+          if (++src == srcLim)

+            break;

+          if ((*src & 0xF0) != 0x80)

+            continue;

+          *dest = *src;

+          break;

+        }

+        

+        num = src - p->bufs[BCJ2_STREAM_MAIN];

+        

+        if (src == srcLim)

+        {

+          p->temp[3] = src[-1];

+          p->bufs[BCJ2_STREAM_MAIN] = src;

+          p->ip += (UInt32)num;

+          p->dest += num;

+          p->state =

+            p->bufs[BCJ2_STREAM_MAIN] ==

+            p->lims[BCJ2_STREAM_MAIN] ?

+              (unsigned)BCJ2_STREAM_MAIN :

+              (unsigned)BCJ2_DEC_STATE_ORIG;

+          return SZ_OK;

+        }

+        

+        {

+          UInt32 bound, ttt;

+          CProb *prob;

+          Byte b = src[0];

+          Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);

+          

+          p->temp[3] = b;

+          p->bufs[BCJ2_STREAM_MAIN] = src + 1;

+          num++;

+          p->ip += (UInt32)num;

+          p->dest += num;

+          

+          prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));

+          

+          _IF_BIT_0

+          {

+            _UPDATE_0

+            continue;

+          }

+          _UPDATE_1

+            

+        }

       }

-      dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |

-          ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);

-      outBuf[outPos++] = (Byte)dest;

-      if (outPos == outSize)

+    }

+

+    {

+      UInt32 val;

+      unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;

+      const Byte *cur = p->bufs[cj];

+      Byte *dest;

+      SizeT rem;

+      

+      if (cur == p->lims[cj])

+      {

+        p->state = cj;

         break;

-      outBuf[outPos++] = (Byte)(dest >> 8);

-      if (outPos == outSize)

+      }

+      

+      val = GetBe32(cur);

+      p->bufs[cj] = cur + 4;

+

+      p->ip += 4;

+      val -= p->ip;

+      dest = p->dest;

+      rem = p->destLim - dest;

+      

+      if (rem < 4)

+      {

+        SizeT i;

+        SetUi32(p->temp, val);

+        for (i = 0; i < rem; i++)

+          dest[i] = p->temp[i];

+        p->dest = dest + rem;

+        p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;

         break;

-      outBuf[outPos++] = (Byte)(dest >> 16);

-      if (outPos == outSize)

-        break;

-      outBuf[outPos++] = prevByte = (Byte)(dest >> 24);

+      }

+      

+      SetUi32(dest, val);

+      p->temp[3] = (Byte)(val >> 24);

+      p->dest = dest + 4;

     }

   }

-  return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;

+

+  if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])

+  {

+    p->range <<= 8;

+    p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;

+  }

+

+  return SZ_OK;

 }

diff --git a/C/Bcj2.h b/C/Bcj2.h
index e8304c5..68893d2 100644
--- a/C/Bcj2.h
+++ b/C/Bcj2.h
@@ -1,5 +1,5 @@
-/* Bcj2.h -- Converter for x86 code (BCJ2)

-2013-01-18 : Igor Pavlov : Public domain */

+/* Bcj2.h -- BCJ2 Converter for x86 code

+2014-11-10 : Igor Pavlov : Public domain */

 

 #ifndef __BCJ2_H

 #define __BCJ2_H

@@ -8,26 +8,138 @@
 

 EXTERN_C_BEGIN

 

+#define BCJ2_NUM_STREAMS 4

+

+enum

+{

+  BCJ2_STREAM_MAIN,

+  BCJ2_STREAM_CALL,

+  BCJ2_STREAM_JUMP,

+  BCJ2_STREAM_RC

+};

+

+enum

+{

+  BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,

+  BCJ2_DEC_STATE_ORIG_1,

+  BCJ2_DEC_STATE_ORIG_2,

+  BCJ2_DEC_STATE_ORIG_3,

+  

+  BCJ2_DEC_STATE_ORIG,

+  BCJ2_DEC_STATE_OK

+};

+

+enum

+{

+  BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,

+  BCJ2_ENC_STATE_OK

+};

+

+

+#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)

+

 /*

-Conditions:

-  outSize <= FullOutputSize,

-  where FullOutputSize is full size of output stream of x86_2 filter.

-

-If buf0 overlaps outBuf, there are two required conditions:

-  1) (buf0 >= outBuf)

-  2) (buf0 + size0 >= outBuf + FullOutputSize).

-

-Returns:

-  SZ_OK

-  SZ_ERROR_DATA - Data error

+CBcj2Dec / CBcj2Enc

+bufs sizes:

+  BUF_SIZE(n) = lims[n] - bufs[n]

+bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:

+    (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0

+    (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0

 */

 

-int Bcj2_Decode(

-    const Byte *buf0, SizeT size0,

-    const Byte *buf1, SizeT size1,

-    const Byte *buf2, SizeT size2,

-    const Byte *buf3, SizeT size3,

-    Byte *outBuf, SizeT outSize);

+/*

+CBcj2Dec:

+dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:

+  bufs[BCJ2_STREAM_MAIN] >= dest &&

+  bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +

+        BUF_SIZE(BCJ2_STREAM_CALL) +

+        BUF_SIZE(BCJ2_STREAM_JUMP)

+     tempReserv = 0 : for first call of Bcj2Dec_Decode

+     tempReserv = 4 : for any other calls of Bcj2Dec_Decode

+  overlap with offset = 1 is not allowed

+*/

+

+typedef struct

+{

+  const Byte *bufs[BCJ2_NUM_STREAMS];

+  const Byte *lims[BCJ2_NUM_STREAMS];

+  Byte *dest;

+  const Byte *destLim;

+

+  unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */

+

+  UInt32 ip;

+  Byte temp[4];

+  UInt32 range;

+  UInt32 code;

+  UInt16 probs[2 + 256];

+} CBcj2Dec;

+

+void Bcj2Dec_Init(CBcj2Dec *p);

+

+/* Returns: SZ_OK or SZ_ERROR_DATA */

+SRes Bcj2Dec_Decode(CBcj2Dec *p);

+

+#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)

+

+

+

+typedef enum

+{

+  BCJ2_ENC_FINISH_MODE_CONTINUE,

+  BCJ2_ENC_FINISH_MODE_END_BLOCK,

+  BCJ2_ENC_FINISH_MODE_END_STREAM

+} EBcj2Enc_FinishMode;

+

+typedef struct

+{

+  Byte *bufs[BCJ2_NUM_STREAMS];

+  const Byte *lims[BCJ2_NUM_STREAMS];

+  const Byte *src;

+  const Byte *srcLim;

+

+  unsigned state;

+  EBcj2Enc_FinishMode finishMode;

+

+  Byte prevByte;

+

+  Byte cache;

+  UInt32 range;

+  UInt64 low;

+  UInt64 cacheSize;

+

+  UInt32 ip;

+

+  /* 32-bit ralative offset in JUMP/CALL commands is

+       - (mod 4 GB)   in 32-bit mode

+       - signed Int32 in 64-bit mode

+     We use (mod 4 GB) check for fileSize.

+     Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */

+  UInt32 fileIp;

+  UInt32 fileSize;    /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */

+  UInt32 relatLimit;  /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */

+

+  UInt32 tempTarget;

+  unsigned tempPos;

+  Byte temp[4 * 2];

+

+  unsigned flushPos;

+  

+  UInt16 probs[2 + 256];

+} CBcj2Enc;

+

+void Bcj2Enc_Init(CBcj2Enc *p);

+void Bcj2Enc_Encode(CBcj2Enc *p);

+

+#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)

+#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)

+

+

+#define BCJ2_RELAT_LIMIT_NUM_BITS 26

+#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)

+

+/* limit for CBcj2Enc::fileSize variable */

+#define BCJ2_FileSize_MAX ((UInt32)1 << 31)

 

 EXTERN_C_END

 

diff --git a/C/Bcj2Enc.c b/C/Bcj2Enc.c
new file mode 100644
index 0000000..6a21015
--- /dev/null
+++ b/C/Bcj2Enc.c
@@ -0,0 +1,312 @@
+/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)

+2014-11-10 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+/* #define SHOW_STAT */

+

+#ifdef SHOW_STAT

+#include <stdio.h>

+#define PRF(x) x

+#else

+#define PRF(x)

+#endif

+

+#include <windows.h>

+#include <string.h>

+

+#include "Bcj2.h"

+#include "CpuArch.h"

+

+#define CProb UInt16

+

+#define kTopValue ((UInt32)1 << 24)

+#define kNumModelBits 11

+#define kBitModelTotal (1 << kNumModelBits)

+#define kNumMoveBits 5

+

+void Bcj2Enc_Init(CBcj2Enc *p)

+{

+  unsigned i;

+

+  p->state = BCJ2_ENC_STATE_OK;

+  p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;

+

+  p->prevByte = 0;

+

+  p->cache = 0;

+  p->range = 0xFFFFFFFF;

+  p->low = 0;

+  p->cacheSize = 1;

+

+  p->ip = 0;

+

+  p->fileIp = 0;

+  p->fileSize = 0;

+  p->relatLimit = BCJ2_RELAT_LIMIT;

+

+  p->tempPos = 0;

+

+  p->flushPos = 0;

+

+  for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)

+    p->probs[i] = kBitModelTotal >> 1;

+}

+

+static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p)

+{

+  if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0)

+  {

+    Byte *buf = p->bufs[BCJ2_STREAM_RC];

+    do

+    {

+      if (buf == p->lims[BCJ2_STREAM_RC])

+      {

+        p->state = BCJ2_STREAM_RC;

+        p->bufs[BCJ2_STREAM_RC] = buf;

+        return True;

+      }

+      *buf++ = (Byte)(p->cache + (Byte)(p->low >> 32));

+      p->cache = 0xFF;

+    }

+    while (--p->cacheSize);

+    p->bufs[BCJ2_STREAM_RC] = buf;

+    p->cache = (Byte)((UInt32)p->low >> 24);

+  }

+  p->cacheSize++;

+  p->low = (UInt32)p->low << 8;

+  return False;

+}

+

+static void Bcj2Enc_Encode_2(CBcj2Enc *p)

+{

+  if (BCJ2_IS_32BIT_STREAM(p->state))

+  {

+    Byte *cur = p->bufs[p->state];

+    if (cur == p->lims[p->state])

+      return;

+    SetBe32(cur, p->tempTarget);

+    p->bufs[p->state] = cur + 4;

+  }

+

+  p->state = BCJ2_ENC_STATE_ORIG;

+

+  for (;;)

+  {

+    if (p->range < kTopValue)

+    {

+      if (RangeEnc_ShiftLow(p))

+        return;

+      p->range <<= 8;

+    }

+

+    {

+      {

+        const Byte *src = p->src;

+        const Byte *srcLim;

+        Byte *dest;

+        SizeT num = p->srcLim - src;

+

+        if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)

+        {

+          if (num <= 4)

+            return;

+          num -= 4;

+        }

+        else if (num == 0)

+          break;

+

+        dest = p->bufs[BCJ2_STREAM_MAIN];

+        if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest))

+        {

+          num = p->lims[BCJ2_STREAM_MAIN] - dest;

+          if (num == 0)

+          {

+            p->state = BCJ2_STREAM_MAIN;

+            return;

+          }

+        }

+       

+        srcLim = src + num;

+

+        if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80)

+          *dest = src[0];

+        else for (;;)

+        {

+          Byte b = *src;

+          *dest = b;

+          if (b != 0x0F)

+          {

+            if ((b & 0xFE) == 0xE8)

+              break;

+            dest++;

+            if (++src != srcLim)

+              continue;

+            break;

+          }

+          dest++;

+          if (++src == srcLim)

+            break;

+          if ((*src & 0xF0) != 0x80)

+            continue;

+          *dest = *src;

+          break;

+        }

+        

+        num = src - p->src;

+        

+        if (src == srcLim)

+        {

+          p->prevByte = src[-1];

+          p->bufs[BCJ2_STREAM_MAIN] = dest;

+          p->src = src;

+          p->ip += (UInt32)num;

+          continue;

+        }

+ 

+        {

+          Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]);

+          Bool needConvert;

+

+          p->bufs[BCJ2_STREAM_MAIN] = dest + 1;

+          p->ip += (UInt32)num + 1;

+          src++;

+          

+          needConvert = False;

+

+          if ((SizeT)(p->srcLim - src) >= 4)

+          {

+            UInt32 relatVal = GetUi32(src);

+            if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize)

+                && ((relatVal + p->relatLimit) >> 1) < p->relatLimit)

+              needConvert = True;

+          }

+

+          {

+            UInt32 bound;

+            unsigned ttt;

+            Byte b = src[-1];

+            CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0));

+

+            ttt = *prob;

+            bound = (p->range >> kNumModelBits) * ttt;

+            

+            if (!needConvert)

+            {

+              p->range = bound;

+              *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));

+              p->src = src;

+              p->prevByte = b;

+              continue;

+            }

+            

+            p->low += bound;

+            p->range -= bound;

+            *prob = (CProb)(ttt - (ttt >> kNumMoveBits));

+

+            {

+              UInt32 relatVal = GetUi32(src);

+              UInt32 absVal;

+              p->ip += 4;

+              absVal = p->ip + relatVal;

+              p->prevByte = src[3];

+              src += 4;

+              p->src = src;

+              {

+                unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;

+                Byte *cur = p->bufs[cj];

+                if (cur == p->lims[cj])

+                {

+                  p->state = cj;

+                  p->tempTarget = absVal;

+                  return;

+                }

+                SetBe32(cur, absVal);

+                p->bufs[cj] = cur + 4;

+              }

+            }

+          }

+        }

+      }

+    }

+  }

+

+  if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)

+    return;

+

+  for (; p->flushPos < 5; p->flushPos++)

+    if (RangeEnc_ShiftLow(p))

+      return;

+  p->state = BCJ2_ENC_STATE_OK;

+}

+

+

+void Bcj2Enc_Encode(CBcj2Enc *p)

+{

+  PRF(printf("\n"));

+  PRF(printf("---- ip = %8d   tempPos = %8d   src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));

+

+  if (p->tempPos != 0)

+  {

+    unsigned extra = 0;

+   

+    for (;;)

+    {

+      const Byte *src = p->src;

+      const Byte *srcLim = p->srcLim;

+      unsigned finishMode = p->finishMode;

+      

+      p->src = p->temp;

+      p->srcLim = p->temp + p->tempPos;

+      if (src != srcLim)

+        p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;

+      

+      PRF(printf("     ip = %8d   tempPos = %8d   src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));

+

+      Bcj2Enc_Encode_2(p);

+      

+      {

+        unsigned num = (unsigned)(p->src - p->temp);

+        unsigned tempPos = p->tempPos - num;

+        unsigned i;

+        p->tempPos = tempPos;

+        for (i = 0; i < tempPos; i++)

+          p->temp[i] = p->temp[i + num];

+      

+        p->src = src;

+        p->srcLim = srcLim;

+        p->finishMode = finishMode;

+        

+        if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim)

+          return;

+        

+        if (extra >= tempPos)

+        {

+          p->src = src - tempPos;

+          p->tempPos = 0;

+          break;

+        }

+        

+        p->temp[tempPos] = src[0];

+        p->tempPos = tempPos + 1;

+        p->src = src + 1;

+        extra++;

+      }

+    }

+  }

+

+  PRF(printf("++++ ip = %8d   tempPos = %8d   src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));

+

+  Bcj2Enc_Encode_2(p);

+  

+  if (p->state == BCJ2_ENC_STATE_ORIG)

+  {

+    const Byte *src = p->src;

+    unsigned rem = (unsigned)(p->srcLim - src);

+    unsigned i;

+    for (i = 0; i < rem; i++)

+      p->temp[i] = src[i];

+    p->tempPos = rem;

+    p->src = src + rem;

+  }

+}

diff --git a/C/Compiler.h b/C/Compiler.h
index 0f76670..de8fab3 100644
--- a/C/Compiler.h
+++ b/C/Compiler.h
@@ -1,5 +1,5 @@
-/* Compiler.h -- Compiler ypes

-2013-11-12 : Igor Pavlov : Public domain */

+/* Compiler.h

+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

@@ -25,4 +26,7 @@
 

 #endif

 

+#define UNUSED_VAR(x) (void)x;

+/* #define UNUSED_VAR(x) x=x; */

+

 #endif

diff --git a/C/CpuArch.c b/C/CpuArch.c
index f8ac0c2..f835c2b 100644
--- a/C/CpuArch.c
+++ b/C/CpuArch.c
@@ -1,5 +1,5 @@
 /* CpuArch.c -- CPU specific code

-2012-05-29: Igor Pavlov : Public domain */

+2016-02-25: Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -45,7 +45,8 @@
     "push %%EDX\n\t"

     "popf\n\t"

     "andl %%EAX, %0\n\t":

-    "=c" (flag) : "c" (flag));

+    "=c" (flag) : "c" (flag) :

+    "%eax", "%edx");

   #endif

   return flag;

 }

@@ -54,7 +55,7 @@
 #define CHECK_CPUID_IS_SUPPORTED

 #endif

 

-static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)

+void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)

 {

   #ifdef USE_ASM

 

@@ -79,7 +80,13 @@
   #else

 

   __asm__ __volatile__ (

-  #if defined(MY_CPU_X86) && defined(__PIC__)

+  #if defined(MY_CPU_AMD64) && defined(__PIC__)

+    "mov %%rbx, %%rdi;"

+    "cpuid;"

+    "xchg %%rbx, %%rdi;"

+    : "=a" (*a) ,

+      "=D" (*b) ,

+  #elif defined(MY_CPU_X86) && defined(__PIC__)

     "mov %%ebx, %%edi;"

     "cpuid;"

     "xchgl %%ebx, %%edi;"

@@ -116,7 +123,7 @@
   return True;

 }

 

-static UInt32 kVendors[][3] =

+static const UInt32 kVendors[][3] =

 {

   { 0x756E6547, 0x49656E69, 0x6C65746E},

   { 0x68747541, 0x69746E65, 0x444D4163},

@@ -144,18 +151,21 @@
   UInt32 family, model;

   if (!x86cpuid_CheckAndRead(&p))

     return True;

-  family = x86cpuid_GetFamily(&p);

-  model = x86cpuid_GetModel(&p);

+

+  family = x86cpuid_GetFamily(p.ver);

+  model = x86cpuid_GetModel(p.ver);

+  

   firm = x86cpuid_GetFirm(&p);

+

   switch (firm)

   {

     case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (

-        /* Atom CPU */

-           model == 0x100C  /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */

-        || model == 0x2006  /* 45 nm, Z6xx */

-        || model == 0x2007  /* 32 nm, Z2460 */

-        || model == 0x3005  /* 32 nm, Z2760 */

-        || model == 0x3006  /* 32 nm, N2xxx, D2xxx */

+        /* In-Order Atom CPU */

+           model == 0x1C  /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */

+        || model == 0x26  /* 45 nm, Z6xx */

+        || model == 0x27  /* 32 nm, Z2460 */

+        || model == 0x35  /* 32 nm, Z2760 */

+        || model == 0x36  /* 32 nm, N2xxx, D2xxx */

         )));

     case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));

     case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));

diff --git a/C/CpuArch.h b/C/CpuArch.h
index 2316205..ef6083c 100644
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -1,5 +1,5 @@
 /* CpuArch.h -- CPU specific code

-2013-11-12: Igor Pavlov : Public domain */

+2016-06-09: Igor Pavlov : Public domain */

 

 #ifndef __CPU_ARCH_H

 #define __CPU_ARCH_H

@@ -10,18 +10,25 @@
 

 /*

 MY_CPU_LE means that CPU is LITTLE ENDIAN.

-If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).

+MY_CPU_BE means that CPU is BIG ENDIAN.

+If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.

 

 MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.

-If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.

 */

 

-#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)

-#define MY_CPU_AMD64

+#if defined(_M_X64) \

+   || defined(_M_AMD64) \

+   || defined(__x86_64__) \

+   || defined(__AMD64__) \

+   || defined(__amd64__)

+  #define MY_CPU_AMD64

 #endif

 

-#if defined(MY_CPU_AMD64) || defined(_M_IA64)

-#define MY_CPU_64BIT

+#if defined(MY_CPU_AMD64) \

+    || defined(_M_IA64) \

+    || defined(__AARCH64EL__) \

+    || defined(__AARCH64EB__)

+  #define MY_CPU_64BIT

 #endif

 

 #if defined(_M_IX86) || defined(__i386__)

@@ -32,8 +39,13 @@
 #define MY_CPU_X86_OR_AMD64

 #endif

 

-#if defined(MY_CPU_X86) || defined(_M_ARM)

-#define MY_CPU_32BIT

+#if defined(MY_CPU_X86) \

+    || defined(_M_ARM) \

+    || defined(__ARMEL__) \

+    || defined(__THUMBEL__) \

+    || defined(__ARMEB__) \

+    || defined(__THUMBEB__)

+  #define MY_CPU_32BIT

 #endif

 

 #if defined(_WIN32) && defined(_M_ARM)

@@ -44,34 +56,64 @@
 #define MY_CPU_IA64_LE

 #endif

 

-#if defined(MY_CPU_X86_OR_AMD64)

-#define MY_CPU_LE_UNALIGN

+#if defined(MY_CPU_X86_OR_AMD64) \

+    || defined(MY_CPU_ARM_LE) \

+    || defined(MY_CPU_IA64_LE) \

+    || defined(__LITTLE_ENDIAN__) \

+    || defined(__ARMEL__) \

+    || defined(__THUMBEL__) \

+    || defined(__AARCH64EL__) \

+    || defined(__MIPSEL__) \

+    || defined(__MIPSEL) \

+    || defined(_MIPSEL) \

+    || defined(__BFIN__) \

+    || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))

+  #define MY_CPU_LE

 #endif

 

-#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE)  || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)

-#define MY_CPU_LE

-#endif

-

-#if defined(__BIG_ENDIAN__) || defined(__m68k__) ||  defined(__ARMEB__) || defined(__MIPSEB__)

-#define MY_CPU_BE

+#if defined(__BIG_ENDIAN__) \

+    || defined(__ARMEB__) \

+    || defined(__THUMBEB__) \

+    || defined(__AARCH64EB__) \

+    || defined(__MIPSEB__) \

+    || defined(__MIPSEB) \

+    || defined(_MIPSEB) \

+    || defined(__m68k__) \

+    || defined(__s390__) \

+    || defined(__s390x__) \

+    || defined(__zarch__) \

+    || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))

+  #define MY_CPU_BE

 #endif

 

 #if defined(MY_CPU_LE) && defined(MY_CPU_BE)

 Stop_Compiling_Bad_Endian

 #endif

 

+

+#ifdef MY_CPU_LE

+  #if defined(MY_CPU_X86_OR_AMD64) \

+      /* || defined(__AARCH64EL__) */

+    #define MY_CPU_LE_UNALIGN

+  #endif

+#endif

+

+

 #ifdef MY_CPU_LE_UNALIGN

 

 #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, d) *(UInt16 *)(p) = (d);

-#define SetUi32(p, d) *(UInt32 *)(p) = (d);

-#define SetUi64(p, d) *(UInt64 *)(p) = (d);

+

+#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }

+#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }

+#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }

 

 #else

 

-#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))

+#define GetUi16(p) ( (UInt16) ( \

+             ((const Byte *)(p))[0] | \

+    ((UInt16)((const Byte *)(p))[1] << 8) ))

 

 #define GetUi32(p) ( \

              ((const Byte *)(p))[0]        | \

@@ -81,23 +123,26 @@
 

 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))

 

-#define SetUi16(p, d) { UInt32 _x_ = (d); \

-    ((Byte *)(p))[0] = (Byte)_x_; \

-    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }

+#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \

+    _ppp_[0] = (Byte)_vvv_; \

+    _ppp_[1] = (Byte)(_vvv_ >> 8); }

 

-#define SetUi32(p, d) { UInt32 _x_ = (d); \

-    ((Byte *)(p))[0] = (Byte)_x_; \

-    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \

-    ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \

-    ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }

+#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \

+    _ppp_[0] = (Byte)_vvv_; \

+    _ppp_[1] = (Byte)(_vvv_ >> 8); \

+    _ppp_[2] = (Byte)(_vvv_ >> 16); \

+    _ppp_[3] = (Byte)(_vvv_ >> 24); }

 

-#define SetUi64(p, d) { UInt64 _x64_ = (d); \

-    SetUi32(p, (UInt32)_x64_); \

-    SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }

+#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \

+    SetUi32(_ppp2_    , (UInt32)_vvv2_); \

+    SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }

 

 #endif

 

-#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)

+

+#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)

+

+/* Note: we use bswap instruction, that is unsupported in 386 cpu */

 

 #include <stdlib.h>

 

@@ -106,6 +151,15 @@
 #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))

 #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))

 

+#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)

+

+#elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))

+

+#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))

+#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))

+

+#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)

+

 #else

 

 #define GetBe32(p) ( \

@@ -116,9 +170,19 @@
 

 #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))

 

+#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \

+    _ppp_[0] = (Byte)(_vvv_ >> 24); \

+    _ppp_[1] = (Byte)(_vvv_ >> 16); \

+    _ppp_[2] = (Byte)(_vvv_ >> 8); \

+    _ppp_[3] = (Byte)_vvv_; }

+

 #endif

 

-#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]))

+

+#define GetBe16(p) ( (UInt16) ( \

+    ((UInt16)((const Byte *)(p))[0] << 8) | \

+             ((const Byte *)(p))[1] ))

+

 

 

 #ifdef MY_CPU_X86_OR_AMD64

@@ -140,12 +204,14 @@
   CPU_FIRM_VIA

 };

 

+void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);

+

 Bool x86cpuid_CheckAndRead(Cx86cpuid *p);

 int x86cpuid_GetFirm(const Cx86cpuid *p);

 

-#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)

-#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)

-#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)

+#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))

+#define x86cpuid_GetModel(ver)  (((ver >> 12) &  0xF0) | ((ver >> 4) & 0xF))

+#define x86cpuid_GetStepping(ver) (ver & 0xF)

 

 Bool CPU_Is_InOrder();

 Bool CPU_Is_Aes_Supported();

diff --git a/C/DllSecur.c b/C/DllSecur.c
new file mode 100644
index 0000000..8745421
--- /dev/null
+++ b/C/DllSecur.c
@@ -0,0 +1,87 @@
+/* DllSecur.c -- DLL loading security

+2016-10-04 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#ifdef _WIN32

+

+#include <windows.h>

+

+#include "DllSecur.h"

+

+#ifndef UNDER_CE

+

+typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);

+

+#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400

+#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32  0x800

+

+static const char * const g_Dlls =

+  #ifndef _CONSOLE

+  "UXTHEME\0"

+  #endif

+  "USERENV\0"

+  "SETUPAPI\0"

+  "APPHELP\0"

+  "PROPSYS\0"

+  "DWMAPI\0"

+  "CRYPTBASE\0"

+  "OLEACC\0"

+  "CLBCATQ\0"

+  ;

+

+#endif

+

+void LoadSecurityDlls()

+{

+  #ifndef UNDER_CE

+  

+  wchar_t buf[MAX_PATH + 100];

+

+  {

+    // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???

+    OSVERSIONINFO vi;

+    vi.dwOSVersionInfoSize = sizeof(vi);

+    if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)

+    {

+      Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)

+          GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");

+      if (setDllDirs)

+        if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))

+          return;

+    }

+  }

+

+  {

+    unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2);

+    if (len == 0 || len > MAX_PATH)

+      return;

+  }

+  {

+    const char *dll;

+    unsigned pos = (unsigned)lstrlenW(buf);

+

+    if (buf[pos - 1] != '\\')

+      buf[pos++] = '\\';

+    

+    for (dll = g_Dlls; dll[0] != 0;)

+    {

+      unsigned k = 0;

+      for (;;)

+      {

+        char c = *dll++;

+        buf[pos + k] = c;

+        k++;

+        if (c == 0)

+          break;

+      }

+

+      lstrcatW(buf, L".dll");

+      LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);

+    }

+  }

+  

+  #endif

+}

+

+#endif

diff --git a/C/DllSecur.h b/C/DllSecur.h
new file mode 100644
index 0000000..023c509
--- /dev/null
+++ b/C/DllSecur.h
@@ -0,0 +1,19 @@
+/* DllSecur.h -- DLL loading for security

+2016-06-08 : Igor Pavlov : Public domain */

+

+#ifndef __DLL_SECUR_H

+#define __DLL_SECUR_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#ifdef _WIN32

+

+void LoadSecurityDlls();

+

+#endif

+

+EXTERN_C_END

+

+#endif

diff --git a/C/LzFind.c b/C/LzFind.c
index df79867..c335d36 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
 /* LzFind.c -- Match finder for LZ algorithms

-2009-04-22 : Igor Pavlov : Public domain */

+2015-10-15 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -11,8 +11,8 @@
 #define kEmptyHashValue 0

 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)

 #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */

-#define kNormalizeMask (~(kNormalizeStepMin - 1))

-#define kMaxHistorySize ((UInt32)3 << 30)

+#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))

+#define kMaxHistorySize ((UInt32)7 << 29)

 

 #define kStartMaxLen 3

 

@@ -21,7 +21,7 @@
   if (!p->directInput)

   {

     alloc->Free(alloc, p->bufferBase);

-    p->bufferBase = 0;

+    p->bufferBase = NULL;

   }

 }

 

@@ -35,17 +35,16 @@
     p->blockSize = blockSize;

     return 1;

   }

-  if (p->bufferBase == 0 || p->blockSize != blockSize)

+  if (!p->bufferBase || p->blockSize != blockSize)

   {

     LzInWindow_Free(p, alloc);

     p->blockSize = blockSize;

     p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);

   }

-  return (p->bufferBase != 0);

+  return (p->bufferBase != NULL);

 }

 

 Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }

-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }

 

 UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }

 

@@ -60,9 +59,12 @@
 {

   if (p->streamEndWasReached || p->result != SZ_OK)

     return;

+

+  /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */

+

   if (p->directInput)

   {

-    UInt32 curSize = 0xFFFFFFFF - p->streamPos;

+    UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);

     if (curSize > p->directInputRem)

       curSize = (UInt32)p->directInputRem;

     p->directInputRem -= curSize;

@@ -71,12 +73,14 @@
       p->streamEndWasReached = 1;

     return;

   }

+  

   for (;;)

   {

     Byte *dest = p->buffer + (p->streamPos - p->pos);

     size_t size = (p->bufferBase + p->blockSize - dest);

     if (size == 0)

       return;

+

     p->result = p->stream->Read(p->stream, dest, &size);

     if (p->result != SZ_OK)

       return;

@@ -94,8 +98,8 @@
 void MatchFinder_MoveBlock(CMatchFinder *p)

 {

   memmove(p->bufferBase,

-    p->buffer - p->keepSizeBefore,

-    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));

+      p->buffer - p->keepSizeBefore,

+      (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);

   p->buffer = p->bufferBase + p->keepSizeBefore;

 }

 

@@ -135,15 +139,15 @@
 void MatchFinder_Construct(CMatchFinder *p)

 {

   UInt32 i;

-  p->bufferBase = 0;

+  p->bufferBase = NULL;

   p->directInput = 0;

-  p->hash = 0;

+  p->hash = NULL;

   MatchFinder_SetDefaultSettings(p);

 

   for (i = 0; i < 256; i++)

   {

     UInt32 r = i;

-    int j;

+    unsigned j;

     for (j = 0; j < 8; j++)

       r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));

     p->crc[i] = r;

@@ -153,7 +157,7 @@
 static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)

 {

   alloc->Free(alloc, p->hash);

-  p->hash = 0;

+  p->hash = NULL;

 }

 

 void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)

@@ -162,11 +166,11 @@
   LzInWindow_Free(p, alloc);

 }

 

-static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)

+static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc)

 {

   size_t sizeInBytes = (size_t)num * sizeof(CLzRef);

   if (sizeInBytes / sizeof(CLzRef) != num)

-    return 0;

+    return NULL;

   return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);

 }

 

@@ -175,19 +179,24 @@
     ISzAlloc *alloc)

 {

   UInt32 sizeReserv;

+  

   if (historySize > kMaxHistorySize)

   {

     MatchFinder_Free(p, alloc);

     return 0;

   }

+  

   sizeReserv = historySize >> 1;

-  if (historySize > ((UInt32)2 << 30))

-    sizeReserv = historySize >> 2;

+       if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;

+  else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;

+  

   sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);

 

   p->keepSizeBefore = historySize + keepAddBufferBefore + 1;

   p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;

+  

   /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */

+  

   if (LzInWindow_Create(p, sizeReserv, alloc))

   {

     UInt32 newCyclicBufferSize = historySize + 1;

@@ -212,6 +221,7 @@
             hs = (1 << 24) - 1;

           else

             hs >>= 1;

+          /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */

         }

       }

       p->hashMask = hs;

@@ -223,24 +233,32 @@
     }

 

     {

-      UInt32 prevSize = p->hashSizeSum + p->numSons;

-      UInt32 newSize;

+      size_t newSize;

+      size_t numSons;

       p->historySize = historySize;

       p->hashSizeSum = hs;

       p->cyclicBufferSize = newCyclicBufferSize;

-      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);

-      newSize = p->hashSizeSum + p->numSons;

-      if (p->hash != 0 && prevSize == newSize)

+      

+      numSons = newCyclicBufferSize;

+      if (p->btMode)

+        numSons <<= 1;

+      newSize = hs + numSons;

+

+      if (p->hash && p->numRefs == newSize)

         return 1;

+      

       MatchFinder_FreeThisClassMemory(p, alloc);

+      p->numRefs = newSize;

       p->hash = AllocRefs(newSize, alloc);

-      if (p->hash != 0)

+      

+      if (p->hash)

       {

         p->son = p->hash + p->hashSizeSum;

         return 1;

       }

     }

   }

+

   MatchFinder_Free(p, alloc);

   return 0;

 }

@@ -249,9 +267,11 @@
 {

   UInt32 limit = kMaxValForNormalize - p->pos;

   UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;

+  

   if (limit2 < limit)

     limit = limit2;

   limit2 = p->streamPos - p->pos;

+  

   if (limit2 <= p->keepSizeAfter)

   {

     if (limit2 > 0)

@@ -259,8 +279,10 @@
   }

   else

     limit2 -= p->keepSizeAfter;

+  

   if (limit2 < limit)

     limit = limit2;

+  

   {

     UInt32 lenLimit = p->streamPos - p->pos;

     if (lenLimit > p->matchMaxLen)

@@ -270,28 +292,39 @@
   p->posLimit = p->pos + limit;

 }

 

-void MatchFinder_Init(CMatchFinder *p)

+void MatchFinder_Init_2(CMatchFinder *p, int readData)

 {

   UInt32 i;

-  for (i = 0; i < p->hashSizeSum; i++)

-    p->hash[i] = kEmptyHashValue;

+  UInt32 *hash = p->hash;

+  UInt32 num = p->hashSizeSum;

+  for (i = 0; i < num; i++)

+    hash[i] = kEmptyHashValue;

+  

   p->cyclicBufferPos = 0;

   p->buffer = p->bufferBase;

   p->pos = p->streamPos = p->cyclicBufferSize;

   p->result = SZ_OK;

   p->streamEndWasReached = 0;

-  MatchFinder_ReadBlock(p);

+  

+  if (readData)

+    MatchFinder_ReadBlock(p);

+  

   MatchFinder_SetLimits(p);

 }

 

+void MatchFinder_Init(CMatchFinder *p)

+{

+  MatchFinder_Init_2(p, True);

+}

+  

 static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)

 {

   return (p->pos - p->historySize - 1) & kNormalizeMask;

 }

 

-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)

+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)

 {

-  UInt32 i;

+  size_t i;

   for (i = 0; i < numItems; i++)

   {

     UInt32 value = items[i];

@@ -306,7 +339,7 @@
 static void MatchFinder_Normalize(CMatchFinder *p)

 {

   UInt32 subValue = MatchFinder_GetSubValue(p);

-  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);

+  MatchFinder_Normalize3(subValue, p->hash, p->numRefs);

   MatchFinder_ReduceOffsets(p, subValue);

 }

 

@@ -467,7 +500,7 @@
 static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }

 

 #define GET_MATCHES_HEADER2(minLen, ret_op) \

-  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \

+  UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \

   lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \

   cur = p->buffer;

 

@@ -483,13 +516,20 @@
 #define SKIP_FOOTER \

   SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;

 

+#define UPDATE_maxLen { \

+    ptrdiff_t diff = (ptrdiff_t)0 - d2; \

+    const Byte *c = cur + maxLen; \

+    const Byte *lim = cur + lenLimit; \

+    for (; c != lim; c++) if (*(c + diff) != *c) break; \

+    maxLen = (UInt32)(c - cur); }

+

 static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

 {

   UInt32 offset;

   GET_MATCHES_HEADER(2)

   HASH2_CALC;

-  curMatch = p->hash[hashValue];

-  p->hash[hashValue] = p->pos;

+  curMatch = p->hash[hv];

+  p->hash[hv] = p->pos;

   offset = 0;

   GET_MATCHES_FOOTER(offset, 1)

 }

@@ -499,35 +539,38 @@
   UInt32 offset;

   GET_MATCHES_HEADER(3)

   HASH_ZIP_CALC;

-  curMatch = p->hash[hashValue];

-  p->hash[hashValue] = p->pos;

+  curMatch = p->hash[hv];

+  p->hash[hv] = p->pos;

   offset = 0;

   GET_MATCHES_FOOTER(offset, 2)

 }

 

 static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

 {

-  UInt32 hash2Value, delta2, maxLen, offset;

+  UInt32 h2, d2, maxLen, offset, pos;

+  UInt32 *hash;

   GET_MATCHES_HEADER(3)

 

   HASH3_CALC;

 

-  delta2 = p->pos - p->hash[hash2Value];

-  curMatch = p->hash[kFix3HashSize + hashValue];

-  

-  p->hash[hash2Value] =

-  p->hash[kFix3HashSize + hashValue] = p->pos;

+  hash = p->hash;

+  pos = p->pos;

 

+  d2 = pos - hash[h2];

+

+  curMatch = hash[kFix3HashSize + hv];

+  

+  hash[h2] = pos;

+  hash[kFix3HashSize + hv] = pos;

 

   maxLen = 2;

   offset = 0;

-  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+

+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)

   {

-    for (; maxLen != lenLimit; maxLen++)

-      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

-        break;

+    UPDATE_maxLen

     distances[0] = maxLen;

-    distances[1] = delta2 - 1;

+    distances[1] = d2 - 1;

     offset = 2;

     if (maxLen == lenLimit)

     {

@@ -535,44 +578,51 @@
       MOVE_POS_RET;

     }

   }

+  

   GET_MATCHES_FOOTER(offset, maxLen)

 }

 

 static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

 {

-  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;

+  UInt32 h2, h3, d2, d3, maxLen, offset, pos;

+  UInt32 *hash;

   GET_MATCHES_HEADER(4)

 

   HASH4_CALC;

 

-  delta2 = p->pos - p->hash[                hash2Value];

-  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];

-  curMatch = p->hash[kFix4HashSize + hashValue];

-  

-  p->hash[                hash2Value] =

-  p->hash[kFix3HashSize + hash3Value] =

-  p->hash[kFix4HashSize + hashValue] = p->pos;

+  hash = p->hash;

+  pos = p->pos;

 

-  maxLen = 1;

+  d2 = pos - hash[                h2];

+  d3 = pos - hash[kFix3HashSize + h3];

+

+  curMatch = hash[kFix4HashSize + hv];

+

+  hash[                h2] = pos;

+  hash[kFix3HashSize + h3] = pos;

+  hash[kFix4HashSize + hv] = pos;

+

+  maxLen = 0;

   offset = 0;

-  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+  

+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)

   {

     distances[0] = maxLen = 2;

-    distances[1] = delta2 - 1;

+    distances[1] = d2 - 1;

     offset = 2;

   }

-  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)

+  

+  if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

   {

     maxLen = 3;

-    distances[offset + 1] = delta3 - 1;

+    distances[offset + 1] = d3 - 1;

     offset += 2;

-    delta2 = delta3;

+    d2 = d3;

   }

+  

   if (offset != 0)

   {

-    for (; maxLen != lenLimit; maxLen++)

-      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

-        break;

+    UPDATE_maxLen

     distances[offset - 2] = maxLen;

     if (maxLen == lenLimit)

     {

@@ -580,46 +630,131 @@
       MOVE_POS_RET;

     }

   }

+  

   if (maxLen < 3)

     maxLen = 3;

+  

   GET_MATCHES_FOOTER(offset, maxLen)

 }

 

+/*

+static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;

+  UInt32 *hash;

+  GET_MATCHES_HEADER(5)

+

+  HASH5_CALC;

+

+  hash = p->hash;

+  pos = p->pos;

+

+  d2 = pos - hash[                h2];

+  d3 = pos - hash[kFix3HashSize + h3];

+  d4 = pos - hash[kFix4HashSize + h4];

+

+  curMatch = hash[kFix5HashSize + hv];

+

+  hash[                h2] = pos;

+  hash[kFix3HashSize + h3] = pos;

+  hash[kFix4HashSize + h4] = pos;

+  hash[kFix5HashSize + hv] = pos;

+

+  maxLen = 0;

+  offset = 0;

+

+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)

+  {

+    distances[0] = maxLen = 2;

+    distances[1] = d2 - 1;

+    offset = 2;

+    if (*(cur - d2 + 2) == cur[2])

+      distances[0] = maxLen = 3;

+    else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

+    {

+      distances[2] = maxLen = 3;

+      distances[3] = d3 - 1;

+      offset = 4;

+      d2 = d3;

+    }

+  }

+  else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

+  {

+    distances[0] = maxLen = 3;

+    distances[1] = d3 - 1;

+    offset = 2;

+    d2 = d3;

+  }

+  

+  if (d2 != d4 && d4 < p->cyclicBufferSize

+      && *(cur - d4) == *cur

+      && *(cur - d4 + 3) == *(cur + 3))

+  {

+    maxLen = 4;

+    distances[offset + 1] = d4 - 1;

+    offset += 2;

+    d2 = d4;

+  }

+  

+  if (offset != 0)

+  {

+    UPDATE_maxLen

+    distances[offset - 2] = maxLen;

+    if (maxLen == lenLimit)

+    {

+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));

+      MOVE_POS_RET;

+    }

+  }

+

+  if (maxLen < 4)

+    maxLen = 4;

+  

+  GET_MATCHES_FOOTER(offset, maxLen)

+}

+*/

+

 static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

 {

-  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;

+  UInt32 h2, h3, d2, d3, maxLen, offset, pos;

+  UInt32 *hash;

   GET_MATCHES_HEADER(4)

 

   HASH4_CALC;

 

-  delta2 = p->pos - p->hash[                hash2Value];

-  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];

-  curMatch = p->hash[kFix4HashSize + hashValue];

+  hash = p->hash;

+  pos = p->pos;

+  

+  d2 = pos - hash[                h2];

+  d3 = pos - hash[kFix3HashSize + h3];

+  

+  curMatch = hash[kFix4HashSize + hv];

 

-  p->hash[                hash2Value] =

-  p->hash[kFix3HashSize + hash3Value] =

-  p->hash[kFix4HashSize + hashValue] = p->pos;

+  hash[                h2] = pos;

+  hash[kFix3HashSize + h3] = pos;

+  hash[kFix4HashSize + hv] = pos;

 

-  maxLen = 1;

+  maxLen = 0;

   offset = 0;

-  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+

+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)

   {

     distances[0] = maxLen = 2;

-    distances[1] = delta2 - 1;

+    distances[1] = d2 - 1;

     offset = 2;

   }

-  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)

+  

+  if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

   {

     maxLen = 3;

-    distances[offset + 1] = delta3 - 1;

+    distances[offset + 1] = d3 - 1;

     offset += 2;

-    delta2 = delta3;

+    d2 = d3;

   }

+  

   if (offset != 0)

   {

-    for (; maxLen != lenLimit; maxLen++)

-      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

-        break;

+    UPDATE_maxLen

     distances[offset - 2] = maxLen;

     if (maxLen == lenLimit)

     {

@@ -627,22 +762,103 @@
       MOVE_POS_RET;

     }

   }

+  

   if (maxLen < 3)

     maxLen = 3;

+

   offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),

-    distances + offset, maxLen) - (distances));

+      distances + offset, maxLen) - (distances));

   MOVE_POS_RET

 }

 

+/*

+static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos

+  UInt32 *hash;

+  GET_MATCHES_HEADER(5)

+

+  HASH5_CALC;

+

+  hash = p->hash;

+  pos = p->pos;

+  

+  d2 = pos - hash[                h2];

+  d3 = pos - hash[kFix3HashSize + h3];

+  d4 = pos - hash[kFix4HashSize + h4];

+

+  curMatch = hash[kFix5HashSize + hv];

+

+  hash[                h2] = pos;

+  hash[kFix3HashSize + h3] = pos;

+  hash[kFix4HashSize + h4] = pos;

+  hash[kFix5HashSize + hv] = pos;

+

+  maxLen = 0;

+  offset = 0;

+

+  if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)

+  {

+    distances[0] = maxLen = 2;

+    distances[1] = d2 - 1;

+    offset = 2;

+    if (*(cur - d2 + 2) == cur[2])

+      distances[0] = maxLen = 3;

+    else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

+    {

+      distances[2] = maxLen = 3;

+      distances[3] = d3 - 1;

+      offset = 4;

+      d2 = d3;

+    }

+  }

+  else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)

+  {

+    distances[0] = maxLen = 3;

+    distances[1] = d3 - 1;

+    offset = 2;

+    d2 = d3;

+  }

+  

+  if (d2 != d4 && d4 < p->cyclicBufferSize

+      && *(cur - d4) == *cur

+      && *(cur - d4 + 3) == *(cur + 3))

+  {

+    maxLen = 4;

+    distances[offset + 1] = d4 - 1;

+    offset += 2;

+    d2 = d4;

+  }

+  

+  if (offset != 0)

+  {

+    UPDATE_maxLen

+    distances[offset - 2] = maxLen;

+    if (maxLen == lenLimit)

+    {

+      p->son[p->cyclicBufferPos] = curMatch;

+      MOVE_POS_RET;

+    }

+  }

+  

+  if (maxLen < 4)

+    maxLen = 4;

+

+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),

+      distances + offset, maxLen) - (distances));

+  MOVE_POS_RET

+}

+*/

+

 UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

 {

   UInt32 offset;

   GET_MATCHES_HEADER(3)

   HASH_ZIP_CALC;

-  curMatch = p->hash[hashValue];

-  p->hash[hashValue] = p->pos;

+  curMatch = p->hash[hv];

+  p->hash[hv] = p->pos;

   offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),

-    distances, 2) - (distances));

+      distances, 2) - (distances));

   MOVE_POS_RET

 }

 

@@ -652,8 +868,8 @@
   {

     SKIP_HEADER(2)

     HASH2_CALC;

-    curMatch = p->hash[hashValue];

-    p->hash[hashValue] = p->pos;

+    curMatch = p->hash[hv];

+    p->hash[hv] = p->pos;

     SKIP_FOOTER

   }

   while (--num != 0);

@@ -665,8 +881,8 @@
   {

     SKIP_HEADER(3)

     HASH_ZIP_CALC;

-    curMatch = p->hash[hashValue];

-    p->hash[hashValue] = p->pos;

+    curMatch = p->hash[hv];

+    p->hash[hv] = p->pos;

     SKIP_FOOTER

   }

   while (--num != 0);

@@ -676,12 +892,14 @@
 {

   do

   {

-    UInt32 hash2Value;

+    UInt32 h2;

+    UInt32 *hash;

     SKIP_HEADER(3)

     HASH3_CALC;

-    curMatch = p->hash[kFix3HashSize + hashValue];

-    p->hash[hash2Value] =

-    p->hash[kFix3HashSize + hashValue] = p->pos;

+    hash = p->hash;

+    curMatch = hash[kFix3HashSize + hv];

+    hash[h2] =

+    hash[kFix3HashSize + hv] = p->pos;

     SKIP_FOOTER

   }

   while (--num != 0);

@@ -691,43 +909,90 @@
 {

   do

   {

-    UInt32 hash2Value, hash3Value;

+    UInt32 h2, h3;

+    UInt32 *hash;

     SKIP_HEADER(4)

     HASH4_CALC;

-    curMatch = p->hash[kFix4HashSize + hashValue];

-    p->hash[                hash2Value] =

-    p->hash[kFix3HashSize + hash3Value] = p->pos;

-    p->hash[kFix4HashSize + hashValue] = p->pos;

+    hash = p->hash;

+    curMatch = hash[kFix4HashSize + hv];

+    hash[                h2] =

+    hash[kFix3HashSize + h3] =

+    hash[kFix4HashSize + hv] = p->pos;

     SKIP_FOOTER

   }

   while (--num != 0);

 }

 

+/*

+static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    UInt32 h2, h3, h4;

+    UInt32 *hash;

+    SKIP_HEADER(5)

+    HASH5_CALC;

+    hash = p->hash;

+    curMatch = hash[kFix5HashSize + hv];

+    hash[                h2] =

+    hash[kFix3HashSize + h3] =

+    hash[kFix4HashSize + h4] =

+    hash[kFix5HashSize + hv] = p->pos;

+    SKIP_FOOTER

+  }

+  while (--num != 0);

+}

+*/

+

 static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

 {

   do

   {

-    UInt32 hash2Value, hash3Value;

+    UInt32 h2, h3;

+    UInt32 *hash;

     SKIP_HEADER(4)

     HASH4_CALC;

-    curMatch = p->hash[kFix4HashSize + hashValue];

-    p->hash[                hash2Value] =

-    p->hash[kFix3HashSize + hash3Value] =

-    p->hash[kFix4HashSize + hashValue] = p->pos;

+    hash = p->hash;

+    curMatch = hash[kFix4HashSize + hv];

+    hash[                h2] =

+    hash[kFix3HashSize + h3] =

+    hash[kFix4HashSize + hv] = p->pos;

     p->son[p->cyclicBufferPos] = curMatch;

     MOVE_POS

   }

   while (--num != 0);

 }

 

+/*

+static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    UInt32 h2, h3, h4;

+    UInt32 *hash;

+    SKIP_HEADER(5)

+    HASH5_CALC;

+    hash = p->hash;

+    curMatch = p->hash[kFix5HashSize + hv];

+    hash[                h2] =

+    hash[kFix3HashSize + h3] =

+    hash[kFix4HashSize + h4] =

+    hash[kFix5HashSize + hv] = p->pos;

+    p->son[p->cyclicBufferPos] = curMatch;

+    MOVE_POS

+  }

+  while (--num != 0);

+}

+*/

+

 void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

 {

   do

   {

     SKIP_HEADER(3)

     HASH_ZIP_CALC;

-    curMatch = p->hash[hashValue];

-    p->hash[hashValue] = p->pos;

+    curMatch = p->hash[hv];

+    p->hash[hv] = p->pos;

     p->son[p->cyclicBufferPos] = curMatch;

     MOVE_POS

   }

@@ -737,13 +1002,22 @@
 void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)

 {

   vTable->Init = (Mf_Init_Func)MatchFinder_Init;

-  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;

   vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;

   vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;

   if (!p->btMode)

   {

-    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;

-    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;

+    /* if (p->numHashBytes <= 4) */

+    {

+      vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;

+      vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;

+    }

+    /*

+    else

+    {

+      vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;

+      vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;

+    }

+    */

   }

   else if (p->numHashBytes == 2)

   {

@@ -755,9 +1029,16 @@
     vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;

     vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;

   }

-  else

+  else /* if (p->numHashBytes == 4) */

   {

     vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;

     vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;

   }

+  /*

+  else

+  {

+    vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;

+    vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;

+  }

+  */

 }

diff --git a/C/LzFind.h b/C/LzFind.h
index bad5000..2ff6673 100644
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,5 +1,5 @@
 /* LzFind.h -- Match finder for LZ algorithms

-2013-01-18 : Igor Pavlov : Public domain */

+2015-10-15 : Igor Pavlov : Public domain */

 

 #ifndef __LZ_FIND_H

 #define __LZ_FIND_H

@@ -21,6 +21,11 @@
   UInt32 cyclicBufferPos;

   UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */

 

+  Byte streamEndWasReached;

+  Byte btMode;

+  Byte bigHash;

+  Byte directInput;

+

   UInt32 matchMaxLen;

   CLzRef *hash;

   CLzRef *son;

@@ -29,30 +34,30 @@
 

   Byte *bufferBase;

   ISeqInStream *stream;

-  int streamEndWasReached;

-

+  

   UInt32 blockSize;

   UInt32 keepSizeBefore;

   UInt32 keepSizeAfter;

 

   UInt32 numHashBytes;

-  int directInput;

   size_t directInputRem;

-  int btMode;

-  int bigHash;

   UInt32 historySize;

   UInt32 fixedHashSize;

   UInt32 hashSizeSum;

-  UInt32 numSons;

   SRes result;

   UInt32 crc[256];

+  size_t numRefs;

 } CMatchFinder;

 

 #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)

-#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])

 

 #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)

 

+#define Inline_MatchFinder_IsFinishedOK(p) \

+    ((p)->streamEndWasReached \

+        && (p)->streamPos == (p)->pos \

+        && (!(p)->directInput || (p)->directInputRem == 0))

+      

 int MatchFinder_NeedMove(CMatchFinder *p);

 Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);

 void MatchFinder_MoveBlock(CMatchFinder *p);

@@ -68,7 +73,7 @@
     UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,

     ISzAlloc *alloc);

 void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);

-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);

+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);

 void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);

 

 UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,

@@ -82,7 +87,6 @@
 */

 

 typedef void (*Mf_Init_Func)(void *object);

-typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);

 typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);

 typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);

 typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);

@@ -91,7 +95,6 @@
 typedef struct _IMatchFinder

 {

   Mf_Init_Func Init;

-  Mf_GetIndexByte_Func GetIndexByte;

   Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;

   Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;

   Mf_GetMatches_Func GetMatches;

@@ -100,9 +103,12 @@
 

 void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);

 

+void MatchFinder_Init_2(CMatchFinder *p, int readData);

 void MatchFinder_Init(CMatchFinder *p);

+

 UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

 UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

+

 void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

 void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

 

diff --git a/C/LzFindMt.c b/C/LzFindMt.c
index 5356d4a..cb61e09 100644
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,5 @@
 /* LzFindMt.c -- multithreaded Match finder for LZ algorithms

-2014-12-29 : Igor Pavlov : Public domain */

+2015-10-15 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -7,7 +7,7 @@
 

 #include "LzFindMt.h"

 

-void MtSync_Construct(CMtSync *p)

+static void MtSync_Construct(CMtSync *p)

 {

   p->wasCreated = False;

   p->csWasInitialized = False;

@@ -20,7 +20,7 @@
   Semaphore_Construct(&p->filledSemaphore);

 }

 

-void MtSync_GetNextBlock(CMtSync *p)

+static void MtSync_GetNextBlock(CMtSync *p)

 {

   if (p->needStart)

   {

@@ -48,7 +48,7 @@
 

 /* MtSync_StopWriting must be called if Writing was started */

 

-void MtSync_StopWriting(CMtSync *p)

+static void MtSync_StopWriting(CMtSync *p)

 {

   UInt32 myNumBlocks = p->numProcessedBlocks;

   if (!Thread_WasCreated(&p->thread) || p->needStart)

@@ -71,7 +71,7 @@
   p->needStart = True;

 }

 

-void MtSync_Destruct(CMtSync *p)

+static void MtSync_Destruct(CMtSync *p)

 {

   if (Thread_WasCreated(&p->thread))

   {

@@ -134,20 +134,20 @@
 #define kMtMaxValForNormalize 0xFFFFFFFF

 

 #define DEF_GetHeads2(name, v, action) \

-static void GetHeads ## name(const Byte *p, UInt32 pos, \

-UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \

-{ action; for (; numHeads != 0; numHeads--) { \

-const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++;  } }

+  static void GetHeads ## name(const Byte *p, UInt32 pos, \

+      UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \

+    { action; for (; numHeads != 0; numHeads--) { \

+      const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++;  } }

 

 #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)

 

-DEF_GetHeads2(2,  (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )

+DEF_GetHeads2(2,  (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )

 DEF_GetHeads(3,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)

 DEF_GetHeads(4,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)

 DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)

 /* DEF_GetHeads(5,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */

 

-void HashThreadFunc(CMatchFinderMt *mt)

+static void HashThreadFunc(CMatchFinderMt *mt)

 {

   CMtSync *p = &mt->hashSync;

   for (;;)

@@ -173,12 +173,12 @@
           CriticalSection_Enter(&mt->btSync.cs);

           CriticalSection_Enter(&mt->hashSync.cs);

           {

-            const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);

-            const Byte *afterPtr;

+            const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);

+            ptrdiff_t offset;

             MatchFinder_MoveBlock(mf);

-            afterPtr = MatchFinder_GetPointerToCurrentPos(mf);

-            mt->pointerToCurPos -= beforePtr - afterPtr;

-            mt->buffer -= beforePtr - afterPtr;

+            offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);

+            mt->pointerToCurPos -= offset;

+            mt->buffer -= offset;

           }

           CriticalSection_Leave(&mt->btSync.cs);

           CriticalSection_Leave(&mt->hashSync.cs);

@@ -192,7 +192,7 @@
         {

           UInt32 subValue = (mf->pos - mf->historySize - 1);

           MatchFinder_ReduceOffsets(mf, subValue);

-          MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);

+          MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);

         }

         {

           UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;

@@ -217,7 +217,7 @@
   }

 }

 

-void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)

+static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)

 {

   MtSync_GetNextBlock(&p->hashSync);

   p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;

@@ -233,7 +233,7 @@
 

 #define NO_INLINE MY_FAST_CALL

 

-Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,

+static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,

     UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,

     UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)

 {

@@ -310,12 +310,14 @@
 

 #endif

 

-void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)

+static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)

 {

   UInt32 numProcessed = 0;

   UInt32 curPos = 2;

   UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);

+  

   distances[1] = p->hashNumAvail;

+  

   while (curPos < limit)

   {

     if (p->hashBufPos == p->hashBufPosLimit)

@@ -324,9 +326,11 @@
       distances[1] = numProcessed + p->hashNumAvail;

       if (p->hashNumAvail >= p->numHashBytes)

         continue;

+      distances[0] = curPos + p->hashNumAvail;

+      distances += curPos;

       for (; p->hashNumAvail != 0; p->hashNumAvail--)

-        distances[curPos++] = 0;

-      break;

+        *distances++ = 0;

+      return;

     }

     {

       UInt32 size = p->hashBufPosLimit - p->hashBufPos;

@@ -343,13 +347,14 @@
         if (size2 < size)

           size = size2;

       }

+      

       #ifndef MFMT_GM_INLINE

       while (curPos < limit && size-- != 0)

       {

         UInt32 *startDistances = distances + curPos;

         UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],

-          pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,

-          startDistances + 1, p->numHashBytes - 1) - startDistances);

+            pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,

+            startDistances + 1, p->numHashBytes - 1) - startDistances);

         *startDistances = num - 1;

         curPos += num;

         cyclicBufferPos++;

@@ -360,7 +365,7 @@
       {

         UInt32 posRes;

         curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,

-          distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);

+            distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);

         p->hashBufPos += posRes - pos;

         cyclicBufferPos += posRes - pos;

         p->buffer += posRes - pos;

@@ -376,10 +381,11 @@
       p->cyclicBufferPos = cyclicBufferPos;

     }

   }

+  

   distances[0] = curPos;

 }

 

-void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)

+static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)

 {

   CMtSync *sync = &p->hashSync;

   if (!sync->needStart)

@@ -393,7 +399,7 @@
   if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)

   {

     UInt32 subValue = p->pos - p->cyclicBufferSize;

-    MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);

+    MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);

     p->pos -= subValue;

   }

 

@@ -432,15 +438,15 @@
 

 void MatchFinderMt_Construct(CMatchFinderMt *p)

 {

-  p->hashBuf = 0;

+  p->hashBuf = NULL;

   MtSync_Construct(&p->hashSync);

   MtSync_Construct(&p->btSync);

 }

 

-void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)

+static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)

 {

   alloc->Free(alloc, p->hashBuf);

-  p->hashBuf = 0;

+  p->hashBuf = NULL;

 }

 

 void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)

@@ -457,9 +463,11 @@
 static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)

 {

   Byte allocaDummy[0x180];

-  allocaDummy[0] = 0;

-  allocaDummy[1] = allocaDummy[0];

-  BtThreadFunc((CMatchFinderMt *)p);

+  unsigned i = 0;

+  for (i = 0; i < 16; i++)

+    allocaDummy[i] = (Byte)0;

+  if (allocaDummy[0] == 0)

+    BtThreadFunc((CMatchFinderMt *)p);

   return 0;

 }

 

@@ -470,10 +478,10 @@
   p->historySize = historySize;

   if (kMtBtBlockSize <= matchMaxLen * 4)

     return SZ_ERROR_PARAM;

-  if (p->hashBuf == 0)

+  if (!p->hashBuf)

   {

     p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));

-    if (p->hashBuf == 0)

+    if (!p->hashBuf)

       return SZ_ERROR_MEM;

     p->btBuf = p->hashBuf + kHashBufferSize;

   }

@@ -493,8 +501,11 @@
   CMatchFinder *mf = p->MatchFinder;

   p->btBufPos = p->btBufPosLimit = 0;

   p->hashBufPos = p->hashBufPosLimit = 0;

-  MatchFinder_Init(mf);

-  p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);

+

+  /* Init without data reading. We don't want to read data in this thread */

+  MatchFinder_Init_2(mf, False);

+  

+  p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);

   p->btNumAvailBytes = 0;

   p->lzPos = p->historySize + 1;

 

@@ -519,13 +530,13 @@
   /* p->MatchFinder->ReleaseStream(); */

 }

 

-void MatchFinderMt_Normalize(CMatchFinderMt *p)

+static void MatchFinderMt_Normalize(CMatchFinderMt *p)

 {

   MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);

   p->lzPos = p->historySize + 1;

 }

 

-void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)

+static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)

 {

   UInt32 blockIndex;

   MtSync_GetNextBlock(&p->btSync);

@@ -537,34 +548,29 @@
     MatchFinderMt_Normalize(p);

 }

 

-const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)

+static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)

 {

   return p->pointerToCurPos;

 }

 

 #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);

 

-UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)

+static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)

 {

   GET_NEXT_BLOCK_IF_REQUIRED;

   return p->btNumAvailBytes;

 }

 

-Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)

+static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

 {

-  return p->pointerToCurPos[index];

-}

-

-UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

-{

-  UInt32 hash2Value, curMatch2;

+  UInt32 h2, curMatch2;

   UInt32 *hash = p->hash;

   const Byte *cur = p->pointerToCurPos;

   UInt32 lzPos = p->lzPos;

   MT_HASH2_CALC

       

-  curMatch2 = hash[hash2Value];

-  hash[hash2Value] = lzPos;

+  curMatch2 = hash[h2];

+  hash[h2] = lzPos;

 

   if (curMatch2 >= matchMinPos)

     if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

@@ -572,23 +578,23 @@
       *distances++ = 2;

       *distances++ = lzPos - curMatch2 - 1;

     }

+  

   return distances;

 }

 

-UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

+static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

 {

-  UInt32 hash2Value, hash3Value, curMatch2, curMatch3;

+  UInt32 h2, h3, curMatch2, curMatch3;

   UInt32 *hash = p->hash;

   const Byte *cur = p->pointerToCurPos;

   UInt32 lzPos = p->lzPos;

   MT_HASH3_CALC

 

-  curMatch2 = hash[                hash2Value];

-  curMatch3 = hash[kFix3HashSize + hash3Value];

+  curMatch2 = hash[                h2];

+  curMatch3 = hash[kFix3HashSize + h3];

   

-  hash[                hash2Value] =

-  hash[kFix3HashSize + hash3Value] =

-    lzPos;

+  hash[                h2] = lzPos;

+  hash[kFix3HashSize + h3] = lzPos;

 

   if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

   {

@@ -601,43 +607,45 @@
     distances[0] = 2;

     distances += 2;

   }

+  

   if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])

   {

     *distances++ = 3;

     *distances++ = lzPos - curMatch3 - 1;

   }

+  

   return distances;

 }

 

 /*

-UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

+static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

 {

-  UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;

+  UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;

   UInt32 *hash = p->hash;

   const Byte *cur = p->pointerToCurPos;

   UInt32 lzPos = p->lzPos;

   MT_HASH4_CALC

       

-  curMatch2 = hash[                hash2Value];

-  curMatch3 = hash[kFix3HashSize + hash3Value];

-  curMatch4 = hash[kFix4HashSize + hash4Value];

+  curMatch2 = hash[                h2];

+  curMatch3 = hash[kFix3HashSize + h3];

+  curMatch4 = hash[kFix4HashSize + h4];

   

-  hash[                hash2Value] =

-  hash[kFix3HashSize + hash3Value] =

-  hash[kFix4HashSize + hash4Value] =

-    lzPos;

+  hash[                h2] = lzPos;

+  hash[kFix3HashSize + h3] = lzPos;

+  hash[kFix4HashSize + h4] = lzPos;

 

   if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

   {

     distances[1] = lzPos - curMatch2 - 1;

     if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])

     {

-      distances[0] =  (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;

+      distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;

       return distances + 2;

     }

     distances[0] = 2;

     distances += 2;

   }

+  

   if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])

   {

     distances[1] = lzPos - curMatch3 - 1;

@@ -659,13 +667,14 @@
       *distances++ = 4;

       *distances++ = lzPos - curMatch4 - 1;

     }

+  

   return distances;

 }

 */

 

 #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;

 

-UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)

+static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)

 {

   const UInt32 *btBuf = p->btBuf + p->btBufPos;

   UInt32 len = *btBuf++;

@@ -683,7 +692,7 @@
   return len;

 }

 

-UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)

+static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)

 {

   const UInt32 *btBuf = p->btBuf + p->btBufPos;

   UInt32 len = *btBuf++;

@@ -691,6 +700,7 @@
 

   if (len == 0)

   {

+    /* change for bt5 ! */

     if (p->btNumAvailBytes-- >= 4)

       len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));

   }

@@ -706,7 +716,7 @@
       *distances2++ = *btBuf++;

     }

     while ((len -= 2) != 0);

-    len  = (UInt32)(distances2 - (distances));

+    len = (UInt32)(distances2 - (distances));

   }

   INCREASE_LZ_POS

   return len;

@@ -716,41 +726,41 @@
 #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;

 #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);

 

-void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)

+static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)

 {

   SKIP_HEADER2_MT { p->btNumAvailBytes--;

   SKIP_FOOTER_MT

 }

 

-void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)

+static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)

 {

   SKIP_HEADER_MT(2)

-      UInt32 hash2Value;

+      UInt32 h2;

       MT_HASH2_CALC

-      hash[hash2Value] = p->lzPos;

+      hash[h2] = p->lzPos;

   SKIP_FOOTER_MT

 }

 

-void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)

+static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)

 {

   SKIP_HEADER_MT(3)

-      UInt32 hash2Value, hash3Value;

+      UInt32 h2, h3;

       MT_HASH3_CALC

-      hash[kFix3HashSize + hash3Value] =

-      hash[                hash2Value] =

+      hash[kFix3HashSize + h3] =

+      hash[                h2] =

         p->lzPos;

   SKIP_FOOTER_MT

 }

 

 /*

-void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)

+static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)

 {

   SKIP_HEADER_MT(4)

-      UInt32 hash2Value, hash3Value, hash4Value;

+      UInt32 h2, h3, h4;

       MT_HASH4_CALC

-      hash[kFix4HashSize + hash4Value] =

-      hash[kFix3HashSize + hash3Value] =

-      hash[                hash2Value] =

+      hash[kFix4HashSize + h4] =

+      hash[kFix3HashSize + h3] =

+      hash[                h2] =

         p->lzPos;

   SKIP_FOOTER_MT

 }

@@ -759,11 +769,11 @@
 void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)

 {

   vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;

-  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;

   vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;

   vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;

   vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;

-  switch(p->MatchFinder->numHashBytes)

+  

+  switch (p->MatchFinder->numHashBytes)

   {

     case 2:

       p->GetHeadsFunc = GetHeads2;

@@ -779,7 +789,6 @@
     default:

     /* case 4: */

       p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;

-      /* p->GetHeadsFunc = GetHeads4; */

       p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;

       vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;

       break;

diff --git a/C/LzFindMt.h b/C/LzFindMt.h
index 320d87c..46b6924 100644
--- a/C/LzFindMt.h
+++ b/C/LzFindMt.h
@@ -1,5 +1,5 @@
 /* LzFindMt.h -- multithreaded Match finder for LZ algorithms

-2013-01-18 : Igor Pavlov : Public domain */

+2015-05-03 : Igor Pavlov : Public domain */

 

 #ifndef __LZ_FIND_MT_H

 #define __LZ_FIND_MT_H

@@ -75,7 +75,7 @@
   UInt32 matchMaxLen;

   UInt32 numHashBytes;

   UInt32 pos;

-  Byte *buffer;

+  const Byte *buffer;

   UInt32 cyclicBufferPos;

   UInt32 cyclicBufferSize; /* it must be historySize + 1 */

   UInt32 cutValue;

diff --git a/C/LzHash.h b/C/LzHash.h
index b2f0e3c..2191444 100644
--- a/C/LzHash.h
+++ b/C/LzHash.h
@@ -1,5 +1,5 @@
 /* LzHash.h -- HASH functions for LZ algorithms

-2009-02-07 : Igor Pavlov : Public domain */

+2015-04-12 : Igor Pavlov : Public domain */

 

 #ifndef __LZ_HASH_H

 #define __LZ_HASH_H

@@ -12,43 +12,46 @@
 #define kFix4HashSize (kHash2Size + kHash3Size)

 #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)

 

-#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);

+#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);

 

 #define HASH3_CALC { \

   UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

-  hash2Value = temp & (kHash2Size - 1); \

-  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }

+  h2 = temp & (kHash2Size - 1); \

+  hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }

 

 #define HASH4_CALC { \

   UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

-  hash2Value = temp & (kHash2Size - 1); \

-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

-  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }

+  h2 = temp & (kHash2Size - 1); \

+  temp ^= ((UInt32)cur[2] << 8); \

+  h3 = temp & (kHash3Size - 1); \

+  hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }

 

 #define HASH5_CALC { \

   UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

-  hash2Value = temp & (kHash2Size - 1); \

-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

-  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \

-  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \

-  hash4Value &= (kHash4Size - 1); }

+  h2 = temp & (kHash2Size - 1); \

+  temp ^= ((UInt32)cur[2] << 8); \

+  h3 = temp & (kHash3Size - 1); \

+  temp ^= (p->crc[cur[3]] << 5); \

+  h4 = temp & (kHash4Size - 1); \

+  hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }

 

-/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */

-#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;

+/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */

+#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;

 

 

 #define MT_HASH2_CALC \

-  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);

+  h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);

 

 #define MT_HASH3_CALC { \

   UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

-  hash2Value = temp & (kHash2Size - 1); \

-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }

+  h2 = temp & (kHash2Size - 1); \

+  h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }

 

 #define MT_HASH4_CALC { \

   UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

-  hash2Value = temp & (kHash2Size - 1); \

-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

-  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }

+  h2 = temp & (kHash2Size - 1); \

+  temp ^= ((UInt32)cur[2] << 8); \

+  h3 = temp & (kHash3Size - 1); \

+  h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }

 

 #endif

diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
index ed91619..b688457 100644
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -1,5 +1,5 @@
 /* Lzma2Dec.c -- LZMA2 Decoder

-2010-12-15 : Igor Pavlov : Public domain */

+2015-11-09 : Igor Pavlov : Public domain */

 

 /* #define SHOW_DEBUG_INFO */

 

@@ -99,12 +99,12 @@
 

 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)

 {

-  switch(p->state)

+  switch (p->state)

   {

     case LZMA2_STATE_CONTROL:

       p->control = b;

-      PRF(printf("\n %4X ", p->decoder.dicPos));

-      PRF(printf(" %2X", b));

+      PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));

+      PRF(printf(" %2X", (unsigned)b));

       if (p->control == 0)

         return LZMA2_STATE_FINISHED;

       if (LZMA2_IS_UNCOMPRESSED_STATE(p))

@@ -124,7 +124,7 @@
     case LZMA2_STATE_UNPACK1:

       p->unpackSize |= (UInt32)b;

       p->unpackSize++;

-      PRF(printf(" %8d", p->unpackSize));

+      PRF(printf(" %8u", (unsigned)p->unpackSize));

       return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;

     

     case LZMA2_STATE_PACK0:

@@ -134,13 +134,13 @@
     case LZMA2_STATE_PACK1:

       p->packSize |= (UInt32)b;

       p->packSize++;

-      PRF(printf(" %8d", p->packSize));

+      PRF(printf(" %8u", (unsigned)p->packSize));

       return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:

         (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);

 

     case LZMA2_STATE_PROP:

     {

-      int lc, lp;

+      unsigned lc, lp;

       if (b >= (9 * 5 * 5))

         return LZMA2_STATE_ERROR;

       lc = b % 9;

@@ -179,13 +179,16 @@
   while (p->state != LZMA2_STATE_FINISHED)

   {

     SizeT dicPos = p->decoder.dicPos;

+    

     if (p->state == LZMA2_STATE_ERROR)

       return SZ_ERROR_DATA;

+    

     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)

     {

       *status = LZMA_STATUS_NOT_FINISHED;

       return SZ_OK;

     }

+

     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)

     {

       if (*srcLen == inSize)

@@ -195,8 +198,15 @@
       }

       (*srcLen)++;

       p->state = Lzma2Dec_UpdateState(p, *src++);

+

+      if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)

+      {

+        p->state = LZMA2_STATE_ERROR;

+        return SZ_ERROR_DATA;

+      }

       continue;

     }

+    

     {

       SizeT destSizeCur = dicLimit - dicPos;

       SizeT srcSizeCur = inSize - *srcLen;

@@ -222,7 +232,10 @@
           if (initDic)

             p->needInitProp = p->needInitState = True;

           else if (p->needInitDic)

+          {

+            p->state = LZMA2_STATE_ERROR;

             return SZ_ERROR_DATA;

+          }

           p->needInitDic = False;

           LzmaDec_InitDicAndState(&p->decoder, initDic, False);

         }

@@ -231,7 +244,10 @@
           srcSizeCur = destSizeCur;

 

         if (srcSizeCur == 0)

+        {

+          p->state = LZMA2_STATE_ERROR;

           return SZ_ERROR_DATA;

+        }

 

         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);

 

@@ -247,17 +263,21 @@
 

         if (p->state == LZMA2_STATE_DATA)

         {

-          int mode = LZMA2_GET_LZMA_MODE(p);

+          unsigned mode = LZMA2_GET_LZMA_MODE(p);

           Bool initDic = (mode == 3);

-          Bool initState = (mode > 0);

+          Bool initState = (mode != 0);

           if ((!initDic && p->needInitDic) || (!initState && p->needInitState))

+          {

+            p->state = LZMA2_STATE_ERROR;

             return SZ_ERROR_DATA;

+          }

           

           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);

           p->needInitDic = False;

           p->needInitState = False;

           p->state = LZMA2_STATE_DATA_CONT;

         }

+  

         if (srcSizeCur > p->packSize)

           srcSizeCur = (SizeT)p->packSize;

           

@@ -276,16 +296,22 @@
 

         if (srcSizeCur == 0 && outSizeProcessed == 0)

         {

-          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||

-              p->unpackSize != 0 || p->packSize != 0)

+          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

+              || p->unpackSize != 0

+              || p->packSize != 0)

+          {

+            p->state = LZMA2_STATE_ERROR;

             return SZ_ERROR_DATA;

+          }

           p->state = LZMA2_STATE_CONTROL;

         }

+        

         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)

           *status = LZMA_STATUS_NOT_FINISHED;

       }

     }

   }

+  

   *status = LZMA_STATUS_FINISHED_WITH_MARK;

   return SZ_OK;

 }

diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
index 9254523..026cdef 100644
--- a/C/Lzma2Dec.h
+++ b/C/Lzma2Dec.h
@@ -1,5 +1,5 @@
 /* Lzma2Dec.h -- LZMA2 Decoder

-2013-01-18 : Igor Pavlov : Public domain */

+2015-05-13 : Igor Pavlov : Public domain */

 

 #ifndef __LZMA2_DEC_H

 #define __LZMA2_DEC_H

@@ -15,7 +15,7 @@
   CLzmaDec decoder;

   UInt32 packSize;

   UInt32 unpackSize;

-  int state;

+  unsigned state;

   Byte control;

   Bool needInitDic;

   Bool needInitState;

diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
index 1627bae..cba0134 100644
--- a/C/Lzma2Enc.c
+++ b/C/Lzma2Enc.c
@@ -1,5 +1,5 @@
 /* Lzma2Enc.c -- LZMA2 Encoder

-2012-06-19 : Igor Pavlov : Public domain */

+2015-10-04 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -109,6 +109,7 @@
   {

     size_t destPos = 0;

     PRF(printf("################# COPY           "));

+

     while (unpackSize > 0)

     {

       UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;

@@ -121,6 +122,7 @@
       unpackSize -= u;

       destPos += u;

       p->srcPos += u;

+      

       if (outStream)

       {

         *packSizeRes += destPos;

@@ -132,9 +134,11 @@
         *packSizeRes = destPos;

       /* needInitState = True; */

     }

+    

     LzmaEnc_RestoreState(p->enc);

     return SZ_OK;

   }

+

   {

     size_t destPos = 0;

     UInt32 u = unpackSize - 1;

@@ -160,11 +164,13 @@
     if (outStream)

       if (outStream->Write(outStream, outBuf, destPos) != destPos)

         return SZ_ERROR_WRITE;

+    

     *packSizeRes = destPos;

     return SZ_OK;

   }

 }

 

+

 /* ---------- Lzma2 Props ---------- */

 

 void Lzma2EncProps_Init(CLzma2EncProps *p)

@@ -221,6 +227,8 @@
 

   LzmaEncProps_Normalize(&p->lzmaProps);

 

+  t1 = p->lzmaProps.numThreads;

+

   if (p->blockSize == 0)

   {

     UInt32 dictSize = p->lzmaProps.dictSize;

@@ -232,28 +240,34 @@
     if (blockSize < dictSize) blockSize = dictSize;

     p->blockSize = (size_t)blockSize;

   }

-  if (t2 > 1)

+  

+  if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)

   {

     UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;

     if (temp > p->lzmaProps.reduceSize)

     {

       UInt64 numBlocks = temp / p->blockSize;

-      if (t2 >= 0 && numBlocks < (UInt64) t2)

+      if (numBlocks < (unsigned)t2)

       {

-        t2 = (UInt32)numBlocks;

+        t2 = (unsigned)numBlocks;

+        if (t2 == 0)

+          t2 = 1;

         t3 = t1 * t2;

       }

     }

   }

+  

   p->numBlockThreads = t2;

   p->numTotalThreads = t3;

 }

 

+

 static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)

 {

   return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;

 }

 

+

 /* ---------- Lzma2 ---------- */

 

 typedef struct

@@ -283,15 +297,17 @@
   UInt64 packTotal = 0;

   SRes res = SZ_OK;

 

-  if (mainEncoder->outBuf == 0)

+  if (!mainEncoder->outBuf)

   {

     mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);

-    if (mainEncoder->outBuf == 0)

+    if (!mainEncoder->outBuf)

       return SZ_ERROR_MEM;

   }

+  

   RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));

   RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,

       mainEncoder->alloc, mainEncoder->allocBig));

+  

   for (;;)

   {

     size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;

@@ -305,16 +321,20 @@
     if (packSize == 0)

       break;

   }

+  

   LzmaEnc_Finish(p->enc);

+

   if (res == SZ_OK)

   {

     Byte b = 0;

     if (outStream->Write(outStream, &b, 1) != 1)

       return SZ_ERROR_WRITE;

   }

+  

   return res;

 }

 

+

 #ifndef _7ZIP_ST

 

 typedef struct

@@ -362,10 +382,12 @@
           break;

         }

       }

+      

       LzmaEnc_Finish(p->enc);

       if (res != SZ_OK)

         return res;

     }

+    

     if (finished)

     {

       if (*destSize == destLim)

@@ -378,12 +400,13 @@
 

 #endif

 

+

 /* ---------- Lzma2Enc ---------- */

 

 CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)

 {

   CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));

-  if (p == 0)

+  if (!p)

     return NULL;

   Lzma2EncProps_Init(&p->props);

   Lzma2EncProps_Normalize(&p->props);

@@ -395,6 +418,7 @@
     for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

       p->coders[i].enc = 0;

   }

+  

   #ifndef _7ZIP_ST

   MtCoder_Construct(&p->mtCoder);

   #endif

@@ -455,22 +479,17 @@
 

   for (i = 0; i < p->props.numBlockThreads; i++)

   {

-    CLzma2EncInt *t = &p->coders[i];

-    if (t->enc == NULL)

+    CLzma2EncInt *t = &p->coders[(unsigned)i];

+    if (!t->enc)

     {

       t->enc = LzmaEnc_Create(p->alloc);

-      if (t->enc == NULL)

+      if (!t->enc)

         return SZ_ERROR_MEM;

     }

   }

 

   #ifndef _7ZIP_ST

-  if (p->props.numBlockThreads <= 1)

-  #endif

-    return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);

-

-  #ifndef _7ZIP_ST

-

+  if (p->props.numBlockThreads > 1)

   {

     CMtCallbackImp mtCallback;

 

@@ -485,9 +504,17 @@
 

     p->mtCoder.blockSize = p->props.blockSize;

     p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;

+    if (p->mtCoder.destBlockSize < p->props.blockSize)

+    {

+      p->mtCoder.destBlockSize = (size_t)0 - 1;

+      if (p->mtCoder.destBlockSize < p->props.blockSize)

+        return SZ_ERROR_FAIL;

+    }

     p->mtCoder.numThreads = p->props.numBlockThreads;

     

     return MtCoder_Code(&p->mtCoder);

   }

   #endif

+

+  return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);

 }

diff --git a/C/Lzma86Dec.c b/C/Lzma86Dec.c
index 760a447..20ac5e7 100644
--- a/C/Lzma86Dec.c
+++ b/C/Lzma86Dec.c
@@ -1,5 +1,7 @@
 /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder

-2009-08-14 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include "Lzma86.h"

 

@@ -7,9 +9,6 @@
 #include "Bra.h"

 #include "LzmaDec.h"

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-

 SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)

 {

   unsigned i;

@@ -23,7 +22,6 @@
 

 SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)

 {

-  ISzAlloc g_Alloc = { SzAlloc, SzFree };

   SRes res;

   int useFilter;

   SizeT inSizePure;

diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c
index 41b488c..ee59fb7 100644
--- a/C/Lzma86Enc.c
+++ b/C/Lzma86Enc.c
@@ -1,5 +1,7 @@
 /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder

-2009-08-14 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include <string.h>

 

@@ -11,13 +13,9 @@
 

 #define SZE_OUT_OVERFLOW SZE_DATA_ERROR

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-

 int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,

     int level, UInt32 dictSize, int filterMode)

 {

-  ISzAlloc g_Alloc = { SzAlloc, SzFree };

   size_t outSize2 = *destLen;

   Byte *filteredStream;

   Bool useFilter;

diff --git a/C/LzmaDec.c b/C/LzmaDec.c
index 38cd9d6..64f1164 100644
--- a/C/LzmaDec.c
+++ b/C/LzmaDec.c
@@ -1,5 +1,5 @@
 /* LzmaDec.c -- LZMA Decoder

-2015-01-01 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -114,14 +114,14 @@
 #define Literal (RepLenCoder + kNumLenProbs)

 

 #define LZMA_BASE_SIZE 1846

-#define LZMA_LIT_SIZE 768

-

-#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))

+#define LZMA_LIT_SIZE 0x300

 

 #if Literal != LZMA_BASE_SIZE

 StopCompilingDueBUG

 #endif

 

+#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))

+

 #define LZMA_DIC_MIN (1 << 12)

 

 /* First LZMA-symbol is always decoded.

@@ -133,8 +133,8 @@
   p->remainLen:

     < kMatchSpecLenStart : normal remain

     = kMatchSpecLenStart : finished

-    = kMatchSpecLenStart + 1 : Flush marker

-    = kMatchSpecLenStart + 2 : State Init Marker

+    = kMatchSpecLenStart + 1 : Flush marker (unused now)

+    = kMatchSpecLenStart + 2 : State Init Marker (unused now)

 */

 

 static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)

@@ -172,9 +172,10 @@
       unsigned symbol;

       UPDATE_0(prob);

       prob = probs + Literal;

-      if (checkDicSize != 0 || processedPos != 0)

-        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +

-        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));

+      if (processedPos != 0 || checkDicSize != 0)

+        prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +

+            (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));

+      processedPos++;

 

       if (state < kNumLitStates)

       {

@@ -195,7 +196,7 @@
       }

       else

       {

-        unsigned matchByte = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+        unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];

         unsigned offs = 0x100;

         state -= (state < 10) ? 3 : 6;

         symbol = 1;

@@ -222,11 +223,11 @@
         }

         #endif

       }

+

       dic[dicPos++] = (Byte)symbol;

-      processedPos++;

       continue;

     }

-    else

+    

     {

       UPDATE_1(prob);

       prob = probs + IsRep + state;

@@ -249,7 +250,7 @@
           IF_BIT_0(prob)

           {

             UPDATE_0(prob);

-            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+            dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];

             dicPos++;

             processedPos++;

             state = state < kNumLitStates ? 9 : 11;

@@ -290,15 +291,17 @@
         state = state < kNumLitStates ? 8 : 11;

         prob = probs + RepLenCoder;

       }

+      

+      #ifdef _LZMA_SIZE_OPT

       {

-        unsigned limit, offset;

+        unsigned lim, offset;

         CLzmaProb *probLen = prob + LenChoice;

         IF_BIT_0(probLen)

         {

           UPDATE_0(probLen);

           probLen = prob + LenLow + (posState << kLenNumLowBits);

           offset = 0;

-          limit = (1 << kLenNumLowBits);

+          lim = (1 << kLenNumLowBits);

         }

         else

         {

@@ -309,19 +312,55 @@
             UPDATE_0(probLen);

             probLen = prob + LenMid + (posState << kLenNumMidBits);

             offset = kLenNumLowSymbols;

-            limit = (1 << kLenNumMidBits);

+            lim = (1 << kLenNumMidBits);

           }

           else

           {

             UPDATE_1(probLen);

             probLen = prob + LenHigh;

             offset = kLenNumLowSymbols + kLenNumMidSymbols;

-            limit = (1 << kLenNumHighBits);

+            lim = (1 << kLenNumHighBits);

           }

         }

-        TREE_DECODE(probLen, limit, len);

+        TREE_DECODE(probLen, lim, len);

         len += offset;

       }

+      #else

+      {

+        CLzmaProb *probLen = prob + LenChoice;

+        IF_BIT_0(probLen)

+        {

+          UPDATE_0(probLen);

+          probLen = prob + LenLow + (posState << kLenNumLowBits);

+          len = 1;

+          TREE_GET_BIT(probLen, len);

+          TREE_GET_BIT(probLen, len);

+          TREE_GET_BIT(probLen, len);

+          len -= 8;

+        }

+        else

+        {

+          UPDATE_1(probLen);

+          probLen = prob + LenChoice2;

+          IF_BIT_0(probLen)

+          {

+            UPDATE_0(probLen);

+            probLen = prob + LenMid + (posState << kLenNumMidBits);

+            len = 1;

+            TREE_GET_BIT(probLen, len);

+            TREE_GET_BIT(probLen, len);

+            TREE_GET_BIT(probLen, len);

+          }

+          else

+          {

+            UPDATE_1(probLen);

+            probLen = prob + LenHigh;

+            TREE_DECODE(probLen, (1 << kLenNumHighBits), len);

+            len += kLenNumLowSymbols + kLenNumMidSymbols;

+          }

+        }

+      }

+      #endif

 

       if (state >= kNumStates)

       {

@@ -332,7 +371,7 @@
         if (distance >= kStartPosModelIndex)

         {

           unsigned posSlot = (unsigned)distance;

-          int numDirectBits = (int)(((distance >> 1) - 1));

+          unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));

           distance = (2 | (distance & 1));

           if (posSlot < kEndPosModelIndex)

           {

@@ -391,6 +430,7 @@
             }

           }

         }

+        

         rep3 = rep2;

         rep2 = rep1;

         rep1 = rep0;

@@ -398,26 +438,39 @@
         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;

       }

 

       len += kMatchMinLen;

 

-      if (limit == dicPos)

-        return SZ_ERROR_DATA;

       {

-        SizeT rem = limit - dicPos;

-        unsigned curLen = ((rem < len) ? (unsigned)rem : len);

-        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);

+        SizeT rem;

+        unsigned curLen;

+        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);

 

         processedPos += curLen;

 

         len -= curLen;

-        if (pos + curLen <= dicBufSize)

+        if (curLen <= dicBufSize - pos)

         {

           Byte *dest = dic + dicPos;

           ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;

@@ -441,7 +494,9 @@
     }

   }

   while (dicPos < limit && buf < bufLimit);

+

   NORMALIZE;

+  

   p->buf = buf;

   p->range = range;

   p->code = code;

@@ -465,9 +520,10 @@
     SizeT dicPos = p->dicPos;

     SizeT dicBufSize = p->dicBufSize;

     unsigned len = p->remainLen;

-    UInt32 rep0 = p->reps[0];

-    if (limit - dicPos < len)

-      len = (unsigned)(limit - dicPos);

+    SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */

+    SizeT rem = limit - dicPos;

+    if (rem < len)

+      len = (unsigned)(rem);

 

     if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)

       p->checkDicSize = p->prop.dicSize;

@@ -477,7 +533,7 @@
     while (len != 0)

     {

       len--;

-      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+      dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];

       dicPos++;

     }

     p->dicPos = dicPos;

@@ -495,17 +551,19 @@
       if (limit - p->dicPos > rem)

         limit2 = p->dicPos + rem;

     }

+    

     RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));

-    if (p->processedPos >= p->prop.dicSize)

+    

+    if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)

       p->checkDicSize = p->prop.dicSize;

+    

     LzmaDec_WriteRem(p, limit);

   }

   while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);

 

   if (p->remainLen > kMatchSpecLenStart)

-  {

     p->remainLen = kMatchSpecLenStart;

-  }

+

   return 0;

 }

 

@@ -522,12 +580,12 @@
   UInt32 range = p->range;

   UInt32 code = p->code;

   const Byte *bufLimit = buf + inSize;

-  CLzmaProb *probs = p->probs;

+  const CLzmaProb *probs = p->probs;

   unsigned state = p->state;

   ELzmaDummy res;

 

   {

-    CLzmaProb *prob;

+    const CLzmaProb *prob;

     UInt32 bound;

     unsigned ttt;

     unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);

@@ -541,9 +599,9 @@
 

       prob = probs + Literal;

       if (p->checkDicSize != 0 || p->processedPos != 0)

-        prob += (LZMA_LIT_SIZE *

-          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +

-          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));

+        prob += ((UInt32)LZMA_LIT_SIZE *

+            ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +

+            (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));

 

       if (state < kNumLitStates)

       {

@@ -553,13 +611,13 @@
       else

       {

         unsigned matchByte = p->dic[p->dicPos - p->reps[0] +

-            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];

+            (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];

         unsigned offs = 0x100;

         unsigned symbol = 1;

         do

         {

           unsigned bit;

-          CLzmaProb *probLit;

+          const CLzmaProb *probLit;

           matchByte <<= 1;

           bit = (matchByte & offs);

           probLit = prob + offs + bit + symbol;

@@ -629,7 +687,7 @@
       }

       {

         unsigned limit, offset;

-        CLzmaProb *probLen = prob + LenChoice;

+        const CLzmaProb *probLen = prob + LenChoice;

         IF_BIT_0_CHECK(probLen)

         {

           UPDATE_0_CHECK;

@@ -669,7 +727,7 @@
         TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);

         if (posSlot >= kStartPosModelIndex)

         {

-          int numDirectBits = ((posSlot >> 1) - 1);

+          unsigned numDirectBits = ((posSlot >> 1) - 1);

 

           /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */

 

@@ -708,13 +766,6 @@
 }

 

 

-static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)

-{

-  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);

-  p->range = 0xFFFFFFFF;

-  p->needFlush = 0;

-}

-

 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)

 {

   p->needFlush = 1;

@@ -739,8 +790,8 @@
 

 static void LzmaDec_InitStateReal(CLzmaDec *p)

 {

-  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));

-  UInt32 i;

+  SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);

+  SizeT i;

   CLzmaProb *probs = p->probs;

   for (i = 0; i < numProbs; i++)

     probs[i] = kBitModelTotal >> 1;

@@ -762,7 +813,7 @@
   {

       int checkEndMarkNow;

 

-      if (p->needFlush != 0)

+      if (p->needFlush)

       {

         for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)

           p->tempBuf[p->tempBufSize++] = *src++;

@@ -773,8 +824,13 @@
         }

         if (p->tempBuf[0] != 0)

           return SZ_ERROR_DATA;

-

-        LzmaDec_InitRc(p, p->tempBuf);

+        p->code =

+              ((UInt32)p->tempBuf[1] << 24)

+            | ((UInt32)p->tempBuf[2] << 16)

+            | ((UInt32)p->tempBuf[3] << 8)

+            | ((UInt32)p->tempBuf[4]);

+        p->range = 0xFFFFFFFF;

+        p->needFlush = 0;

         p->tempBufSize = 0;

       }

 

@@ -858,7 +914,16 @@
         p->buf = p->tempBuf;

         if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)

           return SZ_ERROR_DATA;

-        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));

+        

+        {

+          unsigned kkk = (unsigned)(p->buf - p->tempBuf);

+          if (rem < kkk)

+            return SZ_ERROR_FAIL; /* some internal error */

+          rem -= kkk;

+          if (lookAhead < rem)

+            return SZ_ERROR_FAIL; /* some internal error */

+          lookAhead -= rem;

+        }

         (*srcLen) += lookAhead;

         src += lookAhead;

         inSize -= lookAhead;

@@ -913,13 +978,13 @@
 void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)

 {

   alloc->Free(alloc, p->probs);

-  p->probs = 0;

+  p->probs = NULL;

 }

 

 static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)

 {

   alloc->Free(alloc, p->dic);

-  p->dic = 0;

+  p->dic = NULL;

 }

 

 void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)

@@ -957,12 +1022,12 @@
 static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)

 {

   UInt32 numProbs = LzmaProps_GetNumProbs(propNew);

-  if (p->probs == 0 || numProbs != p->numProbs)

+  if (!p->probs || numProbs != p->numProbs)

   {

     LzmaDec_FreeProbs(p, alloc);

     p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));

     p->numProbs = numProbs;

-    if (p->probs == 0)

+    if (!p->probs)

       return SZ_ERROR_MEM;

   }

   return SZ_OK;

@@ -983,12 +1048,22 @@
   SizeT dicBufSize;

   RINOK(LzmaProps_Decode(&propNew, props, propsSize));

   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));

-  dicBufSize = propNew.dicSize;

-  if (p->dic == 0 || dicBufSize != p->dicBufSize)

+

+  {

+    UInt32 dictSize = propNew.dicSize;

+    SizeT mask = ((UInt32)1 << 12) - 1;

+         if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;

+    else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;

+    dicBufSize = ((SizeT)dictSize + mask) & ~mask;

+    if (dicBufSize < dictSize)

+      dicBufSize = dictSize;

+  }

+

+  if (!p->dic || dicBufSize != p->dicBufSize)

   {

     LzmaDec_FreeDict(p, alloc);

     p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);

-    if (p->dic == 0)

+    if (!p->dic)

     {

       LzmaDec_FreeProbs(p, alloc);

       return SZ_ERROR_MEM;

diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
index 40ee6a4..462ca67 100644
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,5 @@
 /* LzmaEnc.c -- LZMA Encoder

-2014-12-29 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -23,6 +23,9 @@
 static unsigned g_STAT_OFFSET = 0;

 #endif

 

+#define kMaxHistorySize ((UInt32)3 << 29)

+/* #define kMaxHistorySize ((UInt32)7 << 29) */

+

 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)

 

 #define kBlockSize (9 << 10)

@@ -58,6 +61,7 @@
   int level = p->level;

   if (level < 0) level = 5;

   p->level = level;

+  

   if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));

   if (p->dictSize > p->reduceSize)

   {

@@ -68,14 +72,17 @@
       if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }

     }

   }

+

   if (p->lc < 0) p->lc = 3;

   if (p->lp < 0) p->lp = 0;

   if (p->pb < 0) p->pb = 2;

+

   if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);

   if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);

   if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);

   if (p->numHashBytes < 0) p->numHashBytes = 4;

-  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);

+  if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);

+  

   if (p->numThreads < 0)

     p->numThreads =

       #ifndef _7ZIP_ST

@@ -92,17 +99,18 @@
   return props.dictSize;

 }

 

+#if (_MSC_VER >= 1400)

+/* BSR code is fast for some new CPUs */

 /* #define LZMA_LOG_BSR */

-/* Define it for Intel's CPU */

-

+#endif

 

 #ifdef LZMA_LOG_BSR

 

-#define kDicLogSizeMaxCompress 30

+#define kDicLogSizeMaxCompress 32

 

-#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }

+#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }

 

-UInt32 GetPosSlot1(UInt32 pos)

+static UInt32 GetPosSlot1(UInt32 pos)

 {

   UInt32 res;

   BSR2_RET(pos, res);

@@ -113,27 +121,44 @@
 

 #else

 

-#define kNumLogBits (9 + (int)sizeof(size_t) / 2)

+#define kNumLogBits (9 + sizeof(size_t) / 2)

+/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */

+

 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)

 

-void LzmaEnc_FastPosInit(Byte *g_FastPos)

+static void LzmaEnc_FastPosInit(Byte *g_FastPos)

 {

-  int c = 2, slotFast;

+  unsigned slot;

   g_FastPos[0] = 0;

   g_FastPos[1] = 1;

+  g_FastPos += 2;

   

-  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)

+  for (slot = 2; slot < kNumLogBits * 2; slot++)

   {

-    UInt32 k = (1 << ((slotFast >> 1) - 1));

-    UInt32 j;

-    for (j = 0; j < k; j++, c++)

-      g_FastPos[c] = (Byte)slotFast;

+    size_t k = ((size_t)1 << ((slot >> 1) - 1));

+    size_t j;

+    for (j = 0; j < k; j++)

+      g_FastPos[j] = (Byte)slot;

+    g_FastPos += k;

   }

 }

 

-#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \

+/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */

+/*

+#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \

   (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \

-  res = p->g_FastPos[pos >> i] + (i * 2); }

+  res = p->g_FastPos[pos >> zz] + (zz * 2); }

+*/

+

+/*

+#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \

+  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \

+  res = p->g_FastPos[pos >> zz] + (zz * 2); }

+*/

+

+#define BSR2_RET(pos, res) { UInt32 zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \

+  res = p->g_FastPos[pos >> zz] + (zz * 2); }

+

 /*

 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \

   p->g_FastPos[pos >> 6] + 12 : \

@@ -213,6 +238,7 @@
 

 #define kNumStates 12

 

+

 typedef struct

 {

   CLzmaProb choice;

@@ -222,14 +248,16 @@
   CLzmaProb high[kLenNumHighSymbols];

 } CLenEnc;

 

+

 typedef struct

 {

   CLenEnc p;

-  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];

   UInt32 tableSize;

+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];

   UInt32 counters[LZMA_NUM_PB_STATES_MAX];

 } CLenPriceEnc;

 

+

 typedef struct

 {

   UInt32 range;

@@ -244,10 +272,14 @@
   SRes res;

 } CRangeEnc;

 

+

 typedef struct

 {

   CLzmaProb *litProbs;

 

+  UInt32 state;

+  UInt32 reps[LZMA_NUM_REPS];

+

   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];

   CLzmaProb isRep[kNumStates];

   CLzmaProb isRepG0[kNumStates];

@@ -261,15 +293,49 @@
   

   CLenPriceEnc lenEnc;

   CLenPriceEnc repLenEnc;

-

-  UInt32 reps[LZMA_NUM_REPS];

-  UInt32 state;

 } CSaveState;

 

+

 typedef struct

 {

-  IMatchFinder matchFinder;

   void *matchFinderObj;

+  IMatchFinder matchFinder;

+

+  UInt32 optimumEndIndex;

+  UInt32 optimumCurrentIndex;

+

+  UInt32 longestMatchLength;

+  UInt32 numPairs;

+  UInt32 numAvail;

+

+  UInt32 numFastBytes;

+  UInt32 additionalOffset;

+  UInt32 reps[LZMA_NUM_REPS];

+  UInt32 state;

+

+  unsigned lc, lp, pb;

+  unsigned lpMask, pbMask;

+  unsigned lclp;

+

+  CLzmaProb *litProbs;

+

+  Bool fastMode;

+  Bool writeEndMark;

+  Bool finished;

+  Bool multiThread;

+  Bool needInit;

+

+  UInt64 nowPos64;

+  

+  UInt32 matchPriceCount;

+  UInt32 alignPriceCount;

+

+  UInt32 distTableSize;

+

+  UInt32 dictSize;

+  SRes result;

+

+  CRangeEnc rc;

 

   #ifndef _7ZIP_ST

   Bool mtMode;

@@ -282,12 +348,6 @@
   Byte pad[128];

   #endif

   

-  UInt32 optimumEndIndex;

-  UInt32 optimumCurrentIndex;

-

-  UInt32 longestMatchLength;

-  UInt32 numPairs;

-  UInt32 numAvail;

   COptimal opt[kNumOpts];

   

   #ifndef LZMA_LOG_BSR

@@ -296,22 +356,10 @@
 

   UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

   UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];

-  UInt32 numFastBytes;

-  UInt32 additionalOffset;

-  UInt32 reps[LZMA_NUM_REPS];

-  UInt32 state;

 

   UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];

   UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];

   UInt32 alignPrices[kAlignTableSize];

-  UInt32 alignPriceCount;

-

-  UInt32 distTableSize;

-

-  unsigned lc, lp, pb;

-  unsigned lpMask, pbMask;

-

-  CLzmaProb *litProbs;

 

   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];

   CLzmaProb isRep[kNumStates];

@@ -327,26 +375,14 @@
   CLenPriceEnc lenEnc;

   CLenPriceEnc repLenEnc;

 

-  unsigned lclp;

-

-  Bool fastMode;

-  

-  CRangeEnc rc;

-

-  Bool writeEndMark;

-  UInt64 nowPos64;

-  UInt32 matchPriceCount;

-  Bool finished;

-  Bool multiThread;

-

-  SRes result;

-  UInt32 dictSize;

-

-  int needInit;

-

   CSaveState saveState;

+

+  #ifndef _7ZIP_ST

+  Byte pad2[128];

+  #endif

 } CLzmaEnc;

 

+

 void LzmaEnc_SaveState(CLzmaEncHandle pp)

 {

   CLzmaEnc *p = (CLzmaEnc *)pp;

@@ -370,7 +406,7 @@
   memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));

   memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));

   memcpy(dest->reps, p->reps, sizeof(p->reps));

-  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));

+  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));

 }

 

 void LzmaEnc_RestoreState(CLzmaEncHandle pp)

@@ -396,7 +432,7 @@
   memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));

   memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));

   memcpy(dest->reps, p->reps, sizeof(p->reps));

-  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));

+  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));

 }

 

 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)

@@ -405,9 +441,13 @@
   CLzmaEncProps props = *props2;

   LzmaEncProps_Normalize(&props);

 

-  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||

-      props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))

+  if (props.lc > LZMA_LC_MAX

+      || props.lp > LZMA_LP_MAX

+      || props.pb > LZMA_PB_MAX

+      || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)

+      || props.dictSize > kMaxHistorySize)

     return SZ_ERROR_PARAM;

+

   p->dictSize = props.dictSize;

   {

     unsigned fb = props.fb;

@@ -421,7 +461,7 @@
   p->lp = props.lp;

   p->pb = props.pb;

   p->fastMode = (props.algo == 0);

-  p->matchFinderBase.btMode = props.btMode;

+  p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);

   {

     UInt32 numHashBytes = 4;

     if (props.btMode)

@@ -465,8 +505,8 @@
 

 static void RangeEnc_Construct(CRangeEnc *p)

 {

-  p->outStream = 0;

-  p->bufBase = 0;

+  p->outStream = NULL;

+  p->bufBase = NULL;

 }

 

 #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)

@@ -474,10 +514,10 @@
 #define RC_BUF_SIZE (1 << 16)

 static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)

 {

-  if (p->bufBase == 0)

+  if (!p->bufBase)

   {

     p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);

-    if (p->bufBase == 0)

+    if (!p->bufBase)

       return 0;

     p->bufLim = p->bufBase + RC_BUF_SIZE;

   }

@@ -607,7 +647,7 @@
   while (symbol < 0x10000);

 }

 

-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)

+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)

 {

   UInt32 i;

   for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))

@@ -643,7 +683,7 @@
 #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]

 #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]

 

-static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)

+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)

 {

   UInt32 price = 0;

   symbol |= 0x100;

@@ -656,7 +696,7 @@
   return price;

 }

 

-static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)

+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)

 {

   UInt32 price = 0;

   UInt32 offs = 0x100;

@@ -700,7 +740,7 @@
   }

 }

 

-static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)

+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)

 {

   UInt32 price = 0;

   symbol |= (1 << numBitLevels);

@@ -712,7 +752,7 @@
   return price;

 }

 

-static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)

+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)

 {

   UInt32 price = 0;

   UInt32 m = 1;

@@ -763,7 +803,7 @@
   }

 }

 

-static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)

+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)

 {

   UInt32 a0 = GET_PRICE_0a(p->choice);

   UInt32 a1 = GET_PRICE_1a(p->choice);

@@ -786,20 +826,20 @@
     prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);

 }

 

-static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)

+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)

 {

   LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);

   p->counters[posState] = p->tableSize;

 }

 

-static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)

+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)

 {

   UInt32 posState;

   for (posState = 0; posState < numPosStates; posState++)

     LenPriceEnc_UpdateTable(p, posState, ProbPrices);

 }

 

-static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)

+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)

 {

   LenEnc_Encode(&p->p, rc, symbol, posState);

   if (updatePrice)

@@ -814,7 +854,7 @@
 {

   #ifdef SHOW_STAT

   g_STAT_OFFSET += num;

-  printf("\n MovePos %d", num);

+  printf("\n MovePos %u", num);

   #endif

   

   if (num != 0)

@@ -831,12 +871,12 @@
   numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);

   

   #ifdef SHOW_STAT

-  printf("\n i = %d numPairs = %d    ", g_STAT_OFFSET, numPairs / 2);

+  printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);

   g_STAT_OFFSET++;

   {

     UInt32 i;

     for (i = 0; i < numPairs; i += 2)

-      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);

+      printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);

   }

   #endif

   

@@ -845,14 +885,16 @@
     lenRes = p->matches[numPairs - 2];

     if (lenRes == p->numFastBytes)

     {

-      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

-      UInt32 distance = p->matches[numPairs - 1] + 1;

       UInt32 numAvail = p->numAvail;

       if (numAvail > LZMA_MATCH_LEN_MAX)

         numAvail = LZMA_MATCH_LEN_MAX;

       {

-        const Byte *pby2 = pby - distance;

-        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);

+        const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+        const Byte *pby = pbyCur + lenRes;

+        ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];

+        const Byte *pbyLim = pbyCur + numAvail;

+        for (; pby != pbyLim && *pby == pby[dif]; pby++);

+        lenRes = (UInt32)(pby - pbyCur);

       }

     }

   }

@@ -937,16 +979,21 @@
   return p->optimumCurrentIndex;

 }

 

-#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)

+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)

 

 static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)

 {

-  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;

-  UInt32 matchPrice, repMatchPrice, normalMatchPrice;

+  UInt32 lenEnd, cur;

   UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];

   UInt32 *matches;

+

+  {

+

+  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, len;

+  UInt32 matchPrice, repMatchPrice, normalMatchPrice;

   const Byte *data;

   Byte curByte, matchByte;

+

   if (p->optimumEndIndex != p->optimumCurrentIndex)

   {

     const COptimal *opt = &p->opt[p->optimumCurrentIndex];

@@ -981,7 +1028,7 @@
     UInt32 lenTest;

     const Byte *data2;

     reps[i] = p->reps[i];

-    data2 = data - (reps[i] + 1);

+    data2 = data - reps[i] - 1;

     if (data[0] != data2[0] || data[1] != data2[1])

     {

       repLens[i] = 0;

@@ -1125,17 +1172,20 @@
   cur = 0;

 

     #ifdef SHOW_STAT2

-    if (position >= 0)

+    /* if (position >= 0) */

     {

       unsigned i;

       printf("\n pos = %4X", position);

       for (i = cur; i <= lenEnd; i++)

-      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);

+      printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);

     }

     #endif

 

+  }

+

   for (;;)

   {

+    UInt32 numAvail;

     UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;

     UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;

     Bool nextIsChar;

@@ -1282,7 +1332,7 @@
       /* try Literal + rep0 */

       UInt32 temp;

       UInt32 lenTest2;

-      const Byte *data2 = data - (reps[0] + 1);

+      const Byte *data2 = data - reps[0] - 1;

       UInt32 limit = p->numFastBytes + 1;

       if (limit > numAvailFull)

         limit = numAvailFull;

@@ -1325,7 +1375,7 @@
       UInt32 lenTest;

       UInt32 lenTestTemp;

       UInt32 price;

-      const Byte *data2 = data - (reps[repIndex] + 1);

+      const Byte *data2 = data - reps[repIndex] - 1;

       if (data[0] != data2[0] || data[1] != data2[1])

         continue;

       for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);

@@ -1355,13 +1405,13 @@
         {

           UInt32 lenTest2 = lenTest + 1;

           UInt32 limit = lenTest2 + p->numFastBytes;

-          UInt32 nextRepMatchPrice;

           if (limit > numAvailFull)

             limit = numAvailFull;

           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);

           lenTest2 -= lenTest + 1;

           if (lenTest2 >= 2)

           {

+            UInt32 nextRepMatchPrice;

             UInt32 state2 = kRepNextStates[state];

             UInt32 posStateNext = (position + lenTest) & p->pbMask;

             UInt32 curAndLenCharPrice =

@@ -1423,6 +1473,7 @@
       for (lenTest = /*2*/ startLen; ; lenTest++)

       {

         UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];

+        {

         UInt32 lenToPosState = GetLenToPosState(lenTest);

         COptimal *opt;

         if (curBack < kNumFullDistances)

@@ -1438,20 +1489,21 @@
           opt->backPrev = curBack + LZMA_NUM_REPS;

           opt->prev1IsChar = False;

         }

+        }

 

         if (/*_maxMode && */lenTest == matches[offs])

         {

           /* Try Match + Literal + Rep0 */

-          const Byte *data2 = data - (curBack + 1);

+          const Byte *data2 = data - curBack - 1;

           UInt32 lenTest2 = lenTest + 1;

           UInt32 limit = lenTest2 + p->numFastBytes;

-          UInt32 nextRepMatchPrice;

           if (limit > numAvailFull)

             limit = numAvailFull;

           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);

           lenTest2 -= lenTest + 1;

           if (lenTest2 >= 2)

           {

+            UInt32 nextRepMatchPrice;

             UInt32 state2 = kMatchNextStates[state];

             UInt32 posStateNext = (position + lenTest) & p->pbMask;

             UInt32 curAndLenCharPrice = curAndLenPrice +

@@ -1467,15 +1519,15 @@
             /* for (; lenTest2 >= 2; lenTest2--) */

             {

               UInt32 offset = cur + lenTest + 1 + lenTest2;

-              UInt32 curAndLenPrice;

+              UInt32 curAndLenPrice2;

               COptimal *opt;

               while (lenEnd < offset)

                 p->opt[++lenEnd].price = kInfinityPrice;

-              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);

+              curAndLenPrice2 = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);

               opt = &p->opt[offset];

-              if (curAndLenPrice < opt->price)

+              if (curAndLenPrice2 < opt->price)

               {

-                opt->price = curAndLenPrice;

+                opt->price = curAndLenPrice2;

                 opt->posPrev = cur + lenTest + 1;

                 opt->backPrev = 0;

                 opt->prev1IsChar = True;

@@ -1525,7 +1577,7 @@
   for (i = 0; i < LZMA_NUM_REPS; i++)

   {

     UInt32 len;

-    const Byte *data2 = data - (p->reps[i] + 1);

+    const Byte *data2 = data - p->reps[i] - 1;

     if (data[0] != data2[0] || data[1] != data2[1])

       continue;

     for (len = 2; len < numAvail && data[len] == data2[len]; len++);

@@ -1594,7 +1646,7 @@
   for (i = 0; i < LZMA_NUM_REPS; i++)

   {

     UInt32 len, limit;

-    const Byte *data2 = data - (p->reps[i] + 1);

+    const Byte *data2 = data - p->reps[i] - 1;

     if (data[0] != data2[0] || data[1] != data2[1])

       continue;

     limit = mainLen - 1;

@@ -1676,7 +1728,6 @@
 

     {

       UInt32 *distancesPrices = p->distancesPrices[lenToPosState];

-      UInt32 i;

       for (i = 0; i < kStartPosModelIndex; i++)

         distancesPrices[i] = posSlotPrices[i];

       for (; i < kNumFullDistances; i++)

@@ -1690,6 +1741,7 @@
 {

   RangeEnc_Construct(&p->rc);

   MatchFinder_Construct(&p->matchFinderBase);

+  

   #ifndef _7ZIP_ST

   MatchFinderMt_Construct(&p->matchFinderMt);

   p->matchFinderMt.MatchFinder = &p->matchFinderBase;

@@ -1706,15 +1758,15 @@
   #endif

 

   LzmaEnc_InitPriceTables(p->ProbPrices);

-  p->litProbs = 0;

-  p->saveState.litProbs = 0;

+  p->litProbs = NULL;

+  p->saveState.litProbs = NULL;

 }

 

 CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)

 {

   void *p;

   p = alloc->Alloc(alloc, sizeof(CLzmaEnc));

-  if (p != 0)

+  if (p)

     LzmaEnc_Construct((CLzmaEnc *)p);

   return p;

 }

@@ -1723,8 +1775,8 @@
 {

   alloc->Free(alloc, p->litProbs);

   alloc->Free(alloc, p->saveState.litProbs);

-  p->litProbs = 0;

-  p->saveState.litProbs = 0;

+  p->litProbs = NULL;

+  p->saveState.litProbs = NULL;

 }

 

 void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)

@@ -1732,6 +1784,7 @@
   #ifndef _7ZIP_ST

   MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);

   #endif

+  

   MatchFinder_Free(&p->matchFinderBase, allocBig);

   LzmaEnc_FreeLits(p, alloc);

   RangeEnc_Free(&p->rc, alloc);

@@ -1768,7 +1821,7 @@
     ReadMatchDistances(p, &numPairs);

     RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);

     p->state = kLiteralNextStates[p->state];

-    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);

+    curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);

     LitEnc_Encode(&p->rc, p->litProbs, curByte);

     p->additionalOffset--;

     nowPos32++;

@@ -1785,7 +1838,7 @@
       len = GetOptimum(p, nowPos32, &pos);

 

     #ifdef SHOW_STAT2

-    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);

+    printf("\n pos = %4X,   len = %u   pos = %u", nowPos32, len, pos);

     #endif

 

     posState = nowPos32 & p->pbMask;

@@ -1894,7 +1947,7 @@
             RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)

           break;

       }

-      else if (processed >= (1 << 15))

+      else if (processed >= (1 << 17))

       {

         p->nowPos64 += nowPos32 - startPos32;

         return CheckErrors(p);

@@ -1912,18 +1965,19 @@
   UInt32 beforeSize = kNumOpts;

   if (!RangeEnc_Alloc(&p->rc, alloc))

     return SZ_ERROR_MEM;

+

   #ifndef _7ZIP_ST

   p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));

   #endif

 

   {

     unsigned lclp = p->lc + p->lp;

-    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)

+    if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)

     {

       LzmaEnc_FreeLits(p, alloc);

-      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));

-      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));

-      if (p->litProbs == 0 || p->saveState.litProbs == 0)

+      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));

+      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));

+      if (!p->litProbs || !p->saveState.litProbs)

       {

         LzmaEnc_FreeLits(p, alloc);

         return SZ_ERROR_MEM;

@@ -1932,7 +1986,7 @@
     }

   }

 

-  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);

+  p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);

 

   if (beforeSize + p->dictSize < keepWindowSize)

     beforeSize = keepWindowSize - p->dictSize;

@@ -1952,6 +2006,7 @@
     p->matchFinderObj = &p->matchFinderBase;

     MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);

   }

+  

   return SZ_OK;

 }

 

@@ -1980,9 +2035,10 @@
   }

 

   {

-    UInt32 num = 0x300 << (p->lp + p->lc);

+    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);

+    CLzmaProb *probs = p->litProbs;

     for (i = 0; i < num; i++)

-      p->litProbs[i] = kProbInitValue;

+      probs[i] = kProbInitValue;

   }

 

   {

@@ -2089,10 +2145,11 @@
   if (p->mtMode)

     MatchFinderMt_ReleaseStream(&p->matchFinderMt);

   #else

-  pp = pp;

+  UNUSED_VAR(pp);

   #endif

 }

 

+

 typedef struct

 {

   ISeqOutStream funcTable;

@@ -2122,12 +2179,14 @@
   return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);

 }

 

+

 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)

 {

   const CLzmaEnc *p = (CLzmaEnc *)pp;

   return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;

 }

 

+

 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,

     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)

 {

@@ -2162,6 +2221,7 @@
   return res;

 }

 

+

 static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)

 {

   SRes res = SZ_OK;

@@ -2175,9 +2235,9 @@
   for (;;)

   {

     res = LzmaEnc_CodeOneBlock(p, False, 0, 0);

-    if (res != SZ_OK || p->finished != 0)

+    if (res != SZ_OK || p->finished)

       break;

-    if (progress != 0)

+    if (progress)

     {

       res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));

       if (res != SZ_OK)

@@ -2187,10 +2247,19 @@
       }

     }

   }

+  

   LzmaEnc_Finish(p);

+

+  /*

+  if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))

+    res = SZ_ERROR_FAIL;

+  }

+  */

+

   return res;

 }

 

+

 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,

     ISzAlloc *alloc, ISzAlloc *allocBig)

 {

@@ -2198,28 +2267,27 @@
   return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);

 }

 

+

 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)

 {

   CLzmaEnc *p = (CLzmaEnc *)pp;

-  int i;

+  unsigned i;

   UInt32 dictSize = p->dictSize;

   if (*size < LZMA_PROPS_SIZE)

     return SZ_ERROR_PARAM;

   *size = LZMA_PROPS_SIZE;

   props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);

 

-  for (i = 11; i <= 30; i++)

+  if (dictSize >= ((UInt32)1 << 22))

   {

-    if (dictSize <= ((UInt32)2 << i))

-    {

-      dictSize = (2 << i);

-      break;

-    }

-    if (dictSize <= ((UInt32)3 << i))

-    {

-      dictSize = (3 << i);

-      break;

-    }

+    UInt32 kDictMask = ((UInt32)1 << 20) - 1;

+    if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)

+      dictSize = (dictSize + kDictMask) & ~kDictMask;

+  }

+  else for (i = 11; i <= 30; i++)

+  {

+    if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }

+    if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }

   }

 

   for (i = 0; i < 4; i++)

@@ -2227,6 +2295,7 @@
   return SZ_OK;

 }

 

+

 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

     int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)

 {

@@ -2235,19 +2304,22 @@
 

   CSeqOutStreamBuf outStream;

 

-  LzmaEnc_SetInputBuf(p, src, srcLen);

-

   outStream.funcTable.Write = MyWrite;

   outStream.data = dest;

   outStream.rem = *destLen;

   outStream.overflow = False;

 

   p->writeEndMark = writeEndMark;

-

   p->rc.outStream = &outStream.funcTable;

+

   res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);

+  

   if (res == SZ_OK)

+  {

     res = LzmaEnc_Encode2(p, progress);

+    if (res == SZ_OK && p->nowPos64 != srcLen)

+      res = SZ_ERROR_FAIL;

+  }

 

   *destLen -= outStream.rem;

   if (outStream.overflow)

@@ -2255,13 +2327,14 @@
   return res;

 }

 

+

 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,

     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)

 {

   CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);

   SRes res;

-  if (p == 0)

+  if (!p)

     return SZ_ERROR_MEM;

 

   res = LzmaEnc_SetProps(p, props);

diff --git a/C/LzmaLib.c b/C/LzmaLib.c
index 3e3cf40..c10cf1a 100644
--- a/C/LzmaLib.c
+++ b/C/LzmaLib.c
@@ -1,18 +1,12 @@
 /* LzmaLib.c -- LZMA library wrapper

-2008-08-05

-Igor Pavlov

-Public domain */

+2015-06-13 : Igor Pavlov : Public domain */

 

-#include "LzmaEnc.h"

-#include "LzmaDec.h"

 #include "Alloc.h"

+#include "LzmaDec.h"

+#include "LzmaEnc.h"

 #include "LzmaLib.h"

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

-MY_STDAPI LzmaCompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  srcLen,

+MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,

   unsigned char *outProps, size_t *outPropsSize,

   int level, /* 0 <= level <= 9, default = 5 */

   unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */

@@ -38,7 +32,7 @@
 }

 

 

-MY_STDAPI LzmaUncompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  *srcLen,

+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,

   const unsigned char *props, size_t propsSize)

 {

   ELzmaStatus status;

diff --git a/C/MtCoder.c b/C/MtCoder.c
index 303b435..8c0d9b3 100644
--- a/C/MtCoder.c
+++ b/C/MtCoder.c
@@ -1,10 +1,8 @@
 /* MtCoder.c -- Multi-thread Coder

-2010-09-24 : Igor Pavlov : Public domain */

+2015-10-13 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

-#include <stdio.h>

-

 #include "MtCoder.h"

 

 void LoopThread_Construct(CLoopThread *p)

@@ -120,7 +118,7 @@
   LoopThread_Construct(&p->thread);

 }

 

-#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }

+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }

 

 static void CMtThread_CloseEvents(CMtThread *p)

 {

diff --git a/C/Ppmd.h b/C/Ppmd.h
index 25ce2d2..e807ca1 100644
--- a/C/Ppmd.h
+++ b/C/Ppmd.h
@@ -1,5 +1,5 @@
 /* Ppmd.h -- PPMD codec common code

-2013-01-18 : Igor Pavlov : Public domain

+2016-05-16 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

 #ifndef __PPMD_H

@@ -77,8 +77,8 @@
   CPpmd_Byte_Ref;

 

 #define PPMD_SetAllBitsIn256Bytes(p) \

-  { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \

-  p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}

+  { unsigned z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \

+  p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}

 

 EXTERN_C_END

  

diff --git a/C/Ppmd7.c b/C/Ppmd7.c
index 798c118..ba5d329 100644
--- a/C/Ppmd7.c
+++ b/C/Ppmd7.c
@@ -1,10 +1,10 @@
 /* Ppmd7.c -- PPMdH codec

-2010-03-12 : Igor Pavlov : Public domain

+2016-05-21 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

 #include "Precomp.h"

 

-#include <memory.h>

+#include <string.h>

 

 #include "Ppmd7.h"

 

@@ -66,7 +66,7 @@
   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)

   {

     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);

-    do { p->Units2Indx[k++] = (Byte)i; } while(--step);

+    do { p->Units2Indx[k++] = (Byte)i; } while (--step);

     p->Indx2Units[i] = (Byte)k;

   }

 

@@ -257,7 +257,7 @@
 

 #define MyMem12Cpy(dest, src, num) \

   { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \

-    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }

+    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }

 

 static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)

 {

@@ -639,10 +639,10 @@
   unsigned nonMasked = p->MinContext->NumStats - numMasked;

   if (p->MinContext->NumStats != 256)

   {

-    see = p->See[p->NS2Indx[nonMasked - 1]] +

+    see = p->See[(unsigned)p->NS2Indx[nonMasked - 1]] +

         (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +

-        2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +

-        4 * (numMasked > nonMasked) +

+        2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +

+        4 * (unsigned)(numMasked > nonMasked) +

         p->HiBitsFlag;

     {

       unsigned r = (see->Summ >> see->Shift);

diff --git a/C/Ppmd7.h b/C/Ppmd7.h
index 56e81eb..1c7870c 100644
--- a/C/Ppmd7.h
+++ b/C/Ppmd7.h
@@ -1,5 +1,5 @@
 /* Ppmd7.h -- PPMdH compression codec

-2010-03-12 : Igor Pavlov : Public domain

+2016-05-21 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

 /* This code supports virtual RangeDecoder and includes the implementation

@@ -86,10 +86,10 @@
 void Ppmd7_UpdateBin(CPpmd7 *p);

 

 #define Ppmd7_GetBinSumm(p) \

-    &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \

+    &p->BinSumm[(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \

     p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \

     (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \

-    2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \

+    2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \

     ((p->RunLength >> 26) & 0x20)]

 

 CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);

diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
index d82ea90..9b49e5d 100644
--- a/C/Ppmd7Enc.c
+++ b/C/Ppmd7Enc.c
@@ -1,5 +1,5 @@
 /* Ppmd7Enc.c -- PPMdH Encoder

-2010-03-12 : Igor Pavlov : Public domain

+2015-09-28 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

 #include "Precomp.h"

@@ -26,7 +26,7 @@
       p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));

       temp = 0xFF;

     }

-    while(--p->CacheSize != 0);

+    while (--p->CacheSize != 0);

     p->Cache = (Byte)((UInt32)p->Low >> 24);

   }

   p->CacheSize++;

diff --git a/C/RotateDefs.h b/C/RotateDefs.h
index ad7d164..6c790e7 100644
--- a/C/RotateDefs.h
+++ b/C/RotateDefs.h
@@ -1,5 +1,5 @@
 /* RotateDefs.h -- Rotate functions

-2013-11-12 : Igor Pavlov : Public domain */

+2015-03-25 : Igor Pavlov : Public domain */

 

 #ifndef __ROTATE_DEFS_H

 #define __ROTATE_DEFS_H

@@ -8,16 +8,20 @@
 

 #include <stdlib.h>

 

-// #if (_MSC_VER >= 1200)

+/* don't use _rotl with MINGW. It can insert slow call to function. */

+ 

+/* #if (_MSC_VER >= 1200) */

 #pragma intrinsic(_rotl)

 #pragma intrinsic(_rotr)

-// #endif

+/* #endif */

 

 #define rotlFixed(x, n) _rotl((x), (n))

 #define rotrFixed(x, n) _rotr((x), (n))

 

 #else

 

+/* new compilers can translate these macros to fast commands. */

+

 #define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))

 #define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))

 

diff --git a/C/Sha256.c b/C/Sha256.c
index 91208d3..47e2f42 100644
--- a/C/Sha256.c
+++ b/C/Sha256.c
@@ -1,14 +1,21 @@
 /* Crypto/Sha256.c -- SHA-256 Hash

-2010-06-11 : Igor Pavlov : Public domain

+2015-11-14 : Igor Pavlov : Public domain

 This code is based on public domain code from Wei Dai's Crypto++ library. */

 

 #include "Precomp.h"

 

+#include <string.h>

+

+#include "CpuArch.h"

 #include "RotateDefs.h"

 #include "Sha256.h"

 

 /* define it for speed optimization */

-/* #define _SHA256_UNROLL */

+#ifndef _SFX

+#define _SHA256_UNROLL

+#define _SHA256_UNROLL2

+#endif

+

 /* #define _SHA256_UNROLL2 */

 

 void Sha256_Init(CSha256 *p)

@@ -29,26 +36,18 @@
 #define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))

 #define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))

 

-#define blk0(i) (W[i] = data[i])

-#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))

+#define blk0(i) (W[i])

+#define blk2(i) (W[i] += s1(W[((i)-2)&15]) + W[((i)-7)&15] + s0(W[((i)-15)&15]))

 

 #define Ch(x,y,z) (z^(x&(y^z)))

 #define Maj(x,y,z) ((x&y)|(z&(x|y)))

 

-#define a(i) T[(0-(i))&7]

-#define b(i) T[(1-(i))&7]

-#define c(i) T[(2-(i))&7]

-#define d(i) T[(3-(i))&7]

-#define e(i) T[(4-(i))&7]

-#define f(i) T[(5-(i))&7]

-#define g(i) T[(6-(i))&7]

-#define h(i) T[(7-(i))&7]

-

-

 #ifdef _SHA256_UNROLL2

 

-#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\

-  d += h; h += S0(a) + Maj(a, b, c)

+#define R(a,b,c,d,e,f,g,h, i) \

+    h += S1(e) + Ch(e,f,g) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \

+    d += h; \

+    h += S0(a) + Maj(a, b, c)

 

 #define RX_8(i) \

   R(a,b,c,d,e,f,g,h, i); \

@@ -60,14 +59,32 @@
   R(c,d,e,f,g,h,a,b, i+6); \

   R(b,c,d,e,f,g,h,a, i+7)

 

+#define RX_16  RX_8(0); RX_8(8);

+

 #else

 

-#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\

-  d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))

+#define a(i) T[(0-(i))&7]

+#define b(i) T[(1-(i))&7]

+#define c(i) T[(2-(i))&7]

+#define d(i) T[(3-(i))&7]

+#define e(i) T[(4-(i))&7]

+#define f(i) T[(5-(i))&7]

+#define g(i) T[(6-(i))&7]

+#define h(i) T[(7-(i))&7]

+

+#define R(i) \

+    h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \

+    d(i) += h(i); \

+    h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \

 

 #ifdef _SHA256_UNROLL

 

-#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);

+#define RX_8(i)  R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);

+#define RX_16  RX_8(0); RX_8(8);

+

+#else

+

+#define RX_16  unsigned i; for (i = 0; i < 16; i++) { R(i); }

 

 #endif

 

@@ -92,12 +109,30 @@
   0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

 };

 

-static void Sha256_Transform(UInt32 *state, const UInt32 *data)

+static void Sha256_WriteByteBlock(CSha256 *p)

 {

   UInt32 W[16];

   unsigned j;

+  UInt32 *state;

+

   #ifdef _SHA256_UNROLL2

   UInt32 a,b,c,d,e,f,g,h;

+  #else

+  UInt32 T[8];

+  #endif

+

+  for (j = 0; j < 16; j += 4)

+  {

+    const Byte *ccc = p->buffer + j * 4;

+    W[j    ] = GetBe32(ccc);

+    W[j + 1] = GetBe32(ccc + 4);

+    W[j + 2] = GetBe32(ccc + 8);

+    W[j + 3] = GetBe32(ccc + 12);

+  }

+

+  state = p->state;

+

+  #ifdef _SHA256_UNROLL2

   a = state[0];

   b = state[1];

   c = state[2];

@@ -107,19 +142,13 @@
   g = state[6];

   h = state[7];

   #else

-  UInt32 T[8];

   for (j = 0; j < 8; j++)

     T[j] = state[j];

   #endif

 

   for (j = 0; j < 64; j += 16)

   {

-    #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)

-    RX_8(0); RX_8(8);

-    #else

-    unsigned i;

-    for (i = 0; i < 16; i++) { R(i); }

-    #endif

+    RX_16

   }

 

   #ifdef _SHA256_UNROLL2

@@ -146,61 +175,74 @@
 #undef s0

 #undef s1

 

-static void Sha256_WriteByteBlock(CSha256 *p)

-{

-  UInt32 data32[16];

-  unsigned i;

-  for (i = 0; i < 16; i++)

-    data32[i] =

-      ((UInt32)(p->buffer[i * 4    ]) << 24) +

-      ((UInt32)(p->buffer[i * 4 + 1]) << 16) +

-      ((UInt32)(p->buffer[i * 4 + 2]) <<  8) +

-      ((UInt32)(p->buffer[i * 4 + 3]));

-  Sha256_Transform(p->state, data32);

-}

-

 void Sha256_Update(CSha256 *p, const Byte *data, size_t size)

 {

-  UInt32 curBufferPos = (UInt32)p->count & 0x3F;

-  while (size > 0)

+  if (size == 0)

+    return;

+

   {

-    p->buffer[curBufferPos++] = *data++;

-    p->count++;

-    size--;

-    if (curBufferPos == 64)

+    unsigned pos = (unsigned)p->count & 0x3F;

+    unsigned num;

+    

+    p->count += size;

+    

+    num = 64 - pos;

+    if (num > size)

     {

-      curBufferPos = 0;

-      Sha256_WriteByteBlock(p);

+      memcpy(p->buffer + pos, data, size);

+      return;

     }

+    

+    size -= num;

+    memcpy(p->buffer + pos, data, num);

+    data += num;

   }

+

+  for (;;)

+  {

+    Sha256_WriteByteBlock(p);

+    if (size < 64)

+      break;

+    size -= 64;

+    memcpy(p->buffer, data, 64);

+    data += 64;

+  }

+

+  if (size != 0)

+    memcpy(p->buffer, data, size);

 }

 

 void Sha256_Final(CSha256 *p, Byte *digest)

 {

-  UInt64 lenInBits = (p->count << 3);

-  UInt32 curBufferPos = (UInt32)p->count & 0x3F;

+  unsigned pos = (unsigned)p->count & 0x3F;

   unsigned i;

-  p->buffer[curBufferPos++] = 0x80;

-  while (curBufferPos != (64 - 8))

+  

+  p->buffer[pos++] = 0x80;

+  

+  while (pos != (64 - 8))

   {

-    curBufferPos &= 0x3F;

-    if (curBufferPos == 0)

+    pos &= 0x3F;

+    if (pos == 0)

       Sha256_WriteByteBlock(p);

-    p->buffer[curBufferPos++] = 0;

+    p->buffer[pos++] = 0;

   }

-  for (i = 0; i < 8; i++)

+

   {

-    p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);

-    lenInBits <<= 8;

+    UInt64 numBits = (p->count << 3);

+    SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32));

+    SetBe32(p->buffer + 64 - 4, (UInt32)(numBits));

   }

+  

   Sha256_WriteByteBlock(p);

 

-  for (i = 0; i < 8; i++)

+  for (i = 0; i < 8; i += 2)

   {

-    *digest++ = (Byte)(p->state[i] >> 24);

-    *digest++ = (Byte)(p->state[i] >> 16);

-    *digest++ = (Byte)(p->state[i] >> 8);

-    *digest++ = (Byte)(p->state[i]);

+    UInt32 v0 = p->state[i];

+    UInt32 v1 = p->state[i + 1];

+    SetBe32(digest    , v0);

+    SetBe32(digest + 4, v1);

+    digest += 8;

   }

+  

   Sha256_Init(p);

 }

diff --git a/C/Threads.c b/C/Threads.c
index 18ba1e8..ece07e6 100644
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,9 +1,9 @@
 /* Threads.c -- multithreading library

-2013-11-12 : Igor Pavlov : Public domain */

+2014-09-21 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

-#ifndef _WIN32_WCE

+#ifndef UNDER_CE

 #include <process.h>

 #endif

 

diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
index 73122f7..d3bf0fe 100644
--- a/C/Util/7z/7z.dsp
+++ b/C/Util/7z/7z.dsp
@@ -42,7 +42,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

-# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c

+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAcs /Yu"Precomp.h" /FD /c

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -165,6 +165,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\BraIA64.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\CpuArch.c

 # End Source File

 # Begin Source File

@@ -173,6 +177,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Delta.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Delta.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Lzma2Dec.c

 # End Source File

 # Begin Source File

diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index 736a7fe..92bce0a 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-01-02 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -34,75 +34,117 @@
 }

 

 #ifndef _WIN32

+#define _USE_UTF8

+#endif

 

-static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

+/* #define _USE_UTF8 */

 

-static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)

+#ifdef _USE_UTF8

+

+#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))

+

+#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))

+

+#define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n)))))

+#define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F)))

+

+static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim)

 {

-  size_t destPos = 0, srcPos = 0;

+  size_t size = 0;

   for (;;)

   {

-    unsigned numAdds;

-    UInt32 value;

-    if (srcPos == srcLen)

+    UInt32 val;

+    if (src == srcLim)

+      return size;

+    

+    size++;

+    val = *src++;

+   

+    if (val < 0x80)

+      continue;

+

+    if (val < _UTF8_RANGE(1))

     {

-      *destLen = destPos;

-      return True;

-    }

-    value = src[srcPos++];

-    if (value < 0x80)

-    {

-      if (dest)

-        dest[destPos] = (char)value;

-      destPos++;

+      size++;

       continue;

     }

-    if (value >= 0xD800 && value < 0xE000)

+

+    if (val >= 0xD800 && val < 0xDC00 && src != srcLim)

     {

-      UInt32 c2;

-      if (value >= 0xDC00 || srcPos == srcLen)

-        break;

-      c2 = src[srcPos++];

-      if (c2 < 0xDC00 || c2 >= 0xE000)

-        break;

-      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;

+      UInt32 c2 = *src;

+      if (c2 >= 0xDC00 && c2 < 0xE000)

+      {

+        src++;

+        size += 3;

+        continue;

+      }

     }

-    for (numAdds = 1; numAdds < 5; numAdds++)

-      if (value < (((UInt32)1) << (numAdds * 5 + 6)))

-        break;

-    if (dest)

-      dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));

-    destPos++;

-    do

-    {

-      numAdds--;

-      if (dest)

-        dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));

-      destPos++;

-    }

-    while (numAdds != 0);

+

+    size += 2;

   }

-  *destLen = destPos;

-  return False;

+}

+

+static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim)

+{

+  for (;;)

+  {

+    UInt32 val;

+    if (src == srcLim)

+      return dest;

+    

+    val = *src++;

+    

+    if (val < 0x80)

+    {

+      *dest++ = (char)val;

+      continue;

+    }

+

+    if (val < _UTF8_RANGE(1))

+    {

+      dest[0] = _UTF8_HEAD(1, val);

+      dest[1] = _UTF8_CHAR(0, val);

+      dest += 2;

+      continue;

+    }

+

+    if (val >= 0xD800 && val < 0xDC00 && src != srcLim)

+    {

+      UInt32 c2 = *src;

+      if (c2 >= 0xDC00 && c2 < 0xE000)

+      {

+        src++;

+        val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;

+        dest[0] = _UTF8_HEAD(3, val);

+        dest[1] = _UTF8_CHAR(2, val);

+        dest[2] = _UTF8_CHAR(1, val);

+        dest[3] = _UTF8_CHAR(0, val);

+        dest += 4;

+        continue;

+      }

+    }

+    

+    dest[0] = _UTF8_HEAD(2, val);

+    dest[1] = _UTF8_CHAR(1, val);

+    dest[2] = _UTF8_CHAR(0, val);

+    dest += 3;

+  }

 }

 

 static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)

 {

-  size_t destLen = 0;

-  Bool res;

-  Utf16_To_Utf8(NULL, &destLen, src, srcLen);

+  size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen);

   destLen += 1;

   if (!Buf_EnsureSize(dest, destLen))

     return SZ_ERROR_MEM;

-  res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);

-  dest->data[destLen] = 0;

-  return res ? SZ_OK : SZ_ERROR_FAIL;

+  *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0;

+  return SZ_OK;

 }

 

 #endif

 

 static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s

-    #ifdef _WIN32

+    #ifndef _USE_UTF8

     , UINT codePage

     #endif

     )

@@ -110,7 +152,7 @@
   unsigned len = 0;

   for (len = 0; s[len] != 0; len++);

 

-  #ifdef _WIN32

+  #ifndef _USE_UTF8

   {

     unsigned size = len * 3 + 100;

     if (!Buf_EnsureSize(buf, size))

@@ -191,7 +233,7 @@
   SRes res;

   Buf_Init(&buf);

   res = Utf16_To_Char(&buf, s

-      #ifdef _WIN32

+      #ifndef _USE_UTF8

       , CP_OEMCP

       #endif

       );

@@ -268,10 +310,10 @@
     ms[1] = 29;

   for (mon = 0;; mon++)

   {

-    unsigned s = ms[mon];

-    if (v < s)

+    unsigned d = ms[mon];

+    if (v < d)

       break;

-    v -= s;

+    v -= d;

   }

   s = UIntToStr(s, year, 4); *s++ = '-';

   UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;

@@ -281,27 +323,25 @@
   UIntToStr_2(s, sec); s[2] = 0;

 }

 

-void PrintError(const char *sz)

+void PrintError(char *sz)

 {

   printf("\nERROR: %s\n", sz);

 }

 

-#ifdef USE_WINDOWS_FILE

 static void GetAttribString(UInt32 wa, Bool isDir, char *s)

 {

+  #ifdef USE_WINDOWS_FILE

   s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');

   s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');

   s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN   ) != 0) ? 'H': '.');

   s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM   ) != 0) ? 'S': '.');

   s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE  ) != 0) ? 'A': '.');

-  s[5] = '\0';

+  s[5] = 0;

+  #else

+  s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');

+  s[1] = 0;

+  #endif

 }

-#else

-static void GetAttribString(UInt32, Bool, char *s)

-{

-  s[0] = '\0';

-}

-#endif

 

 // #define NUM_PARENTS_MAX 128

 

@@ -318,6 +358,7 @@
   // UInt32 parents[NUM_PARENTS_MAX];

 

   printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");

+

   if (numargs == 1)

   {

     printf(

@@ -329,6 +370,7 @@
       "  x: eXtract files with full paths\n");

     return 0;

   }

+  

   if (numargs < 3)

   {

     PrintError("incorrect command");

@@ -364,11 +406,14 @@
   CrcGenerateTable();

 

   SzArEx_Init(&db);

+  

   res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);

+  

   if (res == SZ_OK)

   {

     char *command = args[1];

     int listCommand = 0, testCommand = 0, fullPaths = 0;

+    

     if (strcmp(command, "l") == 0) listCommand = 1;

     else if (strcmp(command, "t") == 0) testCommand = 1;

     else if (strcmp(command, "e") == 0) { }

@@ -397,7 +442,7 @@
         size_t outSizeProcessed = 0;

         // const CSzFileItem *f = db.Files + i;

         size_t len;

-        int isDir = SzArEx_IsDir(&db, i);

+        unsigned isDir = SzArEx_IsDir(&db, i);

         if (listCommand == 0 && isDir && !fullPaths)

           continue;

         len = SzArEx_GetFileNameUtf16(&db, i, NULL);

@@ -433,6 +478,7 @@
 

           fileSize = SzArEx_GetFileSize(&db, i);

           UInt64ToStr(fileSize, s);

+          

           if (SzBitWithVals_Check(&db.MTime, i))

             ConvertFileTimeToString(&db.MTime.Vals[i], t);

           else

@@ -452,6 +498,7 @@
           printf("\n");

           continue;

         }

+

         fputs(testCommand ?

             "Testing    ":

             "Extracting ",

@@ -459,6 +506,7 @@
         res = PrintString(temp);

         if (res != SZ_OK)

           break;

+        

         if (isDir)

           printf("/");

         else

@@ -470,6 +518,7 @@
           if (res != SZ_OK)

             break;

         }

+        

         if (!testCommand)

         {

           CSzFile outFile;

@@ -477,6 +526,7 @@
           size_t j;

           UInt16 *name = (UInt16 *)temp;

           const UInt16 *destPath = (const UInt16 *)name;

+ 

           for (j = 0; name[j] != 0; j++)

             if (name[j] == '/')

             {

@@ -502,19 +552,23 @@
             res = SZ_ERROR_FAIL;

             break;

           }

+

           processedSize = outSizeProcessed;

+          

           if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)

           {

             PrintError("can not write output file");

             res = SZ_ERROR_FAIL;

             break;

           }

+          

           if (File_Close(&outFile))

           {

             PrintError("can not close output file");

             res = SZ_ERROR_FAIL;

             break;

           }

+          

           #ifdef USE_WINDOWS_FILE

           if (SzBitWithVals_Check(&db.Attribs, i))

             SetFileAttributesW(destPath, db.Attribs.Vals[i]);

@@ -525,15 +579,18 @@
       IAlloc_Free(&allocImp, outBuffer);

     }

   }

+

   SzArEx_Free(&db, &allocImp);

   SzFree(NULL, temp);

 

   File_Close(&archiveStream.file);

+  

   if (res == SZ_OK)

   {

     printf("\nEverything is Ok\n");

     return 0;

   }

+  

   if (res == SZ_ERROR_UNSUPPORTED)

     PrintError("decoder doesn't support this archive");

   else if (res == SZ_ERROR_MEM)

@@ -542,5 +599,6 @@
     PrintError("CRC error");

   else

     printf("\nERROR #%d\n", res);

+  

   return 1;

 }

diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
index 08e6f68..f4a54af 100644
--- a/C/Util/7z/makefile
+++ b/C/Util/7z/makefile
@@ -1,4 +1,3 @@
-# MY_STATIC_LINK=1

 CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT

 

 PROG = 7zDec.exe

@@ -15,7 +14,9 @@
   $O\Bcj2.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

   $O\Ppmd7.obj \

diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc
index 63c59ca..f707935 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 @@
 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 @@
 Bra86.o: ../../Bra86.c

 	$(CXX) $(CFLAGS) ../../Bra86.c

 

+BraIA64.o: ../../BraIA64.c

+	$(CXX) $(CFLAGS) ../../BraIA64.c

+

 Bcj2.o: ../../Bcj2.c

 	$(CXX) $(CFLAGS) ../../Bcj2.c

 

@@ -67,4 +73,3 @@
 

 clean:

 	-$(RM) $(PROG) $(OBJS)

-

diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
index ee659ba..98331b4 100644
--- a/C/Util/Lzma/LzmaUtil.c
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -1,5 +1,5 @@
 /* LzmaUtil.c -- Test application for LZMA compression

-2014-12-31 : Igor Pavlov : Public domain */

+2015-11-08 : Igor Pavlov : Public domain */

 

 #include "../../Precomp.h"

 

@@ -18,10 +18,6 @@
 const char *kCantAllocateMessage = "Can not allocate memory";

 const char *kDataErrorMessage = "Data error";

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 void PrintHelp(char *buffer)

 {

   strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"

@@ -137,7 +133,7 @@
   SRes res;

   CLzmaEncProps props;

 

-  rs = rs;

+  UNUSED_VAR(rs);

 

   enc = LzmaEnc_Create(&g_Alloc);

   if (enc == 0)

diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c
index 7434536..02600c7 100644
--- a/C/Util/LzmaLib/LzmaLibExports.c
+++ b/C/Util/LzmaLib/LzmaLibExports.c
@@ -1,12 +1,14 @@
 /* LzmaLibExports.c -- LZMA library DLL Entry point

-2008-10-04 : Igor Pavlov : Public domain */

+2015-11-08 : Igor Pavlov : Public domain */

+

+#include "../../Precomp.h"

 

 #include <windows.h>

 

 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

 {

-  hInstance = hInstance;

-  dwReason = dwReason;

-  lpReserved = lpReserved;

+  UNUSED_VAR(hInstance);

+  UNUSED_VAR(dwReason);

+  UNUSED_VAR(lpReserved);

   return TRUE;

 }

diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
index 5714e43..50e57ae 100644
--- a/C/Util/SfxSetup/SfxSetup.c
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -1,5 +1,5 @@
 /* SfxSetup.c - 7z SFX Setup

-2014-12-07 : Igor Pavlov : Public domain */

+2016-05-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -20,10 +20,11 @@
 #include "../../7zCrc.h"

 #include "../../7zFile.h"

 #include "../../CpuArch.h"

+#include "../../DllSecur.h"

 

 #define k_EXE_ExtIndex 2

 

-static const char *kExts[] =

+static const char * const kExts[] =

 {

     "bat"

   , "cmd"

@@ -37,7 +38,7 @@
   , "htm"

 };

 

-static const char *kNames[] =

+static const char * const kNames[] =

 {

     "setup"

   , "install"

@@ -63,7 +64,7 @@
 

 #define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))

 

-static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)

+static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len)

 {

   unsigned i;

   for (i = 0; i < num; i++)

@@ -75,7 +76,7 @@
       continue;

     for (j = 0; j < len; j++)

     {

-      unsigned c = item[j];

+      unsigned c = (Byte)item[j];

       if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])

         break;

     }

@@ -88,7 +89,7 @@
 #ifdef _CONSOLE

 static BOOL WINAPI HandlerRoutine(DWORD ctrlType)

 {

-  ctrlType = ctrlType;

+  UNUSED_VAR(ctrlType);

   return TRUE;

 }

 #endif

@@ -144,7 +145,7 @@
     processed -= k7zStartHeaderSize;

     for (pos = 0; pos <= processed; pos++)

     {

-      for (; buf[pos] != '7' && pos <= processed; pos++);

+      for (; pos <= processed && buf[pos] != '7'; pos++);

       if (pos > processed)

         break;

       if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)

@@ -182,6 +183,7 @@
   path[len] = L'\0';

   if (handle == INVALID_HANDLE_VALUE)

     return GetLastError();

+  

   for (;;)

   {

     if (wcscmp(fd.cFileName, L".") != 0 &&

@@ -199,9 +201,11 @@
         if (DeleteFileW(path) == 0)

           res = GetLastError();

       }

+    

       if (res != 0)

         break;

     }

+  

     if (!FindNextFileW(handle, &fd))

     {

       res = GetLastError();

@@ -210,6 +214,7 @@
       break;

     }

   }

+  

   path[len] = L'\0';

   FindClose(handle);

   if (res == 0)

@@ -248,14 +253,17 @@
   const wchar_t *cmdLineParams;

   const char *errorMessage = NULL;

   Bool useShellExecute = True;

+  DWORD exitCode = 0;

+

+  LoadSecurityDlls();

 

   #ifdef _CONSOLE

   SetConsoleCtrlHandler(HandlerRoutine, TRUE);

   #else

-  hInstance = hInstance;

-  hPrevInstance = hPrevInstance;

-  lpCmdLine = lpCmdLine;

-  nCmdShow = nCmdShow;

+  UNUSED_VAR(hInstance);

+  UNUSED_VAR(hPrevInstance);

+  UNUSED_VAR(lpCmdLine);

+  UNUSED_VAR(nCmdShow);

   #endif

 

   CrcGenerateTable();

@@ -315,7 +323,7 @@
         {

           unsigned t = value & 0xF;

           value >>= 4;

-          s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+          s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

         }

         s[k] = '\0';

       }

@@ -391,11 +399,9 @@
     {

       size_t offset = 0;

       size_t outSizeProcessed = 0;

-      size_t len;

       WCHAR *temp;

-      len = SzArEx_GetFileNameUtf16(&db, i, NULL);

-      

-      if (len >= MAX_PATH)

+

+      if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH)

       {

         res = SZ_ERROR_FAIL;

         break;

@@ -584,6 +590,8 @@
     if (hProcess != 0)

     {

       WaitForSingleObject(hProcess, INFINITE);

+      if (!GetExitCodeProcess(hProcess, &exitCode))

+        exitCode = 1;

       CloseHandle(hProcess);

     }

     

@@ -596,7 +604,7 @@
   RemoveDirWithSubItems(path);

 

   if (res == SZ_OK)

-    return 0;

+    return (int)exitCode;

   

   {

     if (res == SZ_ERROR_UNSUPPORTED)

@@ -610,6 +618,7 @@
       if (!errorMessage)

         errorMessage = "ERROR";

     }

+ 

     if (errorMessage)

       PrintErrorMessage(errorMessage);

   }

diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp
index 1d5fdd8..be9de6d 100644
--- a/C/Util/SfxSetup/SfxSetup.dsp
+++ b/C/Util/SfxSetup/SfxSetup.dsp
@@ -167,6 +167,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\BraIA64.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\CpuArch.c

 # End Source File

 # Begin Source File

@@ -175,6 +179,22 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Delta.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Delta.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\DllSecur.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\DllSecur.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Lzma2Dec.c

 # End Source File

 # Begin Source File

diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
index cc9878a..6985944 100644
--- a/C/Util/SfxSetup/makefile
+++ b/C/Util/SfxSetup/makefile
@@ -13,7 +13,10 @@
   $O\Bcj2.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\DllSecur.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

 

diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
index f8bbb1f..cb2c1a4 100644
--- a/C/Util/SfxSetup/makefile_con
+++ b/C/Util/SfxSetup/makefile_con
@@ -14,7 +14,10 @@
   $O\Bcj2.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\DllSecur.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

 

diff --git a/C/Xz.c b/C/Xz.c
index f7b5c24..92144db 100644
--- a/C/Xz.c
+++ b/C/Xz.c
@@ -1,5 +1,5 @@
 /* Xz.c - Xz

-2009-04-15 : Igor Pavlov : Public domain */

+2015-05-01 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -8,8 +8,8 @@
 #include "Xz.h"

 #include "XzCrc64.h"

 

-Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };

-Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };

+const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };

+const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };

 

 unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)

 {

@@ -40,11 +40,11 @@
 

 unsigned XzFlags_GetCheckSize(CXzStreamFlags f)

 {

-  int t = XzFlags_GetCheckType(f);

+  unsigned t = XzFlags_GetCheckType(f);

   return (t == 0) ? 0 : (4 << ((t - 1) / 3));

 }

 

-void XzCheck_Init(CXzCheck *p, int mode)

+void XzCheck_Init(CXzCheck *p, unsigned mode)

 {

   p->mode = mode;

   switch (mode)

diff --git a/C/Xz.h b/C/Xz.h
index 2512fd1..6937bea 100644
--- a/C/Xz.h
+++ b/C/Xz.h
@@ -1,5 +1,5 @@
 /* Xz.h - Xz interface

-2014-12-30 : Igor Pavlov : Public domain */

+2015-05-01 : Igor Pavlov : Public domain */

 

 #ifndef __XZ_H

 #define __XZ_H

@@ -59,8 +59,8 @@
 #define XZ_SIG_SIZE 6

 #define XZ_FOOTER_SIG_SIZE 2

 

-extern Byte XZ_SIG[XZ_SIG_SIZE];

-extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];

+extern const Byte XZ_SIG[XZ_SIG_SIZE];

+extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];

 

 #define XZ_STREAM_FLAGS_SIZE 2

 #define XZ_STREAM_CRC_SIZE 4

@@ -76,13 +76,13 @@
 

 typedef struct

 {

-  int mode;

+  unsigned mode;

   UInt32 crc;

   UInt64 crc64;

   CSha256 sha;

 } CXzCheck;

 

-void XzCheck_Init(CXzCheck *p, int mode);

+void XzCheck_Init(CXzCheck *p, unsigned mode);

 void XzCheck_Update(CXzCheck *p, const void *data, size_t size);

 int XzCheck_Final(CXzCheck *p, Byte *digest);

 

@@ -163,7 +163,7 @@
 {

   ISzAlloc *alloc;

   Byte *buf;

-  int numCoders;

+  unsigned numCoders;

   int finished[MIXCODER_NUM_FILTERS_MAX - 1];

   size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];

   size_t size[MIXCODER_NUM_FILTERS_MAX - 1];

@@ -174,7 +174,7 @@
 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);

 void MixCoder_Free(CMixCoder *p);

 void MixCoder_Init(CMixCoder *p);

-SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);

+SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);

 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,

     const Byte *src, SizeT *srcLen, int srcWasFinished,

     ECoderFinishMode finishMode, ECoderStatus *status);

diff --git a/C/XzCrc64.c b/C/XzCrc64.c
index 667e41b..bd0cf5a 100644
--- a/C/XzCrc64.c
+++ b/C/XzCrc64.c
@@ -1,5 +1,5 @@
 /* XzCrc64.c -- CRC64 calculation

-2011-06-28 : Igor Pavlov : Public domain */

+2015-03-01 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -13,14 +13,15 @@
 #else

   #define CRC_NUM_TABLES 5

   #define CRC_UINT64_SWAP(v) \

-  ((v >> 56) | \

-  ((v >> 40) & ((UInt64)0xFF <<  8)) | \

-  ((v >> 24) & ((UInt64)0xFF << 16)) | \

-  ((v >>  8) & ((UInt64)0xFF << 24)) | \

-  ((v <<  8) & ((UInt64)0xFF << 32)) | \

-  ((v << 24) & ((UInt64)0xFF << 40)) | \

-  ((v << 40) & ((UInt64)0xFF << 48)) | \

-   (v << 56))

+      ((v >> 56) \

+    | ((v >> 40) & ((UInt64)0xFF <<  8)) \

+    | ((v >> 24) & ((UInt64)0xFF << 16)) \

+    | ((v >>  8) & ((UInt64)0xFF << 24)) \

+    | ((v <<  8) & ((UInt64)0xFF << 32)) \

+    | ((v << 24) & ((UInt64)0xFF << 40)) \

+    | ((v << 40) & ((UInt64)0xFF << 48)) \

+    | ((v << 56)))

+

   UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table);

 #endif

 

@@ -64,11 +65,6 @@
 

   g_Crc64Update = XzCrc64UpdateT4;

 

-  

-

-

-

-

   #else

   {

     #ifndef MY_CPU_BE

diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c
index 65be5cd..97d086e 100644
--- a/C/XzCrc64Opt.c
+++ b/C/XzCrc64Opt.c
@@ -1,14 +1,14 @@
 /* XzCrc64Opt.c -- CRC64 calculation

-2011-06-28 : Igor Pavlov : Public domain */

+2015-03-01 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

 #include "CpuArch.h"

 

-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

-

 #ifndef MY_CPU_BE

 

+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

 UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table)

 {

   const Byte *p = (const Byte *)data;

@@ -17,11 +17,11 @@
   for (; size >= 4; size -= 4, p += 4)

   {

     UInt32 d = (UInt32)v ^ *(const UInt32 *)p;

-    v = (v >> 32) ^

-      table[0x300 + ((d      ) & 0xFF)] ^

-      table[0x200 + ((d >>  8) & 0xFF)] ^

-      table[0x100 + ((d >> 16) & 0xFF)] ^

-      table[0x000 + ((d >> 24))];

+    v = (v >> 32)

+        ^ table[0x300 + ((d      ) & 0xFF)]

+        ^ table[0x200 + ((d >>  8) & 0xFF)]

+        ^ table[0x100 + ((d >> 16) & 0xFF)]

+        ^ table[0x000 + ((d >> 24))];

   }

   for (; size > 0; size--, p++)

     v = CRC_UPDATE_BYTE_2(v, *p);

@@ -34,36 +34,36 @@
 #ifndef MY_CPU_LE

 

 #define CRC_UINT64_SWAP(v) \

-  ((v >> 56) | \

-  ((v >> 40) & ((UInt64)0xFF <<  8)) | \

-  ((v >> 24) & ((UInt64)0xFF << 16)) | \

-  ((v >>  8) & ((UInt64)0xFF << 24)) | \

-  ((v <<  8) & ((UInt64)0xFF << 32)) | \

-  ((v << 24) & ((UInt64)0xFF << 40)) | \

-  ((v << 40) & ((UInt64)0xFF << 48)) | \

-   (v << 56))

+      ((v >> 56) \

+    | ((v >> 40) & ((UInt64)0xFF <<  8)) \

+    | ((v >> 24) & ((UInt64)0xFF << 16)) \

+    | ((v >>  8) & ((UInt64)0xFF << 24)) \

+    | ((v <<  8) & ((UInt64)0xFF << 32)) \

+    | ((v << 24) & ((UInt64)0xFF << 40)) \

+    | ((v << 40) & ((UInt64)0xFF << 48)) \

+    | ((v << 56)))

+

+#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8))

 

 UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table)

 {

   const Byte *p = (const Byte *)data;

-  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)

-    v = CRC_UPDATE_BYTE_2(v, *p);

-  v = CRC_UINT64_SWAP(v);

   table += 0x100;

+  v = CRC_UINT64_SWAP(v);

+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

   for (; size >= 4; size -= 4, p += 4)

   {

     UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p;

-    v = (v << 32) ^

-      table[0x000 + ((d      ) & 0xFF)] ^

-      table[0x100 + ((d >>  8) & 0xFF)] ^

-      table[0x200 + ((d >> 16) & 0xFF)] ^

-      table[0x300 + ((d >> 24))];

+    v = (v << 32)

+        ^ table[0x000 + ((d      ) & 0xFF)]

+        ^ table[0x100 + ((d >>  8) & 0xFF)]

+        ^ table[0x200 + ((d >> 16) & 0xFF)]

+        ^ table[0x300 + ((d >> 24))];

   }

-  table -= 0x100;

-  v = CRC_UINT64_SWAP(v);

   for (; size > 0; size--, p++)

-    v = CRC_UPDATE_BYTE_2(v, *p);

-  return v;

+    v = CRC_UPDATE_BYTE_2_BE(v, *p);

+  return CRC_UINT64_SWAP(v);

 }

 

 #endif

diff --git a/C/XzDec.c b/C/XzDec.c
index e23f221..29831b0 100644
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,5 +1,5 @@
 /* XzDec.c -- Xz Decode

-2014-12-30 : Igor Pavlov : Public domain */

+2015-11-09 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -32,9 +32,9 @@
 

 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)

 {

-  int i, limit;

+  unsigned i, limit;

   *value = 0;

-  limit = (maxSize > 9) ? 9 : (int)maxSize;

+  limit = (maxSize > 9) ? 9 : (unsigned)maxSize;

 

   for (i = 0; i < limit;)

   {

@@ -66,15 +66,15 @@
   Byte buf[BRA_BUF_SIZE];

 } CBraState;

 

-void BraState_Free(void *pp, ISzAlloc *alloc)

+static void BraState_Free(void *pp, ISzAlloc *alloc)

 {

   alloc->Free(alloc, pp);

 }

 

-SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

+static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

 {

   CBraState *p = ((CBraState *)pp);

-  alloc = alloc;

+  UNUSED_VAR(alloc);

   p->ip = 0;

   if (p->methodId == XZ_ID_Delta)

   {

@@ -87,7 +87,7 @@
     if (propSize == 4)

     {

       UInt32 v = GetUi32(props);

-      switch(p->methodId)

+      switch (p->methodId)

       {

         case XZ_ID_PPC:

         case XZ_ID_ARM:

@@ -112,7 +112,7 @@
   return SZ_OK;

 }

 

-void BraState_Init(void *pp)

+static void BraState_Init(void *pp)

 {

   CBraState *p = ((CBraState *)pp);

   p->bufPos = p->bufConv = p->bufTotal = 0;

@@ -129,9 +129,9 @@
   CBraState *p = ((CBraState *)pp);

   SizeT destLenOrig = *destLen;

   SizeT srcLenOrig = *srcLen;

+  UNUSED_VAR(finishMode);

   *destLen = 0;

   *srcLen = 0;

-  finishMode = finishMode;

   *wasFinished = 0;

   while (destLenOrig > 0)

   {

@@ -163,7 +163,7 @@
     }

     if (p->bufTotal == 0)

       break;

-    switch(p->methodId)

+    switch (p->methodId)

     {

       case XZ_ID_Delta:

         if (p->encodeMode)

@@ -235,9 +235,9 @@
 

 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

 {

-  pp = pp;

-  props = props;

-  alloc = alloc;

+  UNUSED_VAR(pp);

+  UNUSED_VAR(props);

+  UNUSED_VAR(alloc);

   return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;

 }

 

@@ -251,7 +251,7 @@
 {

   CSbDec *p = (CSbDec *)pp;

   SRes res;

-  srcWasFinished = srcWasFinished;

+  UNUSED_VAR(srcWasFinished);

   p->dest = dest;

   p->destLen = *destLen;

   p->src = src;

@@ -308,7 +308,7 @@
   ELzmaStatus status;

   /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */

   SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);

-  srcWasFinished = srcWasFinished;

+  UNUSED_VAR(srcWasFinished);

   *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);

   return res;

 }

@@ -330,9 +330,9 @@
 

 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)

 {

-  int i;

+  unsigned i;

   p->alloc = alloc;

-  p->buf = 0;

+  p->buf = NULL;

   p->numCoders = 0;

   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)

     p->coders[i].p = NULL;

@@ -340,7 +340,7 @@
 

 void MixCoder_Free(CMixCoder *p)

 {

-  int i;

+  unsigned i;

   for (i = 0; i < p->numCoders; i++)

   {

     IStateCoder *sc = &p->coders[i];

@@ -351,14 +351,14 @@
   if (p->buf)

   {

     p->alloc->Free(p->alloc, p->buf);

-    p->buf = 0; /* 9.31: the BUG was fixed */

+    p->buf = NULL; /* 9.31: the BUG was fixed */

   }

 }

 

 void MixCoder_Init(CMixCoder *p)

 {

-  int i;

-  for (i = 0; i < p->numCoders - 1; i++)

+  unsigned i;

+  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)

   {

     p->size[i] = 0;

     p->pos[i] = 0;

@@ -371,11 +371,11 @@
   }

 }

 

-SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)

+SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)

 {

   IStateCoder *sc = &p->coders[coderIndex];

   p->ids[coderIndex] = methodId;

-  switch(methodId)

+  switch (methodId)

   {

     case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);

     #ifdef USE_SUBBLOCK

@@ -398,10 +398,10 @@
   *srcLen = 0;

   *status = CODER_STATUS_NOT_FINISHED;

 

-  if (p->buf == 0)

+  if (!p->buf)

   {

     p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));

-    if (p->buf == 0)

+    if (!p->buf)

       return SZ_ERROR_MEM;

   }

 

@@ -411,7 +411,7 @@
   for (;;)

   {

     Bool processed = False;

-    int i;

+    unsigned i;

     /*

     if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)

       break;

@@ -520,8 +520,8 @@
 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)

 {

   unsigned pos;

-  int numFilters, i;

-  UInt32 headerSize = (UInt32)header[0] << 2;

+  unsigned numFilters, i;

+  unsigned headerSize = (unsigned)header[0] << 2;

 

   if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))

     return SZ_ERROR_ARCHIVE;

@@ -555,9 +555,9 @@
     pos += (unsigned)size;

 

     #ifdef XZ_DUMP

-    printf("\nf[%d] = %2X: ", i, filter->id);

+    printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);

     {

-      int i;

+      unsigned i;

       for (i = 0; i < size; i++)

         printf(" %2X", filter->props[i]);

     }

@@ -572,9 +572,10 @@
 

 SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)

 {

-  int i;

+  unsigned i;

   Bool needReInit = True;

-  int numFilters = XzBlock_GetNumFilters(block);

+  unsigned numFilters = XzBlock_GetNumFilters(block);

+  

   if (numFilters == p->numCoders)

   {

     for (i = 0; i < numFilters; i++)

@@ -582,6 +583,7 @@
         break;

     needReInit = (i != numFilters);

   }

+  

   if (needReInit)

   {

     MixCoder_Free(p);

@@ -592,12 +594,14 @@
       RINOK(MixCoder_SetFromMethod(p, i, f->id));

     }

   }

+  

   for (i = 0; i < numFilters; i++)

   {

     const CXzFilter *f = &block->filters[numFilters - 1 - i];

     IStateCoder *sc = &p->coders[i];

     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));

   }

+  

   MixCoder_Init(p);

   return SZ_OK;

 }

diff --git a/C/XzEnc.c b/C/XzEnc.c
index 3263519..2e5a003 100644
--- a/C/XzEnc.c
+++ b/C/XzEnc.c
@@ -1,5 +1,5 @@
 /* XzEnc.c -- Xz Encode

-2014-12-30 : Igor Pavlov : Public domain */

+2015-09-16 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -10,6 +10,7 @@
 #include "Alloc.h"

 #include "Bra.h"

 #include "CpuArch.h"

+

 #ifdef USE_SUBBLOCK

 #include "Bcj3Enc.c"

 #include "SbFind.c"

@@ -18,14 +19,6 @@
 

 #include "XzEnc.h"

 

-static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }

-static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }

-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

-

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 #define XzBlock_ClearFlags(p)       (p)->flags = 0;

 #define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);

 #define XzBlock_SetHasPackSize(p)   (p)->flags |= XZ_BF_PACK_SIZE;

@@ -42,7 +35,7 @@
   return WriteBytes(s, buf, size);

 }

 

-SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)

+static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)

 {

   UInt32 crc;

   Byte header[XZ_STREAM_HEADER_SIZE];

@@ -54,17 +47,19 @@
   return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);

 }

 

-SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)

+

+static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)

 {

   Byte header[XZ_BLOCK_HEADER_SIZE_MAX];

 

   unsigned pos = 1;

-  int numFilters, i;

+  unsigned numFilters, i;

   header[pos++] = p->flags;

 

   if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);

   if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);

   numFilters = XzBlock_GetNumFilters(p);

+  

   for (i = 0; i < numFilters; i++)

   {

     const CXzFilter *f = &p->filters[i];

@@ -73,14 +68,17 @@
     memcpy(header + pos, f->props, f->propsSize);

     pos += f->propsSize;

   }

-  while((pos & 3) != 0)

+

+  while ((pos & 3) != 0)

     header[pos++] = 0;

+

   header[0] = (Byte)(pos >> 2);

   SetUi32(header + pos, CrcCalc(header, pos));

   return WriteBytes(s, header, pos + 4);

 }

 

-SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)

+

+static SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)

 {

   Byte buf[32];

   UInt64 globalPos;

@@ -92,6 +90,7 @@
     globalPos = pos;

     buf[0] = 0;

     RINOK(WriteBytesAndCrc(s, buf, pos, &crc));

+

     for (i = 0; i < p->numBlocks; i++)

     {

       const CXzBlockSizes *block = &p->blocks[i];

@@ -100,7 +99,9 @@
       globalPos += pos;

       RINOK(WriteBytesAndCrc(s, buf, pos, &crc));

     }

+    

     pos = ((unsigned)globalPos & 3);

+    

     if (pos != 0)

     {

       buf[0] = buf[1] = buf[2] = 0;

@@ -125,34 +126,36 @@
   }

 }

 

-SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)

+

+static SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)

 {

-  if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)

+  if (!p->blocks || p->numBlocksAllocated == p->numBlocks)

   {

-    size_t num = (p->numBlocks + 1) * 2;

+    size_t num = p->numBlocks * 2 + 1;

     size_t newSize = sizeof(CXzBlockSizes) * num;

     CXzBlockSizes *blocks;

     if (newSize / sizeof(CXzBlockSizes) != num)

       return SZ_ERROR_MEM;

     blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize);

-    if (blocks == 0)

+    if (!blocks)

       return SZ_ERROR_MEM;

     if (p->numBlocks != 0)

     {

       memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));

-      Xz_Free(p, alloc);

+      alloc->Free(alloc, p->blocks);

     }

     p->blocks = blocks;

     p->numBlocksAllocated = num;

   }

   {

     CXzBlockSizes *block = &p->blocks[p->numBlocks++];

-    block->totalSize = totalSize;

     block->unpackSize = unpackSize;

+    block->totalSize = totalSize;

   }

   return SZ_OK;

 }

 

+

 /* ---------- CSeqCheckInStream ---------- */

 

 typedef struct

@@ -163,13 +166,13 @@
   CXzCheck check;

 } CSeqCheckInStream;

 

-void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)

+static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned mode)

 {

   p->processed = 0;

   XzCheck_Init(&p->check, mode);

 }

 

-void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)

+static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)

 {

   XzCheck_Final(&p->check, digest);

 }

@@ -183,6 +186,7 @@
   return res;

 }

 

+

 /* ---------- CSeqSizeOutStream ---------- */

 

 typedef struct

@@ -200,6 +204,7 @@
   return size;

 }

 

+

 /* ---------- CSeqInFilter ---------- */

 

 #define FILTER_BUF_SIZE (1 << 20)

@@ -222,6 +227,7 @@
   if (sizeOriginal == 0)

     return SZ_OK;

   *size = 0;

+  

   for (;;)

   {

     if (!p->srcWasFinished && p->curPos == p->endPos)

@@ -279,6 +285,7 @@
   return SZ_OK;

 }

 

+

 /* ---------- CSbEncInStream ---------- */

 

 #ifdef USE_SUBBLOCK

@@ -296,6 +303,7 @@
   size_t sizeOriginal = *size;

   if (sizeOriginal == 0)

     return S_OK;

+  

   for (;;)

   {

     if (p->enc.needRead && !p->enc.readWasFinished)

@@ -310,6 +318,7 @@
       }

       p->enc.needRead = False;

     }

+  

     *size = sizeOriginal;

     RINOK(SbEnc_Read(&p->enc, data, size));

     if (*size != 0 || !p->enc.needRead)

@@ -362,7 +371,7 @@
 static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)

 {

   p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);

-  if (p->lzma2 == 0)

+  if (!p->lzma2)

     return SZ_ERROR_MEM;

   return SZ_OK;

 }

@@ -380,10 +389,11 @@
   }

 }

 

+

 void XzProps_Init(CXzProps *p)

 {

-  p->lzma2Props = 0;

-  p->filterProps = 0;

+  p->lzma2Props = NULL;

+  p->filterProps = NULL;

   p->checkId = XZ_CHECK_CRC32;

 }

 

@@ -391,10 +401,11 @@
 {

   p->id = 0;

   p->delta = 0;

-  p->ip= 0;

+  p->ip = 0;

   p->ipDefined = False;

 }

 

+

 static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,

     ISeqOutStream *outStream, ISeqInStream *inStream,

     const CXzProps *props, ICompressProgress *progress)

@@ -408,7 +419,7 @@
     CSeqCheckInStream checkInStream;

     CSeqSizeOutStream seqSizeOutStream;

     CXzBlock block;

-    int filterIndex = 0;

+    unsigned filterIndex = 0;

     CXzFilter *filter = NULL;

     const CXzFilterProps *fp = props->filterProps;

     

@@ -420,6 +431,7 @@
       filter = &block.filters[filterIndex++];

       filter->id = fp->id;

       filter->propsSize = 0;

+      

       if (fp->id == XZ_ID_Delta)

       {

         filter->props[0] = (Byte)(fp->delta - 1);

@@ -467,14 +479,16 @@
 

     {

       UInt64 packPos = seqSizeOutStream.processed;

+      

       SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,

-        fp ?

-        #ifdef USE_SUBBLOCK

-        (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:

-        #endif

-        &lzmaf->filter.p:

-        &checkInStream.p,

-        progress);

+          fp ?

+            #ifdef USE_SUBBLOCK

+            (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:

+            #endif

+            &lzmaf->filter.p:

+            &checkInStream.p,

+          progress);

+      

       RINOK(res);

       block.unpackSize = checkInStream.processed;

       block.packSize = seqSizeOutStream.processed - packPos;

@@ -483,7 +497,7 @@
     {

       unsigned padSize = 0;

       Byte buf[128];

-      while((((unsigned)block.packSize + padSize) & 3) != 0)

+      while ((((unsigned)block.packSize + padSize) & 3) != 0)

         buf[padSize++] = 0;

       SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);

       RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));

@@ -493,6 +507,7 @@
   return Xz_WriteFooter(xz, outStream);

 }

 

+

 SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,

     const CXzProps *props, ICompressProgress *progress)

 {

@@ -509,6 +524,7 @@
   return res;

 }

 

+

 SRes Xz_EncodeEmpty(ISeqOutStream *outStream)

 {

   SRes res;

diff --git a/C/XzIn.c b/C/XzIn.c
index c99d71c..aaa0597 100644
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,5 @@
 /* XzIn.c - Xz input

-2014-12-30 : Igor Pavlov : Public domain */

+2015-11-08 : Igor Pavlov : Public domain */

 

 #include "Precomp.h"

 

@@ -72,7 +72,7 @@
 

 static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)

 {

-  size_t i, numBlocks, pos = 1;

+  size_t numBlocks, pos = 1;

   UInt32 crc;

 

   if (size < 5 || buf[0] != 0)

@@ -94,6 +94,7 @@
   Xz_Free(p, alloc);

   if (numBlocks != 0)

   {

+    size_t i;

     p->numBlocks = numBlocks;

     p->numBlocksAllocated = numBlocks;

     p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);

@@ -134,55 +135,58 @@
   return res;

 }

 

-static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)

+static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, void *buf, size_t size)

 {

-  return inStream->Seek(inStream, res, SZ_SEEK_CUR);

+  RINOK(LookInStream_SeekTo(stream, offset));

+  return LookInStream_Read(stream, buf, size);

+  /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */

 }

 

 static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)

 {

   UInt64 indexSize;

   Byte buf[XZ_STREAM_FOOTER_SIZE];

+  UInt64 pos = *startOffset;

 

-  if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)

+  if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE)

     return SZ_ERROR_NO_ARCHIVE;

-  *startOffset = -XZ_STREAM_FOOTER_SIZE;

-  RINOK(SeekFromCur(stream, startOffset));

 

-  RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));

+  pos -= XZ_STREAM_FOOTER_SIZE;

+  RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));

   

   if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

   {

     UInt32 total = 0;

-    *startOffset += XZ_STREAM_FOOTER_SIZE;

+    pos += XZ_STREAM_FOOTER_SIZE;

+    

     for (;;)

     {

       size_t i;

       #define TEMP_BUF_SIZE (1 << 10)

-      Byte tempBuf[TEMP_BUF_SIZE];

-      if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))

-        return SZ_ERROR_NO_ARCHIVE;

-      i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;

+      Byte temp[TEMP_BUF_SIZE];

+      

+      i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos;

+      pos -= i;

+      RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i));

       total += (UInt32)i;

-      *startOffset = -(Int64)i;

-      RINOK(SeekFromCur(stream, startOffset));

-      RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE));

       for (; i != 0; i--)

-        if (tempBuf[i - 1] != 0)

+        if (temp[i - 1] != 0)

           break;

       if (i != 0)

       {

         if ((i & 3) != 0)

           return SZ_ERROR_NO_ARCHIVE;

-        *startOffset += i;

+        pos += i;

         break;

       }

+      if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))

+        return SZ_ERROR_NO_ARCHIVE;

     }

-    if (*startOffset < XZ_STREAM_FOOTER_SIZE)

+    

+    if (pos < XZ_STREAM_FOOTER_SIZE)

       return SZ_ERROR_NO_ARCHIVE;

-    *startOffset -= XZ_STREAM_FOOTER_SIZE;

-    RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));

-    RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));

+    pos -= XZ_STREAM_FOOTER_SIZE;

+    RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));

     if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

       return SZ_ERROR_NO_ARCHIVE;

   }

@@ -197,20 +201,22 @@
 

   indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;

 

-  *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);

-  RINOK(SeekFromCur(stream, startOffset));

+  if (pos < indexSize)

+    return SZ_ERROR_ARCHIVE;

 

+  pos -= indexSize;

+  RINOK(LookInStream_SeekTo(stream, pos));

   RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));

 

   {

     UInt64 totalSize = Xz_GetPackSize(p);

-    UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;

-    if (totalSize == XZ_SIZE_OVERFLOW ||

-      sum >= ((UInt64)1 << 63) ||

-      totalSize >= ((UInt64)1 << 63))

+    if (totalSize == XZ_SIZE_OVERFLOW

+        || totalSize >= ((UInt64)1 << 63)

+        || pos < totalSize + XZ_STREAM_HEADER_SIZE)

       return SZ_ERROR_ARCHIVE;

-    *startOffset = -(Int64)sum;

-    RINOK(SeekFromCur(stream, startOffset));

+    pos -= (totalSize + XZ_STREAM_HEADER_SIZE);

+    RINOK(LookInStream_SeekTo(stream, pos));

+    *startOffset = pos;

   }

   {

     CXzStreamFlags headerFlags;

@@ -299,7 +305,7 @@
     p->streams[p->num++] = st;

     if (*startOffset == 0)

       break;

-    RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));

+    RINOK(LookInStream_SeekTo(stream, *startOffset));

     if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)

       return SZ_ERROR_PROGRESS;

   }

diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 3301b93..80e4154 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -9,37 +9,62 @@
 namespace NArchive {

 namespace N7z {

 

-struct CMethodFull: public CProps

+struct CMethodFull: public CMethodProps

 {

   CMethodId Id;

-  UInt32 NumInStreams;

-  UInt32 NumOutStreams;

+  UInt32 NumStreams;

 

-  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

+  bool IsSimpleCoder() const { return NumStreams == 1; }

 };

 

-struct CBind

+struct CBond2

 {

-  UInt32 InCoder;

-  UInt32 InStream;

   UInt32 OutCoder;

   UInt32 OutStream;

+  UInt32 InCoder;

 };

 

 struct CCompressionMethodMode

 {

+  /*

+    if (Bonds.Empty()), then default bonds must be created

+    if (Filter_was_Inserted)

+    {

+      Methods[0] is filter method

+      Bonds don't contain bonds for filter (these bonds must be created)

+    }

+  */

+

   CObjectVector<CMethodFull> Methods;

-  CRecordVector<CBind> Binds;

+  CRecordVector<CBond2> Bonds;

+

+  bool IsThereBond_to_Coder(unsigned coderIndex) const

+  {

+    FOR_VECTOR(i, Bonds)

+      if (Bonds[i].InCoder == coderIndex)

+        return true;

+    return false;

+  }

+

+  bool DefaultMethod_was_Inserted;

+  bool Filter_was_Inserted;

+

   #ifndef _7ZIP_ST

   UInt32 NumThreads;

+  bool MultiThreadMixer;

   #endif

+  

   bool PasswordIsDefined;

   UString Password;

 

   bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }

-  CCompressionMethodMode(): PasswordIsDefined(false)

+  CCompressionMethodMode():

+      DefaultMethod_was_Inserted(false),

+      Filter_was_Inserted(false),

+      PasswordIsDefined(false)

       #ifndef _7ZIP_ST

       , NumThreads(1)

+      , MultiThreadMixer(true)

       #endif

   {}

 };

diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index d58fb02..1f709cb 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -3,7 +3,6 @@
 #include "StdAfx.h"

 

 #include "../../Common/LimitedStreams.h"

-#include "../../Common/LockedStream.h"

 #include "../../Common/ProgressUtils.h"

 #include "../../Common/StreamObjects.h"

 

@@ -12,50 +11,70 @@
 namespace NArchive {

 namespace N7z {

 

-static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,

-    CBindInfoEx &bindInfo)

+class CDecProgress:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

 {

-  bindInfo.Clear();

-  bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());

+  CMyComPtr<ICompressProgressInfo> _progress;

+public:

+  CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}

+  

+  MY_UNKNOWN_IMP1(ICompressProgressInfo)

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

+STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)

+{

+  return _progress->SetRatioInfo(NULL, outSize);

+}

+

+static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)

+{

+  bi.Clear();

+  

+  bi.Bonds.ClearAndSetSize(folder.Bonds.Size());

   unsigned i;

-  for (i = 0; i < folder.BindPairs.Size(); i++)

+  for (i = 0; i < folder.Bonds.Size(); i++)

   {

-    NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];

-    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;

-    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;

+    NCoderMixer2::CBond &bond = bi.Bonds[i];

+    const N7z::CBond &folderBond = folder.Bonds[i];

+    bond.PackIndex = folderBond.PackIndex;

+    bond.UnpackIndex = folderBond.UnpackIndex;

   }

 

-  bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());

-  bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());

-

-  UInt32 outStreamIndex = 0;

+  bi.Coders.ClearAndSetSize(folder.Coders.Size());

+  bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());

   for (i = 0; i < folder.Coders.Size(); i++)

   {

-    NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];

     const CCoderInfo &coderInfo = folder.Coders[i];

-    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;

-    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;

-    bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;

-    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)

-      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)

-        bindInfo.OutStreams.Add(outStreamIndex);

+    bi.Coders[i].NumStreams = coderInfo.NumStreams;

+    bi.CoderMethodIDs[i] = coderInfo.MethodID;

   }

-  bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());

+  

+  /*

+  if (!bi.SetUnpackCoder())

+    throw 1112;

+  */

+  bi.UnpackCoder = folder.UnpackCoder;

+  bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());

   for (i = 0; i < folder.PackStreams.Size(); i++)

-    bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];

+    bi.PackStreams[i] = folder.PackStreams[i];

 }

 

-static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,

-    const NCoderMixer::CCoderStreamsInfo &a2)

+static inline bool AreCodersEqual(

+    const NCoderMixer2::CCoderStreamsInfo &a1,

+    const NCoderMixer2::CCoderStreamsInfo &a2)

 {

-  return (a1.NumInStreams == a2.NumInStreams) &&

-    (a1.NumOutStreams == a2.NumOutStreams);

+  return (a1.NumStreams == a2.NumStreams);

 }

 

-static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)

+static inline bool AreBondsEqual(

+    const NCoderMixer2::CBond &a1,

+    const NCoderMixer2::CBond &a2)

 {

-  return (a1.InIndex == a2.InIndex) &&

-    (a1.OutIndex == a2.OutIndex);

+  return

+    (a1.PackIndex == a2.PackIndex) &&

+    (a1.UnpackIndex == a2.UnpackIndex);

 }

 

 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)

@@ -66,186 +85,290 @@
   for (i = 0; i < a1.Coders.Size(); i++)

     if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))

       return false;

-  if (a1.BindPairs.Size() != a2.BindPairs.Size())

+  

+  if (a1.Bonds.Size() != a2.Bonds.Size())

     return false;

-  for (i = 0; i < a1.BindPairs.Size(); i++)

-    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))

+  for (i = 0; i < a1.Bonds.Size(); i++)

+    if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))

       return false;

+  

   for (i = 0; i < a1.CoderMethodIDs.Size(); i++)

     if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])

       return false;

-  if (a1.InStreams.Size() != a2.InStreams.Size())

+  

+  if (a1.PackStreams.Size() != a2.PackStreams.Size())

     return false;

-  if (a1.OutStreams.Size() != a2.OutStreams.Size())

+  for (i = 0; i < a1.PackStreams.Size(); i++)

+    if (a1.PackStreams[i] != a2.PackStreams[i])

+      return false;

+

+  /*

+  if (a1.UnpackCoder != a2.UnpackCoder)

     return false;

+  */

   return true;

 }

 

-CDecoder::CDecoder(bool multiThread)

+CDecoder::CDecoder(bool useMixerMT):

+    _bindInfoPrev_Defined(false),

+    _useMixerMT(useMixerMT)

+{}

+

+

+struct CLockedInStream:

+  public IUnknown,

+  public CMyUnknownImp

 {

-  #ifndef _ST_MODE

-  multiThread = true;

+  CMyComPtr<IInStream> Stream;

+  UInt64 Pos;

+

+  MY_UNKNOWN_IMP

+

+  #ifdef USE_MIXER_MT

+  NWindows::NSynchronization::CCriticalSection CriticalSection;

   #endif

-  _multiThread = multiThread;

-  _bindInfoExPrevIsDefined = false;

+};

+

+

+#ifdef USE_MIXER_MT

+

+class CLockedSequentialInStreamMT:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  CLockedInStream *_glob;

+  UInt64 _pos;

+  CMyComPtr<IUnknown> _globRef;

+public:

+  void Init(CLockedInStream *lockedInStream, UInt64 startPos)

+  {

+    _globRef = lockedInStream;

+    _glob = lockedInStream;

+    _pos = startPos;

+  }

+

+  MY_UNKNOWN_IMP1(ISequentialInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);

+

+  if (_pos != _glob->Pos)

+  {

+    RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));

+    _glob->Pos = _pos;

+  }

+

+  UInt32 realProcessedSize = 0;

+  HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);

+  _pos += realProcessedSize;

+  _glob->Pos = _pos;

+  if (processedSize)

+    *processedSize = realProcessedSize;

+  return res;

 }

 

+#endif

+

+

+#ifdef USE_MIXER_ST

+

+class CLockedSequentialInStreamST:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  CLockedInStream *_glob;

+  UInt64 _pos;

+  CMyComPtr<IUnknown> _globRef;

+public:

+  void Init(CLockedInStream *lockedInStream, UInt64 startPos)

+  {

+    _globRef = lockedInStream;

+    _glob = lockedInStream;

+    _pos = startPos;

+  }

+

+  MY_UNKNOWN_IMP1(ISequentialInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (_pos != _glob->Pos)

+  {

+    RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));

+    _glob->Pos = _pos;

+  }

+

+  UInt32 realProcessedSize = 0;

+  HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);

+  _pos += realProcessedSize;

+  _glob->Pos = _pos;

+  if (processedSize)

+    *processedSize = realProcessedSize;

+  return res;

+}

+

+#endif

+

+

+

 HRESULT CDecoder::Decode(

     DECL_EXTERNAL_CODECS_LOC_VARS

     IInStream *inStream,

     UInt64 startPos,

-    const CFolders &folders, int folderIndex,

-    ISequentialOutStream *outStream,

-    ICompressProgressInfo *compressProgress

+    const CFolders &folders, unsigned folderIndex,

+    const UInt64 *unpackSize

+

+    , ISequentialOutStream *outStream

+    , ICompressProgressInfo *compressProgress

+    , ISequentialInStream **

+

+    #ifdef USE_MIXER_ST

+    inStreamMainRes

+    #endif

+    

     _7Z_DECODER_CRYPRO_VARS_DECL

+

     #if !defined(_7ZIP_ST) && !defined(_SFX)

     , bool mtMode, UInt32 numThreads

     #endif

     )

 {

   const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];

-  CFolder folderInfo;

-  folders.ParseFolderInfo(folderIndex, folderInfo);

+  CFolderEx folderInfo;

+  folders.ParseFolderEx(folderIndex, folderInfo);

 

-  if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))

+  if (!folderInfo.IsDecodingSupported())

+    return E_NOTIMPL;

+

+  CBindInfoEx bindInfo;

+  Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);

+  if (!bindInfo.CalcMapsAndCheck())

     return E_NOTIMPL;

   

+  UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);

+  bool fullUnpack = true;

+  if (unpackSize)

+  {

+    if (*unpackSize > folderUnpackSize)

+      return E_FAIL;

+    fullUnpack = (*unpackSize == folderUnpackSize);

+  }

+

   /*

   We don't need to init isEncrypted and passwordIsDefined

   We must upgrade them only

+  

   #ifndef _NO_CRYPTO

   isEncrypted = false;

   passwordIsDefined = false;

   #endif

   */

-

-  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;

   

-  CLockedInStream lockedInStream;

-  lockedInStream.Init(inStream);

-  

-  for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)

+  if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))

   {

-    CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;

-    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;

-    lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);

-    CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;

-    CMyComPtr<ISequentialInStream> inStream = streamSpec;

-    streamSpec->SetStream(lockedStreamImp);

-    streamSpec->Init(packPositions[j + 1] - packPositions[j]);

-    inStreams.Add(inStream);

-  }

-  

-  unsigned numCoders = folderInfo.Coders.Size();

-  

-  CBindInfoEx bindInfo;

-  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);

-  bool createNewCoders;

-  if (!_bindInfoExPrevIsDefined)

-    createNewCoders = true;

-  else

-    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);

-  if (createNewCoders)

-  {

-    unsigned i;

-    _decoders.Clear();

-    // _decoders2.Clear();

-    

-    _mixerCoder.Release();

+    _mixerRef.Release();

 

-    if (_multiThread)

+    #ifdef USE_MIXER_MT

+    #ifdef USE_MIXER_ST

+    if (_useMixerMT)

+    #endif

     {

-      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;

-      _mixerCoder = _mixerCoderMTSpec;

-      _mixerCoderCommon = _mixerCoderMTSpec;

+      _mixerMT = new NCoderMixer2::CMixerMT(false);

+      _mixerRef = _mixerMT;

+      _mixer = _mixerMT;

     }

+    #ifdef USE_MIXER_ST

     else

+    #endif

+    #endif

     {

-      #ifdef _ST_MODE

-      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;

-      _mixerCoder = _mixerCoderSTSpec;

-      _mixerCoderCommon = _mixerCoderSTSpec;

+      #ifdef USE_MIXER_ST

+      _mixerST = new NCoderMixer2::CMixerST(false);

+      _mixerRef = _mixerST;

+      _mixer = _mixerST;

       #endif

     }

-    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));

     

-    for (i = 0; i < numCoders; i++)

+    RINOK(_mixer->SetBindInfo(bindInfo));

+    

+    FOR_VECTOR(i, folderInfo.Coders)

     {

       const CCoderInfo &coderInfo = folderInfo.Coders[i];

 

+      #ifndef _SFX

+      // we don't support RAR codecs here

+      if ((coderInfo.MethodID >> 8) == 0x403)

+        return E_NOTIMPL;

+      #endif

   

-      CMyComPtr<ICompressCoder> decoder;

-      CMyComPtr<ICompressCoder2> decoder2;

+      CCreatedCoder cod;

       RINOK(CreateCoder(

           EXTERNAL_CODECS_LOC_VARS

-          coderInfo.MethodID, decoder, decoder2, false));

-      CMyComPtr<IUnknown> decoderUnknown;

+          coderInfo.MethodID, false, cod));

+    

       if (coderInfo.IsSimpleCoder())

       {

-        if (decoder == 0)

+        if (!cod.Coder)

           return E_NOTIMPL;

-

-        decoderUnknown = (IUnknown *)decoder;

-        

-        if (_multiThread)

-          _mixerCoderMTSpec->AddCoder(decoder);

-        #ifdef _ST_MODE

-        else

-          _mixerCoderSTSpec->AddCoder(decoder, false);

-        #endif

+        // CMethodId m = coderInfo.MethodID;

+        // isFilter = (IsFilterMethod(m) || m == k_AES);

       }

       else

       {

-        if (decoder2 == 0)

+        if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)

           return E_NOTIMPL;

-        decoderUnknown = (IUnknown *)decoder2;

-        if (_multiThread)

-          _mixerCoderMTSpec->AddCoder2(decoder2);

-        #ifdef _ST_MODE

-        else

-          _mixerCoderSTSpec->AddCoder2(decoder2, false);

-        #endif

       }

-      _decoders.Add(decoderUnknown);

+      _mixer->AddCoder(cod);

+      

+      // now there is no codec that uses another external codec

+      /*

       #ifdef EXTERNAL_CODECS

       CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

       decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

       if (setCompressCodecsInfo)

       {

+        // we must use g_ExternalCodecs also

         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));

       }

       #endif

+      */

     }

-    _bindInfoExPrev = bindInfo;

-    _bindInfoExPrevIsDefined = true;

+    

+    _bindInfoPrev = bindInfo;

+    _bindInfoPrev_Defined = true;

   }

-  unsigned i;

-  _mixerCoderCommon->ReInit();

+

+  _mixer->ReInit();

   

   UInt32 packStreamIndex = 0;

   UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];

-  UInt32 unpackStreamIndex = unpackStreamIndexStart;

-  UInt32 coderIndex = 0;

-  // UInt32 coder2Index = 0;

-  

-  for (i = 0; i < numCoders; i++)

+

+  unsigned i;

+

+  for (i = 0; i < folderInfo.Coders.Size(); i++)

   {

     const CCoderInfo &coderInfo = folderInfo.Coders[i];

-    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];

-    

+    IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();

+

     {

       CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;

-      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);

+      decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);

       if (setDecoderProperties)

       {

         const CByteBuffer &props = coderInfo.Props;

         size_t size = props.Size();

         if (size > 0xFFFFFFFF)

           return E_NOTIMPL;

-        // if (size > 0)

-        {

-          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));

-        }

+        HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);

+        if (res == E_INVALIDARG)

+          res = E_NOTIMPL;

+        RINOK(res);

       }

     }

 

@@ -253,7 +376,7 @@
     if (mtMode)

     {

       CMyComPtr<ICompressSetCoderMt> setCoderMt;

-      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);

+      decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);

       if (setCoderMt)

       {

         RINOK(setCoderMt->SetNumberOfThreads(numThreads));

@@ -264,7 +387,7 @@
     #ifndef _NO_CRYPTO

     {

       CMyComPtr<ICryptoSetPassword> cryptoSetPassword;

-      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);

+      decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);

       if (cryptoSetPassword)

       {

         isEncrypted = true;

@@ -273,71 +396,148 @@
         CMyComBSTR passwordBSTR;

         RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));

         passwordIsDefined = true;

+        password.Empty();

         size_t len = 0;

         if (passwordBSTR)

-          len = MyStringLen((BSTR)passwordBSTR);

-        CByteBuffer buffer(len * 2);

-        for (size_t i = 0; i < len; i++)

         {

-          wchar_t c = passwordBSTR[i];

-          ((Byte *)buffer)[i * 2] = (Byte)c;

-          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);

+          password = passwordBSTR;

+          len = password.Len();

+        }

+        CByteBuffer buffer(len * 2);

+        for (size_t k = 0; k < len; k++)

+        {

+          wchar_t c = passwordBSTR[k];

+          ((Byte *)buffer)[k * 2] = (Byte)c;

+          ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);

         }

         RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));

       }

     }

     #endif

 

-    coderIndex++;

-    

-    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;

-    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;

-    CObjArray<UInt64> packSizes(numInStreams);

-    CObjArray<const UInt64 *> packSizesPointers(numInStreams);

-    CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);

-    UInt32 j;

-

-    for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)

-      unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];

-    

-    for (j = 0; j < numInStreams; j++, packStreamIndex++)

     {

-      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);

-      if (bindPairIndex >= 0)

-        packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];

-      else

+      CMyComPtr<ICompressSetFinishMode> setFinishMode;

+      decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);

+      if (setFinishMode)

       {

-        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);

-        if (index < 0)

-          return S_FALSE; // check it

-        packSizes[j] = packPositions[index + 1] - packPositions[index];

-        packSizesPointers[j] = &packSizes[j];

+        RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));

       }

     }

     

-    _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);

-  }

-  UInt32 mainCoder, temp;

-  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);

+    UInt32 numStreams = (UInt32)coderInfo.NumStreams;

+    

+    CObjArray<UInt64> packSizes(numStreams);

+    CObjArray<const UInt64 *> packSizesPointers(numStreams);

+       

+    for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)

+    {

+      int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);

+      

+      if (bond >= 0)

+        packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];

+      else

+      {

+        int index = folderInfo.Find_in_PackStreams(packStreamIndex);

+        if (index < 0)

+          return E_NOTIMPL;

+        packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];

+        packSizesPointers[j] = &packSizes[j];

+      }

+    }

 

-  if (_multiThread)

-    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);

-  /*

-  else

-    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;

-  */

+    const UInt64 *unpackSizesPointer =

+        (unpackSize && i == bindInfo.UnpackCoder) ?

+            unpackSize :

+            &folders.CoderUnpackSizes[unpackStreamIndexStart + i];

+    

+    _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);

+  }

+

+  if (outStream)

+  {

+    _mixer->SelectMainCoder(!fullUnpack);

+  }

+

+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;

   

-  if (numCoders == 0)

-    return 0;

+  CLockedInStream *lockedInStreamSpec = new CLockedInStream;

+  CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;

+

+  bool needMtLock = false;

+

+  if (folderInfo.PackStreams.Size() > 1)

+  {

+    // lockedInStream.Pos = (UInt64)(Int64)-1;

+    // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));

+    RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));

+    lockedInStreamSpec->Stream = inStream;

+

+    #ifdef USE_MIXER_ST

+    if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))

+    #endif

+      needMtLock = true;

+  }

+

+  for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)

+  {

+    CMyComPtr<ISequentialInStream> packStream;

+    UInt64 packPos = startPos + packPositions[j];

+

+    if (folderInfo.PackStreams.Size() == 1)

+    {

+      RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));

+      packStream = inStream;

+    }

+    else

+    {

+      #ifdef USE_MIXER_MT

+      #ifdef USE_MIXER_ST

+      if (_useMixerMT || needMtLock)

+      #endif

+      {

+        CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;

+        packStream = lockedStreamImpSpec;

+        lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);

+      }

+      #ifdef USE_MIXER_ST

+      else

+      #endif

+      #endif

+      {

+        #ifdef USE_MIXER_ST

+        CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;

+        packStream = lockedStreamImpSpec;

+        lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);

+        #endif

+      }

+    }

+

+    CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;

+    inStreams.AddNew() = streamSpec;

+    streamSpec->SetStream(packStream);

+    streamSpec->Init(packPositions[j + 1] - packPositions[j]);

+  }

+  

   unsigned num = inStreams.Size();

   CObjArray<ISequentialInStream *> inStreamPointers(num);

   for (i = 0; i < num; i++)

     inStreamPointers[i] = inStreams[i];

-  ISequentialOutStream *outStreamPointer = outStream;

-  return _mixerCoder->Code(

-      inStreamPointers, NULL, num,

-      &outStreamPointer, NULL, 1,

-      compressProgress);

+

+  if (outStream)

+  {

+    CMyComPtr<ICompressProgressInfo> progress2;

+    if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))

+      progress2 = new CDecProgress(compressProgress);

+

+    ISequentialOutStream *outStreamPointer = outStream;

+    return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);

+  }

+  

+  #ifdef USE_MIXER_ST

+    return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);

+  #else

+    return E_FAIL;

+  #endif

 }

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index f27170d..051f843 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -3,25 +3,17 @@
 #ifndef __7Z_DECODE_H

 #define __7Z_DECODE_H

 

-#include "../../IStream.h"

-#include "../../IPassword.h"

-

 #include "../Common/CoderMixer2.h"

-#include "../Common/CoderMixer2MT.h"

-#ifdef _ST_MODE

-#include "../Common/CoderMixer2ST.h"

-#endif

-

-#include "../../Common/CreateCoder.h"

 

 #include "7zIn.h"

 

 namespace NArchive {

 namespace N7z {

 

-struct CBindInfoEx: public NCoderMixer::CBindInfo

+struct CBindInfoEx: public NCoderMixer2::CBindInfo

 {

   CRecordVector<CMethodId> CoderMethodIDs;

+

   void Clear()

   {

     CBindInfo::Clear();

@@ -31,29 +23,40 @@
 

 class CDecoder

 {

-  bool _bindInfoExPrevIsDefined;

-  CBindInfoEx _bindInfoExPrev;

+  bool _bindInfoPrev_Defined;

+  CBindInfoEx _bindInfoPrev;

   

-  bool _multiThread;

-  #ifdef _ST_MODE

-  NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;

+  bool _useMixerMT;

+  

+  #ifdef USE_MIXER_ST

+    NCoderMixer2::CMixerST *_mixerST;

   #endif

-  NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;

-  NCoderMixer::CCoderMixer2 *_mixerCoderCommon;

   

-  CMyComPtr<ICompressCoder2> _mixerCoder;

-  CObjectVector<CMyComPtr<IUnknown> > _decoders;

-  // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;

+  #ifdef USE_MIXER_MT

+    NCoderMixer2::CMixerMT *_mixerMT;

+  #endif

+  

+  NCoderMixer2::CMixer *_mixer;

+  CMyComPtr<IUnknown> _mixerRef;

+

 public:

-  CDecoder(bool multiThread);

+

+  CDecoder(bool useMixerMT);

+  

   HRESULT Decode(

       DECL_EXTERNAL_CODECS_LOC_VARS

       IInStream *inStream,

       UInt64 startPos,

-      const CFolders &folders, int folderIndex,

-      ISequentialOutStream *outStream,

-      ICompressProgressInfo *compressProgress

+      const CFolders &folders, unsigned folderIndex,

+      const UInt64 *unpackSize // if (!unpackSize), then full folder is required

+                               // if (unpackSize), then only *unpackSize bytes from folder are required

+

+      , ISequentialOutStream *outStream

+      , ICompressProgressInfo *compressProgress

+      , ISequentialInStream **inStreamMainRes

+      

       _7Z_DECODER_CRYPRO_VARS_DECL

+      

       #if !defined(_7ZIP_ST) && !defined(_SFX)

       , bool mtMode, UInt32 numThreads

       #endif

diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 365489c..7636c60 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -12,43 +12,80 @@
 #include "7zEncode.h"

 #include "7zSpecStream.h"

 

-static const UInt64 k_Delta = 0x03;

-static const UInt64 k_BCJ = 0x03030103;

-static const UInt64 k_BCJ2 = 0x0303011B;

-

 namespace NArchive {

 namespace N7z {

 

-static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,

-    const CRecordVector<CMethodId> decompressionMethods,

-    CFolder &folder)

+void CEncoder::InitBindConv()

 {

-  // bindInfo.CoderMethodIDs.Clear();

-  // folder.OutStreams.Clear();

-  folder.BindPairs.SetSize(bindInfo.BindPairs.Size());

-  unsigned i;

-  for (i = 0; i < bindInfo.BindPairs.Size(); i++)

+  unsigned numIn = _bindInfo.Coders.Size();

+  

+  _SrcIn_to_DestOut.ClearAndSetSize(numIn);

+  _DestOut_to_SrcIn.ClearAndSetSize(numIn);

+

+  unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();

+  _SrcOut_to_DestIn.ClearAndSetSize(numOut);

+  // _DestIn_to_SrcOut.ClearAndSetSize(numOut);

+

+  UInt32 destIn = 0;

+  UInt32 destOut = 0;

+

+  for (unsigned i = _bindInfo.Coders.Size(); i != 0;)

   {

-    CBindPair &bp = folder.BindPairs[i];

-    const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];

-    bp.InIndex = mixerBp.InIndex;

-    bp.OutIndex = mixerBp.OutIndex;

+    i--;

+

+    const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];

+

+    numIn--;

+    numOut -= coder.NumStreams;

+    

+    _SrcIn_to_DestOut[numIn] = destOut;

+    _DestOut_to_SrcIn[destOut] = numIn;

+

+    destOut++;

+  

+    for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)

+    {

+      UInt32 index = numOut + j;

+      _SrcOut_to_DestIn[index] = destIn;

+      // _DestIn_to_SrcOut[destIn] = index;

+    }

   }

-  folder.Coders.SetSize(bindInfo.Coders.Size());

-  for (i = 0; i < bindInfo.Coders.Size(); i++)

+}

+

+void CEncoder::SetFolder(CFolder &folder)

+{

+  folder.Bonds.SetSize(_bindInfo.Bonds.Size());

+  

+  unsigned i;

+

+  for (i = 0; i < _bindInfo.Bonds.Size(); i++)

+  {

+    CBond &fb = folder.Bonds[i];

+    const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];

+    fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];

+    fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];

+  }

+  

+  folder.Coders.SetSize(_bindInfo.Coders.Size());

+  

+  for (i = 0; i < _bindInfo.Coders.Size(); i++)

   {

     CCoderInfo &coderInfo = folder.Coders[i];

-    const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];

-    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;

-    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;

-    coderInfo.MethodID = decompressionMethods[i];

-    // coderInfo.Props can be nonFree;

+    const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];

+    

+    coderInfo.NumStreams = coderStreamsInfo.NumStreams;

+    coderInfo.MethodID = _decompressionMethods[i];

+    // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.

   }

-  folder.PackStreams.SetSize(bindInfo.InStreams.Size());

-  for (i = 0; i < bindInfo.InStreams.Size(); i++)

-    folder.PackStreams[i] = bindInfo.InStreams[i];

+  

+  folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());

+  

+  for (i = 0; i < _bindInfo.PackStreams.Size(); i++)

+    folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];

 }

 

+

+

 static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)

 {

   CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

@@ -58,30 +95,75 @@
   return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;

 }

 

+

+

+void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)

+{

+  _progress = progress;

+  OutSize = 0;

+}

+

+STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)

+{

+  UInt64 outSize2;

+  {

+    #ifndef _7ZIP_ST

+    NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);

+    #endif

+    outSize2 = OutSize;

+  }

+  

+  if (_progress)

+    return _progress->SetRatioInfo(inSize, &outSize2);

+   

+  return S_OK;

+}

+

+

+

 HRESULT CEncoder::CreateMixerCoder(

     DECL_EXTERNAL_CODECS_LOC_VARS

     const UInt64 *inSizeForReduce)

 {

-  _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;

-  _mixerCoder = _mixerCoderSpec;

-  RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));

-  FOR_VECTOR (i, _options.Methods)

+  #ifdef USE_MIXER_MT

+  #ifdef USE_MIXER_ST

+  if (_options.MultiThreadMixer)

+  #endif

   {

-    const CMethodFull &methodFull = _options.Methods[i];

-    CCoderInfo &encodingInfo = _codersInfo.AddNew();

-    encodingInfo.MethodID = methodFull.Id;

-    CMyComPtr<ICompressCoder> encoder;

-    CMyComPtr<ICompressCoder2> encoder2;

-    

+    _mixerMT = new NCoderMixer2::CMixerMT(true);

+    _mixerRef = _mixerMT;

+    _mixer = _mixerMT;

+  }

+  #ifdef USE_MIXER_ST

+  else

+  #endif

+  #endif

+  {

+    #ifdef USE_MIXER_ST

+    _mixerST = new NCoderMixer2::CMixerST(true);

+    _mixerRef = _mixerST;

+    _mixer = _mixerST;

+    #endif

+  }

 

+  RINOK(_mixer->SetBindInfo(_bindInfo));

+

+  FOR_VECTOR (m, _options.Methods)

+  {

+    const CMethodFull &methodFull = _options.Methods[m];

+

+    CCreatedCoder cod;

+    

     RINOK(CreateCoder(

         EXTERNAL_CODECS_LOC_VARS

-        methodFull.Id, encoder, encoder2, true));

+        methodFull.Id, true, cod));

 

-    if (!encoder && !encoder2)

+    if (cod.NumStreams != methodFull.NumStreams)

+      return E_FAIL;

+    if (!cod.Coder && !cod.Coder2)

       return E_FAIL;

 

-    CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;

+    CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;

    

     #ifndef _7ZIP_ST

     {

@@ -105,21 +187,25 @@
     }

     */

 

+    // now there is no codec that uses another external codec

+    /*

     #ifdef EXTERNAL_CODECS

     CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

     encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

     if (setCompressCodecsInfo)

     {

+      // we must use g_ExternalCodecs also

       RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));

     }

     #endif

+    */

     

     CMyComPtr<ICryptoSetPassword> cryptoSetPassword;

     encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);

 

     if (cryptoSetPassword)

     {

-      const UInt32 sizeInBytes = _options.Password.Len() * 2;

+      const unsigned sizeInBytes = _options.Password.Len() * 2;

       CByteBuffer buffer(sizeInBytes);

       for (unsigned i = 0; i < _options.Password.Len(); i++)

       {

@@ -127,21 +213,79 @@
         ((Byte *)buffer)[i * 2] = (Byte)c;

         ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);

       }

-      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));

+      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));

     }

 

-    if (encoder)

-      _mixerCoderSpec->AddCoder(encoder);

-    else

-      _mixerCoderSpec->AddCoder2(encoder2);

+    _mixer->AddCoder(cod);

   }

   return S_OK;

 }

 

+

+

+class CSequentialOutTempBufferImp2:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CInOutTempBuffer *_buf;

+public:

+  CMtEncMultiProgress *_mtProgresSpec;

+  

+  CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}

+  void Init(CInOutTempBuffer *buffer) { _buf = buffer; }

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)

+{

+  if (!_buf->Write(data, size))

+  {

+    if (processed)

+      *processed = 0;

+    return E_FAIL;

+  }

+  if (processed)

+    *processed = size;

+  if (_mtProgresSpec)

+    _mtProgresSpec->AddOutSize(size);

+  return S_OK;

+}

+

+

+class CSequentialOutMtNotify:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+public:

+  CMyComPtr<ISequentialOutStream> _stream;

+  CMtEncMultiProgress *_mtProgresSpec;

+  

+  CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)

+{

+  UInt32 realProcessed = 0;

+  HRESULT res = _stream->Write(data, size, &realProcessed);

+  if (processed)

+    *processed = realProcessed;

+  if (_mtProgresSpec)

+    _mtProgresSpec->AddOutSize(size);

+  return res;

+}

+

+

+

 HRESULT CEncoder::Encode(

     DECL_EXTERNAL_CODECS_LOC_VARS

     ISequentialInStream *inStream,

-    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

+    // const UInt64 *inStreamSize,

+    const UInt64 *inSizeForReduce,

     CFolder &folderItem,

     CRecordVector<UInt64> &coderUnpackSizes,

     UInt64 &unpackSize,

@@ -151,27 +295,37 @@
 {

   RINOK(EncoderConstr());

 

-  if (!_mixerCoderSpec)

+  if (!_mixerRef)

   {

     RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));

   }

-  _mixerCoderSpec->ReInit();

-  // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);

+  

+  _mixer->ReInit();

+

+  CMtEncMultiProgress *mtProgressSpec = NULL;

+  CMyComPtr<ICompressProgressInfo> mtProgress;

+

+  CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;

+  CMyComPtr<ISequentialOutStream> mtOutStreamNotify;

 

   CObjectVector<CInOutTempBuffer> inOutTempBuffers;

-  CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;

+  CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;

   CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;

+  

   unsigned numMethods = _bindInfo.Coders.Size();

+  

   unsigned i;

-  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+

+  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)

   {

     CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();

     iotb.Create();

     iotb.InitWriting();

   }

-  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+  

+  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)

   {

-    CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;

+    CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;

     CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;

     tempBufferSpec->Init(&inOutTempBuffers[i - 1]);

     tempBuffers.Add(tempBuffer);

@@ -179,94 +333,111 @@
   }

 

   for (i = 0; i < numMethods; i++)

-    _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);

+    _mixer->SetCoderInfo(i, NULL, NULL);

 

-  if (_bindInfo.InStreams.IsEmpty())

-    return E_FAIL;

-  UInt32 mainCoderIndex, mainStreamIndex;

-  _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);

-  

+

+  /* inStreamSize can be used by BCJ2 to set optimal range of conversion.

+     But current BCJ2 encoder uses also another way to check exact size of current file.

+     So inStreamSize is not required. */

+

+  /*

   if (inStreamSize)

-  {

-    CRecordVector<const UInt64 *> sizePointers;

-    for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)

-      if (i == mainStreamIndex)

-        sizePointers.Add(inStreamSize);

-      else

-        sizePointers.Add(NULL);

-    _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);

-  }

+    _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);

+  */

 

   

-  // UInt64 outStreamStartPos;

-  // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));

-  

   CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;

   CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;

+

   CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;

   CMyComPtr<ISequentialOutStream> outStreamSizeCount;

 

   inStreamSizeCountSpec->Init(inStream);

 

-  CRecordVector<ISequentialInStream *> inStreamPointers;

+  ISequentialInStream *inStreamPointer = inStreamSizeCount;

   CRecordVector<ISequentialOutStream *> outStreamPointers;

-  inStreamPointers.Add(inStreamSizeCount);

   

-  if (_bindInfo.OutStreams.Size() != 0)

-  {

-    outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;

-    outStreamSizeCount = outStreamSizeCountSpec;

-    outStreamSizeCountSpec->SetStream(outStream);

-    outStreamSizeCountSpec->Init();

-    outStreamPointers.Add(outStreamSizeCount);

-  }

+  SetFolder(folderItem);

 

-  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

-    outStreamPointers.Add(tempBuffers[i - 1]);

-

-  for (i = 0; i < _codersInfo.Size(); i++)

+  for (i = 0; i < numMethods; i++)

   {

-    CCoderInfo &encodingInfo = _codersInfo[i];

-    

+    IUnknown *coder = _mixer->GetCoder(i).GetUnknown();

+

     CMyComPtr<ICryptoResetInitVector> resetInitVector;

-    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);

+    coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);

     if (resetInitVector)

     {

       resetInitVector->ResetInitVector();

     }

 

     CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

-    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

+    coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

+

+    CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;

+

     if (writeCoderProperties)

     {

       CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;

-      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

+      CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);

       outStreamSpec->Init();

-      writeCoderProperties->WriteCoderProperties(outStream);

-      outStreamSpec->CopyToBuffer(encodingInfo.Props);

+      writeCoderProperties->WriteCoderProperties(dynOutStream);

+      outStreamSpec->CopyToBuffer(props);

+    }

+    else

+      props.Free();

+  }

+

+  _mixer->SelectMainCoder(false);

+  UInt32 mainCoder = _mixer->MainCoderIndex;

+

+  bool useMtProgress = false;

+  if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))

+  {

+    #ifdef _7ZIP_ST

+    if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))

+    #endif

+      useMtProgress = true;

+  }

+

+  if (useMtProgress)

+  {

+    mtProgressSpec = new CMtEncMultiProgress;

+    mtProgress = mtProgressSpec;

+    mtProgressSpec->Init(compressProgress);

+    

+    mtOutStreamNotifySpec = new CSequentialOutMtNotify;

+    mtOutStreamNotify = mtOutStreamNotifySpec;

+    mtOutStreamNotifySpec->_stream = outStream;

+    mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;

+    

+    FOR_VECTOR(t, tempBufferSpecs)

+    {

+      tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;

     }

   }

-

-  UInt32 progressIndex = mainCoderIndex;

-

-  for (i = 0; i + 1 < _codersInfo.Size(); i++)

+  

+  

+  if (_bindInfo.PackStreams.Size() != 0)

   {

-    UInt64 m = _codersInfo[i].MethodID;

-    if (m == k_Delta || m == k_BCJ || m == k_BCJ2)

-      progressIndex = i + 1;

+    outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;

+    outStreamSizeCount = outStreamSizeCountSpec;

+    outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);

+    outStreamSizeCountSpec->Init();

+    outStreamPointers.Add(outStreamSizeCount);

   }

 

-  _mixerCoderSpec->SetProgressCoderIndex(progressIndex);

+  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)

+    outStreamPointers.Add(tempBuffers[i - 1]);

+

+  RINOK(_mixer->Code(

+      &inStreamPointer,

+      &outStreamPointers.Front(),

+      mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));

   

-  RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,

-    &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));

-  

-  ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);

-  

-  if (_bindInfo.OutStreams.Size() != 0)

+  if (_bindInfo.PackStreams.Size() != 0)

     packSizes.Add(outStreamSizeCountSpec->GetSize());

   

-  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)

   {

     CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];

     RINOK(inOutTempBuffer.WriteToStream(outStream));

@@ -274,37 +445,45 @@
   }

 

   unpackSize = 0;

-  for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)

+  

+  for (i = 0; i < _bindInfo.Coders.Size(); i++)

   {

-    int binder = _bindInfo.FindBinderForInStream(

-        _bindReverseConverter->DestOutToSrcInMap[i]);

+    int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);

     UInt64 streamSize;

-    if (binder < 0)

+    if (bond < 0)

     {

       streamSize = inStreamSizeCountSpec->GetSize();

       unpackSize = streamSize;

     }

     else

-      streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);

+      streamSize = _mixer->GetBondStreamSize(bond);

     coderUnpackSizes.Add(streamSize);

   }

-  for (i = 0; i < numMethods; i++)

-    folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;

+  

   return S_OK;

 }

 

 

 CEncoder::CEncoder(const CCompressionMethodMode &options):

-  _bindReverseConverter(0),

-  _constructed(false)

+    _constructed(false)

 {

   if (options.IsEmpty())

     throw 1;

 

   _options = options;

-  _mixerCoderSpec = NULL;

+

+  #ifdef USE_MIXER_ST

+    _mixerST = NULL;

+  #endif

+  

+  #ifdef USE_MIXER_MT

+    _mixerMT = NULL;

+  #endif

+

+  _mixer = NULL;

 }

 

+

 HRESULT CEncoder::EncoderConstr()

 {

   if (_constructed)

@@ -314,112 +493,125 @@
     // it has only password method;

     if (!_options.PasswordIsDefined)

       throw 1;

-    if (!_options.Binds.IsEmpty())

+    if (!_options.Bonds.IsEmpty())

       throw 1;

-    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+

     CMethodFull method;

-    

-    method.NumInStreams = 1;

-    method.NumOutStreams = 1;

-    coderStreamsInfo.NumInStreams = 1;

-    coderStreamsInfo.NumOutStreams = 1;

     method.Id = k_AES;

-    

+    method.NumStreams = 1;

     _options.Methods.Add(method);

+

+    NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;

+    coderStreamsInfo.NumStreams = 1;

     _bindInfo.Coders.Add(coderStreamsInfo);

   

-    _bindInfo.InStreams.Add(0);

-    _bindInfo.OutStreams.Add(0);

+    _bindInfo.PackStreams.Add(0);

+    _bindInfo.UnpackCoder = 0;

   }

   else

   {

 

-  UInt32 numInStreams = 0, numOutStreams = 0;

+  UInt32 numOutStreams = 0;

   unsigned i;

+  

   for (i = 0; i < _options.Methods.Size(); i++)

   {

     const CMethodFull &methodFull = _options.Methods[i];

-    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

-    coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;

-    coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;

-    if (_options.Binds.IsEmpty())

+    NCoderMixer2::CCoderStreamsInfo cod;

+    

+    cod.NumStreams = methodFull.NumStreams;

+

+    if (_options.Bonds.IsEmpty())

     {

-      if (i < _options.Methods.Size() - 1)

+      // if there are no bonds in options, we create bonds via first streams of coders

+      if (i != _options.Methods.Size() - 1)

       {

-        NCoderMixer::CBindPair bindPair;

-        bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;

-        bindPair.OutIndex = numOutStreams;

-        _bindInfo.BindPairs.Add(bindPair);

+        NCoderMixer2::CBond bond;

+        bond.PackIndex = numOutStreams;

+        bond.UnpackIndex = i + 1; // it's next coder

+        _bindInfo.Bonds.Add(bond);

       }

-      else if (coderStreamsInfo.NumOutStreams != 0)

-        _bindInfo.OutStreams.Insert(0, numOutStreams);

-      for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)

-        _bindInfo.OutStreams.Add(numOutStreams + j);

+      else if (cod.NumStreams != 0)

+        _bindInfo.PackStreams.Insert(0, numOutStreams);

+      

+      for (UInt32 j = 1; j < cod.NumStreams; j++)

+        _bindInfo.PackStreams.Add(numOutStreams + j);

     }

     

-    numInStreams += coderStreamsInfo.NumInStreams;

-    numOutStreams += coderStreamsInfo.NumOutStreams;

+    numOutStreams += cod.NumStreams;

 

-    _bindInfo.Coders.Add(coderStreamsInfo);

+    _bindInfo.Coders.Add(cod);

   }

 

-  if (!_options.Binds.IsEmpty())

+  if (!_options.Bonds.IsEmpty())

   {

-    for (i = 0; i < _options.Binds.Size(); i++)

+    for (i = 0; i < _options.Bonds.Size(); i++)

     {

-      NCoderMixer::CBindPair bindPair;

-      const CBind &bind = _options.Binds[i];

-      bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;

-      bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;

-      _bindInfo.BindPairs.Add(bindPair);

+      NCoderMixer2::CBond mixerBond;

+      const CBond2 &bond = _options.Bonds[i];

+      if (bond.InCoder >= _bindInfo.Coders.Size()

+          || bond.OutCoder >= _bindInfo.Coders.Size()

+          || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)

+        return E_INVALIDARG;

+      mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;

+      mixerBond.UnpackIndex = bond.InCoder;

+      _bindInfo.Bonds.Add(mixerBond);

     }

-    for (i = 0; i < (int)numOutStreams; i++)

-      if (_bindInfo.FindBinderForOutStream(i) == -1)

-        _bindInfo.OutStreams.Add(i);

+

+    for (i = 0; i < numOutStreams; i++)

+      if (_bindInfo.FindBond_for_PackStream(i) == -1)

+        _bindInfo.PackStreams.Add(i);

   }

 

-  for (i = 0; i < (int)numInStreams; i++)

-    if (_bindInfo.FindBinderForInStream(i) == -1)

-      _bindInfo.InStreams.Add(i);

+  if (!_bindInfo.SetUnpackCoder())

+    return E_INVALIDARG;

 

-  if (_bindInfo.InStreams.IsEmpty())

-    throw 1; // this is error

+  if (!_bindInfo.CalcMapsAndCheck())

+    return E_INVALIDARG;

 

-  // Make main stream first in list

-  int inIndex = _bindInfo.InStreams[0];

-  for (;;)

+  if (_bindInfo.PackStreams.Size() != 1)

   {

-    UInt32 coderIndex, coderStreamIndex;

-    _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);

-    UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);

-    int binder = _bindInfo.FindBinderForOutStream(outIndex);

-    if (binder >= 0)

+    /* main_PackStream is pack stream of main path of coders tree.

+       We find main_PackStream, and place to start of list of out streams.

+       It allows to use more optimal memory usage for temp buffers,

+       if main_PackStream is largest stream. */

+

+    UInt32 ci = _bindInfo.UnpackCoder;

+    

+    for (;;)

     {

-      inIndex = _bindInfo.BindPairs[binder].InIndex;

-      continue;

-    }

-    for (i = 0; i < _bindInfo.OutStreams.Size(); i++)

-      if (_bindInfo.OutStreams[i] == outIndex)

-      {

-        _bindInfo.OutStreams.Delete(i);

-        _bindInfo.OutStreams.Insert(0, outIndex);

+      if (_bindInfo.Coders[ci].NumStreams == 0)

         break;

+      

+      UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];

+      int bond = _bindInfo.FindBond_for_PackStream(outIndex);

+      if (bond >= 0)

+      {

+        ci = _bindInfo.Bonds[bond].UnpackIndex;

+        continue;

       }

-    break;

+      

+      int si = _bindInfo.FindStream_in_PackStreams(outIndex);

+      if (si >= 0)

+        _bindInfo.PackStreams.MoveToFront(si);

+      break;

+    }

   }

 

   if (_options.PasswordIsDefined)

   {

-    unsigned numCryptoStreams = _bindInfo.OutStreams.Size();

+    unsigned numCryptoStreams = _bindInfo.PackStreams.Size();

 

+    unsigned numInStreams = _bindInfo.Coders.Size();

+    

     for (i = 0; i < numCryptoStreams; i++)

     {

-      NCoderMixer::CBindPair bindPair;

-      bindPair.InIndex = numInStreams + i;

-      bindPair.OutIndex = _bindInfo.OutStreams[i];

-      _bindInfo.BindPairs.Add(bindPair);

+      NCoderMixer2::CBond bond;

+      bond.UnpackIndex = numInStreams + i;

+      bond.PackIndex = _bindInfo.PackStreams[i];

+      _bindInfo.Bonds.Add(bond);

     }

-    _bindInfo.OutStreams.Clear();

+    _bindInfo.PackStreams.Clear();

 

     /*

     if (numCryptoStreams == 0)

@@ -428,37 +620,37 @@
 

     for (i = 0; i < numCryptoStreams; i++)

     {

-      NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

       CMethodFull method;

-      method.NumInStreams = 1;

-      method.NumOutStreams = 1;

-      coderStreamsInfo.NumInStreams = method.NumOutStreams;

-      coderStreamsInfo.NumOutStreams = method.NumInStreams;

+      method.NumStreams = 1;

       method.Id = k_AES;

-

       _options.Methods.Add(method);

-      _bindInfo.Coders.Add(coderStreamsInfo);

-      _bindInfo.OutStreams.Add(numOutStreams + i);

+

+      NCoderMixer2::CCoderStreamsInfo cod;

+      cod.NumStreams = 1;

+      _bindInfo.Coders.Add(cod);

+

+      _bindInfo.PackStreams.Add(numOutStreams++);

     }

   }

 

   }

 

-  for (int i = _options.Methods.Size() - 1; i >= 0; i--)

-  {

-    const CMethodFull &methodFull = _options.Methods[i];

-    _decompressionMethods.Add(methodFull.Id);

-  }

+  for (unsigned i = _options.Methods.Size(); i != 0;)

+    _decompressionMethods.Add(_options.Methods[--i].Id);

 

-  _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);

-  _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);

+  if (_bindInfo.Coders.Size() > 16)

+    return E_INVALIDARG;

+  if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)

+    return E_INVALIDARG;

+

+  if (!_bindInfo.CalcMapsAndCheck())

+    return E_INVALIDARG;

+

+  InitBindConv();

   _constructed = true;

   return S_OK;

 }

 

-CEncoder::~CEncoder()

-{

-  delete _bindReverseConverter;

-}

+CEncoder::~CEncoder() {}

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
index 0f28cfb..434cbec 100644
--- a/CPP/7zip/Archive/7z/7zEncode.h
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -3,47 +3,82 @@
 #ifndef __7Z_ENCODE_H

 #define __7Z_ENCODE_H

 

-// #include "../../Common/StreamObjects.h"

-

 #include "7zCompressionMode.h"

 

 #include "../Common/CoderMixer2.h"

-#include "../Common/CoderMixer2MT.h"

-#ifdef _ST_MODE

-#include "../Common/CoderMixer2ST.h"

-#endif

-#include "7zItem.h"

 

-#include "../../Common/CreateCoder.h"

+#include "7zItem.h"

 

 namespace NArchive {

 namespace N7z {

 

+class CMtEncMultiProgress:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+  CMyComPtr<ICompressProgressInfo> _progress;

+  #ifndef _7ZIP_ST

+  NWindows::NSynchronization::CCriticalSection CriticalSection;

+  #endif

+

+public:

+  UInt64 OutSize;

+

+  CMtEncMultiProgress(): OutSize(0) {}

+

+  void Init(ICompressProgressInfo *progress);

+

+  void AddOutSize(UInt64 addOutSize)

+  {

+    #ifndef _7ZIP_ST

+    NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);

+    #endif

+    OutSize += addOutSize;

+  }

+

+  MY_UNKNOWN_IMP1(ICompressProgressInfo)

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

 class CEncoder

 {

-  NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;

-  CMyComPtr<ICompressCoder2> _mixerCoder;

-

-  CObjectVector<CCoderInfo> _codersInfo;

+  #ifdef USE_MIXER_ST

+    NCoderMixer2::CMixerST *_mixerST;

+  #endif

+  #ifdef USE_MIXER_MT

+    NCoderMixer2::CMixerMT *_mixerMT;

+  #endif

+  

+  NCoderMixer2::CMixer *_mixer;

+  CMyComPtr<IUnknown> _mixerRef;

 

   CCompressionMethodMode _options;

-  NCoderMixer::CBindInfo _bindInfo;

-  NCoderMixer::CBindInfo _decompressBindInfo;

-  NCoderMixer::CBindReverseConverter *_bindReverseConverter;

+  NCoderMixer2::CBindInfo _bindInfo;

   CRecordVector<CMethodId> _decompressionMethods;

 

+  CRecordVector<UInt32> _SrcIn_to_DestOut;

+  CRecordVector<UInt32> _SrcOut_to_DestIn;

+  // CRecordVector<UInt32> _DestIn_to_SrcOut;

+  CRecordVector<UInt32> _DestOut_to_SrcIn;

+

+  void InitBindConv();

+  void SetFolder(CFolder &folder);

+

   HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS

       const UInt64 *inSizeForReduce);

 

   bool _constructed;

 public:

+

   CEncoder(const CCompressionMethodMode &options);

   ~CEncoder();

   HRESULT EncoderConstr();

   HRESULT Encode(

       DECL_EXTERNAL_CODECS_LOC_VARS

       ISequentialInStream *inStream,

-      const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

+      // const UInt64 *inStreamSize,

+      const UInt64 *inSizeForReduce,

       CFolder &folderItem,

       CRecordVector<UInt64> &coderUnpackSizes,

       UInt64 &unpackSize,

diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 9310762..a675797 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -2,205 +2,337 @@
 

 #include "StdAfx.h"

 

+#include "../../../../C/7zCrc.h"

+

 #include "../../../Common/ComTry.h"

 

 #include "../../Common/ProgressUtils.h"

 

 #include "7zDecode.h"

-// #include "7z1Decode.h"

-#include "7zFolderOutStream.h"

 #include "7zHandler.h"

 

+// EXTERN_g_ExternalCodecs

+

 namespace NArchive {

 namespace N7z {

 

-struct CExtractFolderInfo

+class CFolderOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

 {

-  #ifdef _7Z_VOL

-  int VolumeIndex;

-  #endif

-  CNum FileIndex;

-  CNum FolderIndex;

-  CBoolVector ExtractStatuses;

-  UInt64 UnpackSize;

-  CExtractFolderInfo(

-    #ifdef _7Z_VOL

-    int volumeIndex,

-    #endif

-    CNum fileIndex, CNum folderIndex):

-    #ifdef _7Z_VOL

-    VolumeIndex(volumeIndex),

-    #endif

-    FileIndex(fileIndex),

-    FolderIndex(folderIndex),

-    UnpackSize(0)

-  {

-    if (fileIndex != kNumNoIndex)

-    {

-      ExtractStatuses.ClearAndSetSize(1);

-      ExtractStatuses[0] = true;

-    }

-  };

+  CMyComPtr<ISequentialOutStream> _stream;

+public:

+  bool TestMode;

+  bool CheckCrc;

+private:

+  bool _fileIsOpen;

+  bool _calcCrc;

+  UInt32 _crc;

+  UInt64 _rem;

+

+  const UInt32 *_indexes;

+  unsigned _numFiles;

+  unsigned _fileIndex;

+

+  HRESULT OpenFile(bool isCorrupted = false);

+  HRESULT CloseFile_and_SetResult(Int32 res);

+  HRESULT CloseFile();

+  HRESULT ProcessEmptyFiles();

+

+public:

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

+

+  const CDbEx *_db;

+  CMyComPtr<IArchiveExtractCallback> ExtractCallback;

+

+  bool ExtraWriteWasCut;

+

+  CFolderOutStream():

+      TestMode(false),

+      CheckCrc(true)

+      {}

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+

+  HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);

+  HRESULT FlushCorrupted(Int32 callbackOperationResult);

+

+  bool WasWritingFinished() const { return _numFiles == 0; }

 };

 

+

+HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)

+{

+  _fileIndex = startIndex;

+  _indexes = indexes;

+  _numFiles = numFiles;

+  

+  _fileIsOpen = false;

+  ExtraWriteWasCut = false;

+  

+  return ProcessEmptyFiles();

+}

+

+HRESULT CFolderOutStream::OpenFile(bool isCorrupted)

+{

+  const CFileItem &fi = _db->Files[_fileIndex];

+  UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);

+  Int32 askMode = (_fileIndex == nextFileIndex) ?

+        (TestMode ?

+        NExtract::NAskMode::kTest :

+        NExtract::NAskMode::kExtract) :

+      NExtract::NAskMode::kSkip;

+

+  if (isCorrupted

+      && askMode == NExtract::NAskMode::kExtract

+      && !_db->IsItemAnti(_fileIndex)

+      && !fi.IsDir)

+    askMode = NExtract::NAskMode::kTest;

+  

+  CMyComPtr<ISequentialOutStream> realOutStream;

+  RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));

+  

+  _stream = realOutStream;

+  _crc = CRC_INIT_VAL;

+  _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);

+

+  _fileIsOpen = true;

+  _rem = fi.Size;

+  

+  if (askMode == NExtract::NAskMode::kExtract

+      && !realOutStream

+      && !_db->IsItemAnti(_fileIndex)

+      && !fi.IsDir)

+    askMode = NExtract::NAskMode::kSkip;

+  return ExtractCallback->PrepareOperation(askMode);

+}

+

+HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)

+{

+  _stream.Release();

+  _fileIsOpen = false;

+  

+  if (!_indexes)

+    _numFiles--;

+  else if (*_indexes == _fileIndex)

+  {

+    _indexes++;

+    _numFiles--;

+  }

+

+  _fileIndex++;

+  return ExtractCallback->SetOperationResult(res);

+}

+

+HRESULT CFolderOutStream::CloseFile()

+{

+  const CFileItem &fi = _db->Files[_fileIndex];

+  return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?

+      NExtract::NOperationResult::kOK :

+      NExtract::NOperationResult::kCRCError);

+}

+

+HRESULT CFolderOutStream::ProcessEmptyFiles()

+{

+  while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)

+  {

+    RINOK(OpenFile());

+    RINOK(CloseFile());

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  

+  while (size != 0)

+  {

+    if (_fileIsOpen)

+    {

+      UInt32 cur = (size < _rem ? size : (UInt32)_rem);

+      HRESULT result = S_OK;

+      if (_stream)

+        result = _stream->Write(data, cur, &cur);

+      if (_calcCrc)

+        _crc = CrcUpdate(_crc, data, cur);

+      if (processedSize)

+        *processedSize += cur;

+      data = (const Byte *)data + cur;

+      size -= cur;

+      _rem -= cur;

+      if (_rem == 0)

+      {

+        RINOK(CloseFile());

+        RINOK(ProcessEmptyFiles());

+      }

+      RINOK(result);

+      if (cur == 0)

+        break;

+      continue;

+    }

+  

+    RINOK(ProcessEmptyFiles());

+    if (_numFiles == 0)

+    {

+      // we support partial extracting

+      /*

+      if (processedSize)

+        *processedSize += size;

+      break;

+      */

+      ExtraWriteWasCut = true;

+      // return S_FALSE;

+      return k_My_HRESULT_WritingWasCut;

+    }

+    RINOK(OpenFile());

+  }

+  

+  return S_OK;

+}

+

+HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)

+{

+  while (_numFiles != 0)

+  {

+    if (_fileIsOpen)

+    {

+      RINOK(CloseFile_and_SetResult(callbackOperationResult));

+    }

+    else

+    {

+      RINOK(OpenFile(true));

+    }

+  }

+  return S_OK;

+}

+

 STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

     Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)

 {

   COM_TRY_BEGIN

-  bool testMode = (testModeSpec != 0);

+  

   CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;

+  

   UInt64 importantTotalUnpacked = 0;

 

+  // numItems = (UInt32)(Int32)-1;

+

   bool allFilesMode = (numItems == (UInt32)(Int32)-1);

   if (allFilesMode)

-    numItems =

-    #ifdef _7Z_VOL

-    _refs.Size();

-    #else

-    _db.Files.Size();

-    #endif

+    numItems = _db.Files.Size();

 

-  if(numItems == 0)

+  if (numItems == 0)

     return S_OK;

 

-  /*

-  if(_volumes.Size() != 1)

-    return E_FAIL;

-  const CVolume &volume = _volumes.Front();

-  const CDbEx &_db = volume.Database;

-  IInStream *_inStream = volume.Stream;

-  */

-  

-  CObjectVector<CExtractFolderInfo> extractFolderInfoVector;

-  for (UInt32 ii = 0; ii < numItems; ii++)

   {

-    // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];

-    UInt32 ref2Index = allFilesMode ? ii : indices[ii];

-    // const CRef2 &ref2 = _refs[ref2Index];

-

-    // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)

+    CNum prevFolder = kNumNoIndex;

+    UInt32 nextFile = 0;

+    

+    UInt32 i;

+    

+    for (i = 0; i < numItems; i++)

     {

-      #ifdef _7Z_VOL

-      // const CRef &ref = ref2.Refs[ri];

-      const CRef &ref = _refs[ref2Index];

-

-      int volumeIndex = ref.VolumeIndex;

-      const CVolume &volume = _volumes[volumeIndex];

-      const CDbEx &db = volume.Database;

-      UInt32 fileIndex = ref.ItemIndex;

-      #else

-      const CDbEx &db = _db;

-      UInt32 fileIndex = ref2Index;

-      #endif

-

-      CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];

+      UInt32 fileIndex = allFilesMode ? i : indices[i];

+      CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];

       if (folderIndex == kNumNoIndex)

-      {

-        extractFolderInfoVector.Add(CExtractFolderInfo(

-            #ifdef _7Z_VOL

-            volumeIndex,

-            #endif

-            fileIndex, kNumNoIndex));

         continue;

-      }

-      if (extractFolderInfoVector.IsEmpty() ||

-        folderIndex != extractFolderInfoVector.Back().FolderIndex

-        #ifdef _7Z_VOL

-        || volumeIndex != extractFolderInfoVector.Back().VolumeIndex

-        #endif

-        )

-      {

-        extractFolderInfoVector.Add(CExtractFolderInfo(

-            #ifdef _7Z_VOL

-            volumeIndex,

-            #endif

-            kNumNoIndex, folderIndex));

-        UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);

-        importantTotalUnpacked += unpackSize;

-        extractFolderInfoVector.Back().UnpackSize = unpackSize;

-      }

-      

-      CExtractFolderInfo &efi = extractFolderInfoVector.Back();

-      

-      // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];

-      CNum startIndex = db.FolderStartFileIndex[folderIndex];

-      for (CNum index = efi.ExtractStatuses.Size();

-          index <= fileIndex - startIndex; index++)

-      {

-        // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;

-        // Count partial_folder_size

-        // efi.UnpackSize += unpackSize;

-        // importantTotalUnpacked += unpackSize;

-        efi.ExtractStatuses.Add(index == fileIndex - startIndex);

-      }

+      if (folderIndex != prevFolder || fileIndex < nextFile)

+        nextFile = _db.FolderStartFileIndex[folderIndex];

+      for (CNum index = nextFile; index <= fileIndex; index++)

+        importantTotalUnpacked += _db.Files[index].Size;

+      nextFile = fileIndex + 1;

+      prevFolder = folderIndex;

     }

   }

 

   RINOK(extractCallback->SetTotal(importantTotalUnpacked));

 

-  CDecoder decoder(

-    #ifdef _ST_MODE

-    false

-    #else

-    true

-    #endif

-    );

-  // CDecoder1 decoder;

-

-  UInt64 totalPacked = 0;

-  UInt64 totalUnpacked = 0;

-  UInt64 curPacked, curUnpacked;

-

   CLocalProgress *lps = new CLocalProgress;

   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(extractCallback, false);

 

-  for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)

+  CDecoder decoder(

+    #if !defined(USE_MIXER_MT)

+      false

+    #elif !defined(USE_MIXER_ST)

+      true

+    #elif !defined(__7Z_SET_PROPERTIES)

+      #ifdef _7ZIP_ST

+        false

+      #else

+        true

+      #endif

+    #else

+      _useMultiThreadMixer

+    #endif

+    );

+

+  UInt64 curPacked, curUnpacked;

+

+  CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;

+  extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);

+

+  CFolderOutStream *folderOutStream = new CFolderOutStream;

+  CMyComPtr<ISequentialOutStream> outStream(folderOutStream);

+

+  folderOutStream->_db = &_db;

+  folderOutStream->ExtractCallback = extractCallback;

+  folderOutStream->TestMode = (testModeSpec != 0);

+  folderOutStream->CheckCrc = (_crcSize != 0);

+

+  for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)

   {

-    lps->OutSize = totalUnpacked;

-    lps->InSize = totalPacked;

     RINOK(lps->SetCur());

 

-    if (i >= extractFolderInfoVector.Size())

+    if (i >= numItems)

       break;

-    

-    const CExtractFolderInfo &efi = extractFolderInfoVector[i];

-    curUnpacked = efi.UnpackSize;

+

+    curUnpacked = 0;

     curPacked = 0;

 

-    CFolderOutStream *folderOutStream = new CFolderOutStream;

-    CMyComPtr<ISequentialOutStream> outStream(folderOutStream);

+    UInt32 fileIndex = allFilesMode ? i : indices[i];

+    CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];

 

-    #ifdef _7Z_VOL

-    const CVolume &volume = _volumes[efi.VolumeIndex];

-    const CDbEx &db = volume.Database;

-    #else

-    const CDbEx &db = _db;

-    #endif

+    UInt32 numSolidFiles = 1;

 

-    CNum startIndex;

-    if (efi.FileIndex != kNumNoIndex)

-      startIndex = efi.FileIndex;

-    else

-      startIndex = db.FolderStartFileIndex[efi.FolderIndex];

+    if (folderIndex != kNumNoIndex)

+    {

+      curPacked = _db.GetFolderFullPackSize(folderIndex);

+      UInt32 nextFile = fileIndex + 1;

+      fileIndex = _db.FolderStartFileIndex[folderIndex];

+      UInt32 k;

 

-    HRESULT result = folderOutStream->Init(&db,

-        #ifdef _7Z_VOL

-        volume.StartRef2Index,

-        #else

-        0,

-        #endif

-        startIndex,

-        &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);

+      for (k = i + 1; k < numItems; k++)

+      {

+        UInt32 fileIndex2 = allFilesMode ? k : indices[k];

+        if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex

+            || fileIndex2 < nextFile)

+          break;

+        nextFile = fileIndex2 + 1;

+      }

+      

+      numSolidFiles = k - i;

+      

+      for (k = fileIndex; k < nextFile; k++)

+        curUnpacked += _db.Files[k].Size;

+    }

 

-    RINOK(result);

+    {

+      HRESULT result = folderOutStream->Init(fileIndex,

+          allFilesMode ? NULL : indices + i,

+          numSolidFiles);

 

-    if (efi.FileIndex != kNumNoIndex)

+      i += numSolidFiles;

+

+      RINOK(result);

+    }

+

+    // to test solid block with zero unpacked size we disable that code

+    if (folderOutStream->WasWritingFinished())

       continue;

 

-    CNum folderIndex = efi.FolderIndex;

-    curPacked = _db.GetFolderFullPackSize(folderIndex);

-

     #ifndef _NO_CRYPTO

     CMyComPtr<ICryptoGetTextPassword> getTextPassword;

     if (extractCallback)

@@ -212,50 +344,64 @@
       #ifndef _NO_CRYPTO

         bool isEncrypted = false;

         bool passwordIsDefined = false;

+        UString password;

       #endif

 

+

       HRESULT result = decoder.Decode(

           EXTERNAL_CODECS_VARS

-          #ifdef _7Z_VOL

-            volume.Stream,

-          #else

-            _inStream,

-          #endif

-          db.ArcInfo.DataStartPosition,

-          db, folderIndex,

+          _inStream,

+          _db.ArcInfo.DataStartPosition,

+          _db, folderIndex,

+          &curUnpacked,

+

           outStream,

-          progress

+          progress,

+          NULL // *inStreamMainRes

+          

           _7Z_DECODER_CRYPRO_VARS

           #if !defined(_7ZIP_ST) && !defined(_SFX)

             , true, _numThreads

           #endif

           );

 

-      if (result == S_FALSE)

+      if (result == S_FALSE || result == E_NOTIMPL)

       {

-        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

+        bool wasFinished = folderOutStream->WasWritingFinished();

+      

+        int resOp = (result == S_FALSE ?

+            NExtract::NOperationResult::kDataError :

+            NExtract::NOperationResult::kUnsupportedMethod);

+

+        RINOK(folderOutStream->FlushCorrupted(resOp));

+

+        if (wasFinished)

+        {

+          // we don't show error, if it's after required files

+          if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)

+          {

+            RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));

+          }

+        }

         continue;

       }

-      if (result == E_NOTIMPL)

-      {

-        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));

-        continue;

-      }

+      

       if (result != S_OK)

         return result;

-      if (folderOutStream->WasWritingFinished() != S_OK)

-      {

-        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

-        continue;

-      }

+

+      RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

+      continue;

     }

     catch(...)

     {

       RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

-      continue;

+      // continue;

+      return E_FAIL;

     }

   }

+

   return S_OK;

+

   COM_TRY_END

 }

 

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 7971191..51a6f68 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -7,96 +7,103 @@
 namespace NArchive {

 namespace N7z {

 

-CFolderInStream::CFolderInStream()

-{

-  _inStreamWithHashSpec = new CSequentialInStreamWithCRC;

-  _inStreamWithHash = _inStreamWithHashSpec;

-}

-

 void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,

-    const UInt32 *fileIndices, UInt32 numFiles)

+    const UInt32 *indexes, unsigned numFiles)

 {

   _updateCallback = updateCallback;

+  _indexes = indexes;

   _numFiles = numFiles;

-  _fileIndex = 0;

-  _fileIndices = fileIndices;

-  Processed.Clear();

-  CRCs.Clear();

-  Sizes.Clear();

-  _fileIsOpen = false;

-  _currentSizeIsDefined = false;

+  _index = 0;

+  

+  Processed.ClearAndReserve(numFiles);

+  CRCs.ClearAndReserve(numFiles);

+  Sizes.ClearAndReserve(numFiles);

+  

+  _pos = 0;

+  _crc = CRC_INIT_VAL;

+  _size_Defined = false;

+  _size = 0;

+

+  _stream.Release();

 }

 

 HRESULT CFolderInStream::OpenStream()

 {

-  _filePos = 0;

-  while (_fileIndex < _numFiles)

+  _pos = 0;

+  _crc = CRC_INIT_VAL;

+  _size_Defined = false;

+  _size = 0;

+

+  while (_index < _numFiles)

   {

     CMyComPtr<ISequentialInStream> stream;

-    HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);

-    if (result != S_OK && result != S_FALSE)

-      return result;

-    _fileIndex++;

-    _inStreamWithHashSpec->SetStream(stream);

-    _inStreamWithHashSpec->Init();

+    HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);

+    if (result != S_OK)

+    {

+      if (result != S_FALSE)

+        return result;

+    }

+

+    _stream = stream;

+    

     if (stream)

     {

-      _fileIsOpen = true;

       CMyComPtr<IStreamGetSize> streamGetSize;

       stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);

       if (streamGetSize)

       {

-        RINOK(streamGetSize->GetSize(&_currentSize));

-        _currentSizeIsDefined = true;

+        if (streamGetSize->GetSize(&_size) == S_OK)

+          _size_Defined = true;

       }

       return S_OK;

     }

+    

+    _index++;

     RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));

-    Sizes.Add(0);

-    Processed.Add(result == S_OK);

-    AddDigest();

+    AddFileInfo(result == S_OK);

   }

   return S_OK;

 }

 

-void CFolderInStream::AddDigest()

+void CFolderInStream::AddFileInfo(bool isProcessed)

 {

-  CRCs.Add(_inStreamWithHashSpec->GetCRC());

-}

-

-HRESULT CFolderInStream::CloseStream()

-{

-  RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));

-  _inStreamWithHashSpec->ReleaseStream();

-  _fileIsOpen = false;

-  _currentSizeIsDefined = false;

-  Processed.Add(true);

-  Sizes.Add(_filePos);

-  AddDigest();

-  return S_OK;

+  Processed.Add(isProcessed);

+  Sizes.Add(_pos);

+  CRCs.Add(CRC_GET_DIGEST(_crc));

 }

 

 STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != 0)

+  if (processedSize)

     *processedSize = 0;

-  while (size > 0)

+  while (size != 0)

   {

-    if (_fileIsOpen)

+    if (_stream)

     {

       UInt32 processed2;

-      RINOK(_inStreamWithHash->Read(data, size, &processed2));

-      if (processed2 == 0)

+      RINOK(_stream->Read(data, size, &processed2));

+      if (processed2 != 0)

       {

-        RINOK(CloseStream());

-        continue;

+        _crc = CrcUpdate(_crc, data, processed2);

+        _pos += processed2;

+        if (processedSize)

+          *processedSize = processed2;

+        return S_OK;

       }

-      if (processedSize != 0)

-        *processedSize = processed2;

-      _filePos += processed2;

-      break;

+      

+      _stream.Release();

+      _index++;

+      AddFileInfo(true);

+

+      _pos = 0;

+      _crc = CRC_INIT_VAL;

+      _size_Defined = false;

+      _size = 0;

+

+      RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));

     }

-    if (_fileIndex >= _numFiles)

+    

+    if (_index >= _numFiles)

       break;

     RINOK(OpenStream());

   }

@@ -106,17 +113,23 @@
 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)

 {

   *value = 0;

-  unsigned index2 = (unsigned)subStream;

   if (subStream > Sizes.Size())

-    return E_FAIL;

-  if (index2 < Sizes.Size())

+    return S_FALSE; // E_FAIL;

+  

+  unsigned index = (unsigned)subStream;

+  if (index < Sizes.Size())

   {

-    *value = Sizes[index2];

+    *value = Sizes[index];

     return S_OK;

   }

-  if (!_currentSizeIsDefined)

+  

+  if (!_size_Defined)

+  {

+    *value = _pos;

     return S_FALSE;

-  *value = _currentSize;

+  }

+  

+  *value = (_pos > _size ? _pos : _size);

   return S_OK;

 }

 

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
index e516dff..f2b1c59 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -3,11 +3,13 @@
 #ifndef __7Z_FOLDER_IN_STREAM_H

 #define __7Z_FOLDER_IN_STREAM_H

 

+#include "../../../../C/7zCrc.h"

+

+#include "../../../Common/MyCom.h"

+#include "../../../Common/MyVector.h"

+

 #include "../../ICoder.h"

 #include "../IArchive.h"

-#include "../Common/InStreamWithCRC.h"

-

-#include "7zItem.h"

 

 namespace NArchive {

 namespace N7z {

@@ -17,33 +19,34 @@
   public ICompressGetSubStreamSize,

   public CMyUnknownImp

 {

-  CSequentialInStreamWithCRC *_inStreamWithHashSpec;

-  CMyComPtr<ISequentialInStream> _inStreamWithHash;

+  CMyComPtr<ISequentialInStream> _stream;

+  UInt64 _pos;

+  UInt32 _crc;

+  bool _size_Defined;

+  UInt64 _size;

+

+  const UInt32 *_indexes;

+  unsigned _numFiles;

+  unsigned _index;

+

   CMyComPtr<IArchiveUpdateCallback> _updateCallback;

 

-  bool _currentSizeIsDefined;

-  bool _fileIsOpen;

-  UInt64 _currentSize;

-  UInt64 _filePos;

-  const UInt32 *_fileIndices;

-  UInt32 _numFiles;

-  UInt32 _fileIndex;

-

   HRESULT OpenStream();

-  HRESULT CloseStream();

-  void AddDigest();

+  void AddFileInfo(bool isProcessed);

 

 public:

   CRecordVector<bool> Processed;

   CRecordVector<UInt32> CRCs;

   CRecordVector<UInt64> Sizes;

 

-  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

+  MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

 

-  CFolderInStream();

-  void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);

+  void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);

+

+  bool WasFinished() const { return _index == _numFiles; }

+

   UInt64 GetFullSize() const

   {

     UInt64 size = 0;

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
deleted file mode 100644
index d206d7c..0000000
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// 7zFolderOutStream.cpp

-

-#include "StdAfx.h"

-

-#include "7zFolderOutStream.h"

-

-namespace NArchive {

-namespace N7z {

-

-CFolderOutStream::CFolderOutStream()

-{

-  _crcStreamSpec = new COutStreamWithCRC;

-  _crcStream = _crcStreamSpec;

-}

-

-HRESULT CFolderOutStream::Init(

-    const CDbEx *db,

-    UInt32 ref2Offset, UInt32 startIndex,

-    const CBoolVector *extractStatuses,

-    IArchiveExtractCallback *extractCallback,

-    bool testMode, bool checkCrc)

-{

-  _db = db;

-  _ref2Offset = ref2Offset;

-  _startIndex = startIndex;

-

-  _extractStatuses = extractStatuses;

-  _extractCallback = extractCallback;

-  _testMode = testMode;

-  _checkCrc = checkCrc;

-

-  _currentIndex = 0;

-  _fileIsOpen = false;

-  return ProcessEmptyFiles();

-}

-

-HRESULT CFolderOutStream::OpenFile()

-{

-  Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?

-      NExtract::NAskMode::kTest :

-      NExtract::NAskMode::kExtract) :

-      NExtract::NAskMode::kSkip;

-  CMyComPtr<ISequentialOutStream> realOutStream;

-  UInt32 index = _startIndex + _currentIndex;

-  RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));

-  _crcStreamSpec->SetStream(realOutStream);

-  _crcStreamSpec->Init(_checkCrc);

-  _fileIsOpen = true;

-  const CFileItem &fi = _db->Files[index];

-  _rem = fi.Size;

-  if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&

-      !_db->IsItemAnti(index) && !fi.IsDir)

-    askMode = NExtract::NAskMode::kSkip;

-  return _extractCallback->PrepareOperation(askMode);

-}

-

-HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)

-{

-  _crcStreamSpec->ReleaseStream();

-  _fileIsOpen = false;

-  _currentIndex++;

-  return _extractCallback->SetOperationResult(res);

-}

-

-HRESULT CFolderOutStream::CloseFileAndSetResult()

-{

-  const CFileItem &fi = _db->Files[_startIndex + _currentIndex];

-  return CloseFileAndSetResult(

-      (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?

-      NExtract::NOperationResult::kOK :

-      NExtract::NOperationResult::kCRCError);

-}

-

-HRESULT CFolderOutStream::ProcessEmptyFiles()

-{

-  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)

-  {

-    RINOK(OpenFile());

-    RINOK(CloseFileAndSetResult());

-  }

-  return S_OK;

-}

-

-STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

-{

-  if (processedSize != NULL)

-    *processedSize = 0;

-  while (size != 0)

-  {

-    if (_fileIsOpen)

-    {

-      UInt32 cur = size < _rem ? size : (UInt32)_rem;

-      RINOK(_crcStream->Write(data, cur, &cur));

-      if (cur == 0)

-        break;

-      data = (const Byte *)data + cur;

-      size -= cur;

-      _rem -= cur;

-      if (processedSize != NULL)

-        *processedSize += cur;

-      if (_rem == 0)

-      {

-        RINOK(CloseFileAndSetResult());

-        RINOK(ProcessEmptyFiles());

-        continue;

-      }

-    }

-    else

-    {

-      RINOK(ProcessEmptyFiles());

-      if (_currentIndex == _extractStatuses->Size())

-      {

-        // we support partial extracting

-        if (processedSize != NULL)

-          *processedSize += size;

-        break;

-      }

-      RINOK(OpenFile());

-    }

-  }

-  return S_OK;

-}

-

-STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)

-{

-  *value = 0;

-  if ((int)subStream >= _extractStatuses->Size())

-    return S_FALSE;

-  *value = _db->Files[_startIndex + (int)subStream].Size;

-  return S_OK;

-}

-

-HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)

-{

-  while (_currentIndex < _extractStatuses->Size())

-  {

-    if (_fileIsOpen)

-    {

-      RINOK(CloseFileAndSetResult(resultEOperationResult));

-    }

-    else

-    {

-      RINOK(OpenFile());

-    }

-  }

-  return S_OK;

-}

-

-}}

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
deleted file mode 100644
index c00aba7..0000000
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 7zFolderOutStream.h

-

-#ifndef __7Z_FOLDER_OUT_STREAM_H

-#define __7Z_FOLDER_OUT_STREAM_H

-

-#include "../../IStream.h"

-#include "../IArchive.h"

-#include "../Common/OutStreamWithCRC.h"

-

-#include "7zIn.h"

-

-namespace NArchive {

-namespace N7z {

-

-class CFolderOutStream:

-  public ISequentialOutStream,

-  public ICompressGetSubStreamSize,

-  public CMyUnknownImp

-{

-  COutStreamWithCRC *_crcStreamSpec;

-  CMyComPtr<ISequentialOutStream> _crcStream;

-  const CDbEx *_db;

-  const CBoolVector *_extractStatuses;

-  CMyComPtr<IArchiveExtractCallback> _extractCallback;

-  UInt32 _ref2Offset;

-  UInt32 _startIndex;

-  unsigned _currentIndex;

-  bool _testMode;

-  bool _checkCrc;

-  bool _fileIsOpen;

-  UInt64 _rem;

-

-  HRESULT OpenFile();

-  HRESULT CloseFileAndSetResult(Int32 res);

-  HRESULT CloseFileAndSetResult();

-  HRESULT ProcessEmptyFiles();

-public:

-  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

-

-  CFolderOutStream();

-

-  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

-  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

-

-  HRESULT Init(

-      const CDbEx *db,

-      UInt32 ref2Offset, UInt32 startIndex,

-      const CBoolVector *extractStatuses,

-      IArchiveExtractCallback *extractCallback,

-      bool testMode, bool checkCrc);

-  HRESULT FlushCorrupted(Int32 resultEOperationResult);

-  HRESULT WasWritingFinished() const

-      { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }

-};

-

-}}

-

-#endif

diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 6104440..ce955a6 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -36,10 +36,14 @@
   #endif

 

   #ifdef EXTRACT_ONLY

+  

   _crcSize = 4;

+  

   #ifdef __7Z_SET_PROPERTIES

   _numThreads = NSystem::GetNumberOfProcessors();

+  _useMultiThreadMixer = true;

   #endif

+  

   #endif

 }

 

@@ -150,22 +154,12 @@
  

 void CHandler::AddMethodName(AString &s, UInt64 id)

 {

-  UString methodName;

-  FindMethod(EXTERNAL_CODECS_VARS id, methodName);

-  if (methodName.IsEmpty())

-  {

-    for (unsigned i = 0; i < methodName.Len(); i++)

-      if (methodName[i] >= 0x80)

-      {

-        methodName.Empty();

-        break;

-      }

-  }

-  if (methodName.IsEmpty())

+  AString name;

+  FindMethod(EXTERNAL_CODECS_VARS id, name);

+  if (name.IsEmpty())

     ConvertMethodIdToString(s, id);

   else

-    for (unsigned i = 0; i < methodName.Len(); i++)

-      s += (char)methodName[i];

+    s += name;

 }

 

 #endif

@@ -186,8 +180,7 @@
       FOR_VECTOR (i, pm.IDs)

       {

         UInt64 id = pm.IDs[i];

-        if (!s.IsEmpty())

-          s += ' ';

+        s.Add_Space_if_NotEmpty();

         char temp[16];

         if (id == k_LZMA2)

         {

@@ -376,6 +369,7 @@
   // numCoders == 0 ???

   CNum numCoders = inByte.ReadNum();

   bool needSpace = false;

+  

   for (; numCoders != 0; numCoders--, needSpace = true)

   {

     if (pos < 32) // max size of property

@@ -435,11 +429,11 @@
         name = "LZMA2";

         if (propsSize == 1)

         {

-          Byte p = props[0];

-          if ((p & 1) == 0)

-            ConvertUInt32ToString((UInt32)((p >> 1) + 12), s);

+          Byte d = props[0];

+          if ((d & 1) == 0)

+            ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);

           else

-            GetStringForSizeValue(s, 3 << ((p >> 1) + 11));

+            GetStringForSizeValue(s, 3 << ((d >> 1) + 11));

         }

       }

       else if (id == k_PPMD)

@@ -500,17 +494,8 @@
     }

     else

     {

-      UString methodName;

+      AString methodName;

       FindMethod(EXTERNAL_CODECS_VARS id64, methodName);

-      if (methodName.IsEmpty())

-      {

-        for (unsigned j = 0; j < methodName.Len(); j++)

-          if (methodName[j] >= 0x80)

-          {

-            methodName.Empty();

-            break;

-          }

-      }

       if (needSpace)

         temp[--pos] = ' ';

       if (methodName.IsEmpty())

@@ -522,10 +507,11 @@
           break;

         pos -= len;

         for (unsigned i = 0; i < len; i++)

-          temp[pos + i] = (char)methodName[i];

+          temp[pos + i] = methodName[i];

       }

     }

   }

+  

   if (numCoders != 0 && pos >= 4)

   {

     temp[--pos] = ' ';

@@ -533,6 +519,7 @@
     temp[--pos] = '.';

     temp[--pos] = '.';

   }

+  

   return PropVarEm_Set_Str(prop, temp + pos);

   // }

 }

@@ -555,7 +542,7 @@
   const CFileItem &item = _db.Files[index];

   UInt32 index2 = index;

 

-  switch(propID)

+  switch (propID)

   {

     case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;

     case kpidSize:

@@ -608,7 +595,9 @@
     */

 

     case kpidPath: return _db.GetPath_Prop(index, value);

+    

     #ifndef _SFX

+    

     case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);

     case kpidBlock:

       {

@@ -617,30 +606,29 @@
           PropVarEm_Set_UInt32(value, (UInt32)folderIndex);

       }

       break;

+    /*

     case kpidPackedSize0:

     case kpidPackedSize1:

     case kpidPackedSize2:

     case kpidPackedSize3:

     case kpidPackedSize4:

       {

-        /*

         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

         if (folderIndex != kNumNoIndex)

         {

-          const CFolder &folderInfo = _db.Folders[folderIndex];

           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&

-              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))

+              _db.FoStartPackStreamIndex[folderIndex + 1] -

+              _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))

           {

-            prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);

+            PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));

           }

-          else

-            prop = (UInt64)0;

         }

         else

-          prop = (UInt64)0;

-        */

+          PropVarEm_Set_UInt64(value, 0);

       }

       break;

+    */

+    

     #endif

   }

   // prop.Detach(value);

@@ -668,7 +656,13 @@
       openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);

     #endif

 

-    CInArchive archive;

+    CInArchive archive(

+          #ifdef __7Z_SET_PROPERTIES

+          _useMultiThreadMixer

+          #else

+          true

+          #endif

+          );

     _db.IsArc = false;

     RINOK(archive.Open(stream, maxCheckStartPosition));

     _db.IsArc = true;

@@ -677,7 +671,7 @@
         EXTERNAL_CODECS_VARS

         _db

         #ifndef _NO_CRYPTO

-          , getTextPassword, _isEncrypted, _passwordIsDefined

+          , getTextPassword, _isEncrypted, _passwordIsDefined, _password

         #endif

         );

     RINOK(result);

@@ -688,8 +682,9 @@
   {

     Close();

     // return E_INVALIDARG;

+    // return S_FALSE;

     // we must return out_of_memory here

-    return S_FALSE;

+    return E_OUTOFMEMORY;

   }

   // _inStream = stream;

   #ifndef _SFX

@@ -707,6 +702,7 @@
   #ifndef _NO_CRYPTO

   _isEncrypted = false;

   _passwordIsDefined = false;

+  _password.Empty();

   #endif

   return S_OK;

   COM_TRY_END

@@ -715,11 +711,12 @@
 #ifdef __7Z_SET_PROPERTIES

 #ifdef EXTRACT_ONLY

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

   const UInt32 numProcessors = NSystem::GetNumberOfProcessors();

   _numThreads = numProcessors;

+  _useMultiThreadMixer = true;

 

   for (UInt32 i = 0; i < numProps; i++)

   {

@@ -729,10 +726,15 @@
       return E_INVALIDARG;

     const PROPVARIANT &value = values[i];

     UInt32 number;

-    int index = ParseStringToUInt32(name, number);

+    unsigned index = ParseStringToUInt32(name, number);

     if (index == 0)

     {

-      if (name.IsPrefixedBy(L"mt"))

+      if (name.IsEqualTo("mtf"))

+      {

+        RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));

+        continue;

+      }

+      if (name.IsPrefixedBy_Ascii_NoCase("mt"))

       {

         RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));

         continue;

diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index e7a80d8..00a8e83 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,24 +18,14 @@
 namespace NArchive {

 namespace N7z {

 

-const UInt32 k_Copy = 0x0;

-const UInt32 k_Delta = 3;

-const UInt32 k_LZMA2 = 0x21;

-const UInt32 k_LZMA  = 0x030101;

-const UInt32 k_PPMD  = 0x030401;

-const UInt32 k_BCJ  = 0x03030103;

-const UInt32 k_BCJ2 = 0x0303011B;

-const UInt32 k_Deflate = 0x040108;

-const UInt32 k_BZip2   = 0x040202;

-

 #ifndef __7Z_SET_PROPERTIES

 

 #ifdef EXTRACT_ONLY

-#if !defined(_7ZIP_ST) && !defined(_SFX)

-#define __7Z_SET_PROPERTIES

-#endif

+  #if !defined(_7ZIP_ST) && !defined(_SFX)

+    #define __7Z_SET_PROPERTIES

+  #endif

 #else

-#define __7Z_SET_PROPERTIES

+  #define __7Z_SET_PROPERTIES

 #endif

 

 #endif

@@ -54,6 +44,7 @@
   UInt64 _numSolidBytes;

   bool _numSolidBytesDefined;

   bool _solidExtension;

+  bool _useTypeSorting;

 

   bool _compressHeaders;

   bool _encryptHeadersSpecified;

@@ -64,7 +55,9 @@
   CBoolPair Write_ATime;

   CBoolPair Write_MTime;

 

-  bool _volumeMode;

+  bool _useMultiThreadMixer;

+

+  // bool _volumeMode;

 

   void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }

   void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }

@@ -117,7 +110,7 @@
   INTERFACE_IArchiveGetRawProps(;)

 

   #ifdef __7Z_SET_PROPERTIES

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);

+  STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);

   #endif

 

   #ifndef EXTRACT_ONLY

@@ -131,28 +124,29 @@
 private:

   CMyComPtr<IInStream> _inStream;

   NArchive::N7z::CDbEx _db;

+  

   #ifndef _NO_CRYPTO

   bool _isEncrypted;

   bool _passwordIsDefined;

+  UString _password;

   #endif

 

   #ifdef EXTRACT_ONLY

   

   #ifdef __7Z_SET_PROPERTIES

   UInt32 _numThreads;

+  bool _useMultiThreadMixer;

   #endif

 

   UInt32 _crcSize;

 

   #else

   

-  CRecordVector<CBind> _binds;

+  CRecordVector<CBond2> _bonds;

 

   HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);

   HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);

-  void AddDefaultMethod();

-  HRESULT SetMainMethod(CCompressionMethodMode &method,

-      CObjectVector<COneMethodInfo> &methodsInfo

+  HRESULT SetMainMethod(CCompressionMethodMode &method

       #ifndef _7ZIP_ST

       , UInt32 numThreads

       #endif

diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index aff5809..2f6a072 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -18,11 +18,11 @@
 namespace NArchive {

 namespace N7z {

 

-static const wchar_t *k_LZMA_Name = L"LZMA";

-static const wchar_t *kDefaultMethodName = L"LZMA2";

-static const wchar_t *k_Copy_Name = L"Copy";

+static const char *k_LZMA_Name = "LZMA";

+static const char *kDefaultMethodName = "LZMA2";

+static const char *k_Copy_Name = "Copy";

 

-static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";

+static const char *k_MatchFinder_ForHeaders = "BT2";

 static const UInt32 k_NumFastBytes_ForHeaders = 273;

 static const UInt32 k_Level_ForHeaders = 5;

 static const UInt32 k_Dictionary_ForHeaders =

@@ -42,7 +42,7 @@
 {

   if (!FindMethod(

       EXTERNAL_CODECS_VARS

-      m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))

+      m.MethodName, dest.Id, dest.NumStreams))

     return E_INVALIDARG;

   (CProps &)dest = (CProps &)m;

   return S_OK;

@@ -54,48 +54,62 @@
     return S_OK;

   COneMethodInfo m;

   m.MethodName = k_LZMA_Name;

-  m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);

-  m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);

+  m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);

+  m.AddProp_Level(k_Level_ForHeaders);

   m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);

   m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);

-  m.AddNumThreadsProp(1);

+  m.AddProp_NumThreads(1);

 

-  CMethodFull methodFull;

-  RINOK(PropsMethod_To_FullMethod(methodFull, m));

-  headerMethod.Methods.Add(methodFull);

-  return S_OK;

-}

-

-void CHandler::AddDefaultMethod()

-{

-  FOR_VECTOR (i, _methods)

-  {

-    UString &methodName = _methods[i].MethodName;

-    if (methodName.IsEmpty())

-      methodName = kDefaultMethodName;

-  }

-  if (_methods.IsEmpty())

-  {

-    COneMethodInfo m;

-    m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);

-    _methods.Add(m);

-  }

+  CMethodFull &methodFull = headerMethod.Methods.AddNew();

+  return PropsMethod_To_FullMethod(methodFull, m);

 }

 

 HRESULT CHandler::SetMainMethod(

-    CCompressionMethodMode &methodMode,

-    CObjectVector<COneMethodInfo> &methods

+    CCompressionMethodMode &methodMode

     #ifndef _7ZIP_ST

     , UInt32 numThreads

     #endif

     )

 {

-  AddDefaultMethod();

+  methodMode.Bonds = _bonds;

+

+  CObjectVector<COneMethodInfo> methods = _methods;

+

+  {

+    FOR_VECTOR (i, methods)

+    {

+      AString &methodName = methods[i].MethodName;

+      if (methodName.IsEmpty())

+        methodName = kDefaultMethodName;

+    }

+    if (methods.IsEmpty())

+    {

+      COneMethodInfo &m = methods.AddNew();

+      m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);

+      methodMode.DefaultMethod_was_Inserted = true;

+    }

+  }

+

+  if (!_filterMethod.MethodName.IsEmpty())

+  {

+    // if (methodMode.Bonds.IsEmpty())

+    {

+      FOR_VECTOR (k, methodMode.Bonds)

+      {

+        CBond2 &bond = methodMode.Bonds[k];

+        bond.InCoder++;

+        bond.OutCoder++;

+      }

+      methods.Insert(0, _filterMethod);

+      methodMode.Filter_was_Inserted = true;

+    }

+  }

 

   const UInt64 kSolidBytes_Min = (1 << 24);

   const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;

 

   bool needSolid = false;

+  

   FOR_VECTOR (i, methods)

   {

     COneMethodInfo &oneMethodInfo = methods[i];

@@ -105,9 +119,8 @@
       #endif

       );

 

-    CMethodFull methodFull;

+    CMethodFull &methodFull = methodMode.Methods.AddNew();

     RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));

-    methodMode.Methods.Add(methodFull);

 

     if (methodFull.Id != k_Copy)

       needSolid = true;

@@ -125,6 +138,7 @@
       case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;

       default: continue;

     }

+    

     _numSolidBytes = (UInt64)dicSize << 7;

     if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;

     if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;

@@ -268,7 +282,8 @@
   bool need_CTime = (Write_CTime.Def && Write_CTime.Val);

   bool need_ATime = (Write_ATime.Def && Write_ATime.Val);

   bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);

-  if (db)

+  

+  if (db && !db->Files.IsEmpty())

   {

     if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();

     if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();

@@ -494,14 +509,19 @@
 

     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);

   }

 

@@ -517,18 +537,20 @@
 

   CCompressionMethodMode methodMode, headerMethod;

 

-  HRESULT res = SetMainMethod(methodMode, _methods

+  HRESULT res = SetMainMethod(methodMode

     #ifndef _7ZIP_ST

     , _numThreads

     #endif

     );

   RINOK(res);

-  methodMode.Binds = _binds;

 

   RINOK(SetHeaderMethod(headerMethod));

+  

   #ifndef _7ZIP_ST

   methodMode.NumThreads = _numThreads;

+  methodMode.MultiThreadMixer = _useMultiThreadMixer;

   headerMethod.NumThreads = 1;

+  headerMethod.MultiThreadMixer = _useMultiThreadMixer;

   #endif

 

   CMyComPtr<ICryptoGetTextPassword2> getPassword2;

@@ -542,7 +564,7 @@
     Int32 passwordIsDefined;

     RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));

     methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);

-    if (methodMode.PasswordIsDefined && (BSTR)password)

+    if (methodMode.PasswordIsDefined && password)

       methodMode.Password = password;

   }

 

@@ -550,6 +572,15 @@
 

   bool encryptHeaders = false;

 

+  #ifndef _NO_CRYPTO

+  if (!methodMode.PasswordIsDefined && _passwordIsDefined)

+  {

+    // if header is compressed, we use that password for updated archive

+    methodMode.PasswordIsDefined = true;

+    methodMode.Password = _password;

+  }

+  #endif

+

   if (methodMode.PasswordIsDefined)

   {

     if (_encryptHeadersSpecified)

@@ -569,12 +600,14 @@
   if (numItems < 2)

     compressMainHeader = false;

 

+  int level = GetLevel();

+

   CUpdateOptions options;

   options.Method = &methodMode;

-  options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;

-  int level = GetLevel();

-  options.UseFilters = level != 0 && _autoFilter;

-  options.MaxFilter = level >= 8;

+  options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;

+  options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);

+  options.MaxFilter = (level >= 8);

+  options.AnalysisLevel = GetAnalysisLevel();

 

   options.HeaderOptions.CompressMainHeader = compressMainHeader;

   /*

@@ -586,8 +619,12 @@
   options.NumSolidFiles = _numSolidFiles;

   options.NumSolidBytes = _numSolidBytes;

   options.SolidExtension = _solidExtension;

+  options.UseTypeSorting = _useTypeSorting;

+

   options.RemoveSfxBlock = _removeSfxBlock;

-  options.VolumeMode = _volumeMode;

+  // options.VolumeMode = _volumeMode;

+

+  options.MultiThreadMixer = _useMultiThreadMixer;

 

   COutArchive archive;

   CArchiveDatabaseOut newDatabase;

@@ -635,20 +672,22 @@
   COM_TRY_END

 }

 

-static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)

+static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)

 {

   stream = 0;

-  int index = ParseStringToUInt32(srcString, coder);

-  if (index == 0)

-    return E_INVALIDARG;

-  srcString.Delete(0, index);

+  {

+    unsigned index = ParseStringToUInt32(srcString, coder);

+    if (index == 0)

+      return E_INVALIDARG;

+    srcString.DeleteFrontal(index);

+  }

   if (srcString[0] == 's')

   {

     srcString.Delete(0);

-    int index = ParseStringToUInt32(srcString, stream);

+    unsigned index = ParseStringToUInt32(srcString, stream);

     if (index == 0)

       return E_INVALIDARG;

-    srcString.Delete(0, index);

+    srcString.DeleteFrontal(index);

   }

   return S_OK;

 }

@@ -667,8 +706,12 @@
   Write_ATime.Init();

   Write_MTime.Init();

 

-  _volumeMode = false;

+  _useMultiThreadMixer = true;

+

+  // _volumeMode = false;

+

   InitSolid();

+  _useTypeSorting = false;

 }

 

 HRESULT COutHandler::SetSolidFromString(const UString &s)

@@ -762,7 +805,7 @@
   

   UInt32 number;

   int index = ParseStringToUInt32(name, number);

-  UString realName = name.Ptr(index);

+  // UString realName = name.Ptr(index);

   if (index == 0)

   {

     if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);

@@ -787,15 +830,19 @@
     if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);

     if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);

     

-    if (name.IsEqualTo("v"))  return PROPVARIANT_to_bool(value, _volumeMode);

+    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);

 }

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

-  _binds.Clear();

+  _bonds.Clear();

   InitProps();

 

   for (UInt32 i = 0; i < numProps; i++)

@@ -812,15 +859,19 @@
       if (value.vt != VT_EMPTY)

         return E_INVALIDARG;

       name.Delete(0);

-      CBind bind;

-      RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));

+      

+      CBond2 bond;

+      RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));

       if (name[0] != ':')

         return E_INVALIDARG;

       name.Delete(0);

-      RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));

+      UInt32 inStream = 0;

+      RINOK(ParseBond(name, bond.InCoder, inStream));

+      if (inStream != 0)

+        return E_INVALIDARG;

       if (!name.IsEmpty())

         return E_INVALIDARG;

-      _binds.Add(bind);

+      _bonds.Add(bond);

       continue;

     }

 

@@ -831,40 +882,27 @@
   if (numEmptyMethods > 0)

   {

     unsigned k;

-    for (k = 0; k < _binds.Size(); k++)

+    for (k = 0; k < _bonds.Size(); k++)

     {

-      const CBind &bind = _binds[k];

-      if (bind.InCoder < (UInt32)numEmptyMethods ||

-          bind.OutCoder < (UInt32)numEmptyMethods)

+      const CBond2 &bond = _bonds[k];

+      if (bond.InCoder < (UInt32)numEmptyMethods ||

+          bond.OutCoder < (UInt32)numEmptyMethods)

         return E_INVALIDARG;

     }

-    for (k = 0; k < _binds.Size(); k++)

+    for (k = 0; k < _bonds.Size(); k++)

     {

-      CBind &bind = _binds[k];

-      bind.InCoder -= (UInt32)numEmptyMethods;

-      bind.OutCoder -= (UInt32)numEmptyMethods;

+      CBond2 &bond = _bonds[k];

+      bond.InCoder -= (UInt32)numEmptyMethods;

+      bond.OutCoder -= (UInt32)numEmptyMethods;

     }

     _methods.DeleteFrontal(numEmptyMethods);

   }

   

-  AddDefaultMethod();

-

-  if (!_filterMethod.MethodName.IsEmpty())

+  FOR_VECTOR (k, _bonds)

   {

-    FOR_VECTOR (k, _binds)

-    {

-      CBind &bind = _binds[k];

-      bind.InCoder++;

-      bind.OutCoder++;

-    }

-    _methods.Insert(0, _filterMethod);

-  }

-

-  FOR_VECTOR (k, _binds)

-  {

-    const CBind &bind = _binds[k];

-    if (bind.InCoder >= (UInt32)_methods.Size() ||

-        bind.OutCoder >= (UInt32)_methods.Size())

+    const CBond2 &bond = _bonds[k];

+    if (bond.InCoder >= (UInt32)_methods.Size() ||

+        bond.OutCoder >= (UInt32)_methods.Size())

       return E_INVALIDARG;

   }

 

diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
index 78b5061..7de6eee 100644
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -96,6 +96,53 @@
   };

 }

 

+

+const UInt32 k_Copy = 0;

+const UInt32 k_Delta = 3;

+

+const UInt32 k_LZMA2 = 0x21;

+

+const UInt32 k_SWAP2 = 0x20302;

+const UInt32 k_SWAP4 = 0x20304;

+

+const UInt32 k_LZMA  = 0x30101;

+const UInt32 k_PPMD  = 0x30401;

+

+const UInt32 k_Deflate = 0x40108;

+const UInt32 k_BZip2   = 0x40202;

+

+const UInt32 k_BCJ   = 0x3030103;

+const UInt32 k_BCJ2  = 0x303011B;

+const UInt32 k_PPC   = 0x3030205;

+const UInt32 k_IA64  = 0x3030401;

+const UInt32 k_ARM   = 0x3030501;

+const UInt32 k_ARMT  = 0x3030701;

+const UInt32 k_SPARC = 0x3030805;

+

+const UInt32 k_AES   = 0x6F10701;

+

+

+static inline bool IsFilterMethod(UInt64 m)

+{

+  if (m > (UInt64)0xFFFFFFFF)

+    return false;

+  switch ((UInt32)m)

+  {

+    case k_Delta:

+    case k_BCJ:

+    case k_BCJ2:

+    case k_PPC:

+    case k_IA64:

+    case k_ARM:

+    case k_ARMT:

+    case k_SPARC:

+    case k_SWAP2:

+    case k_SWAP4:

+      return true;

+  }

+  return false;

+}

+

 }}

 

 #endif

diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 5a85507..b03bc89 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,9 +32,6 @@
 namespace NArchive {

 namespace N7z {

 

-static const UInt32 k_LZMA2 = 0x21;

-static const UInt32 k_LZMA  = 0x030101;

-

 static void BoolVector_Fill_False(CBoolVector &v, unsigned size)

 {

   v.ClearAndSetSize(size);

@@ -43,78 +40,6 @@
     p[i] = false;

 }

 

-static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)

-{

-  if (index >= (UInt32)v.Size())

-    return true;

-  bool res = v[index];

-  v[index] = true;

-  return res;

-}

-

-bool CFolder::CheckStructure(unsigned numUnpackSizes) const

-{

-  const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it

-  const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax

-  const unsigned kNumBindsMax = 32;

-

-  if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)

-    return false;

-

-  {

-    CBoolVector v;

-    BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());

-    

-    unsigned i;

-    for (i = 0; i < BindPairs.Size(); i++)

-      if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))

-        return false;

-    for (i = 0; i < PackStreams.Size(); i++)

-      if (BoolVector_GetAndSet(v, PackStreams[i]))

-        return false;

-    

-    BoolVector_Fill_False(v, numUnpackSizes);

-    for (i = 0; i < BindPairs.Size(); i++)

-      if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))

-        return false;

-  }

-  

-  UInt32 mask[kMaskSize];

-  unsigned i;

-  for (i = 0; i < kMaskSize; i++)

-    mask[i] = 0;

-

-  {

-    CUIntVector inStreamToCoder, outStreamToCoder;

-    for (i = 0; i < Coders.Size(); i++)

-    {

-      CNum j;

-      const CCoderInfo &coder = Coders[i];

-      for (j = 0; j < coder.NumInStreams; j++)

-        inStreamToCoder.Add(i);

-      for (j = 0; j < coder.NumOutStreams; j++)

-        outStreamToCoder.Add(i);

-    }

-    

-    for (i = 0; i < BindPairs.Size(); i++)

-    {

-      const CBindPair &bp = BindPairs[i];

-      mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);

-    }

-  }

-  

-  for (i = 0; i < kMaskSize; i++)

-    for (unsigned j = 0; j < kMaskSize; j++)

-      if (((1 << j) & mask[i]) != 0)

-        mask[i] |= mask[j];

-

-  for (i = 0; i < kMaskSize; i++)

-    if (((1 << i) & mask[i]) != 0)

-      return false;

-

-  return true;

-}

-

 class CInArchiveException {};

 class CUnsupportedFeatureException: public CInArchiveException {};

 

@@ -168,6 +93,8 @@
   Byte external = archive->ReadByte();

   if (external != 0)

   {

+    if (!dataVector)

+      ThrowIncorrect();

     CNum dataIndex = archive->ReadNum();

     if (dataIndex >= dataVector->Size())

       ThrowIncorrect();

@@ -193,6 +120,8 @@
 

 void CInByte2::ReadBytes(Byte *data, size_t size)

 {

+  if (size == 0)

+    return;

   if (size > _size - _pos)

     ThrowEndOfData();

   memcpy(data, _buffer + _pos, size);

@@ -218,41 +147,48 @@
     processed = 0;

     return 0;

   }

-  Byte firstByte = *p++;

+  

+  unsigned b = *p++;

   size--;

-  if ((firstByte & 0x80) == 0)

+  

+  if ((b & 0x80) == 0)

   {

     processed = 1;

-    return firstByte;

+    return b;

   }

-  Byte mask = 0x40;

+  

   if (size == 0)

   {

     processed = 0;

     return 0;

   }

+  

   UInt64 value = (UInt64)*p;

   p++;

   size--;

+  

   for (unsigned i = 1; i < 8; i++)

   {

-    if ((firstByte & mask) == 0)

+    unsigned mask = (unsigned)0x80 >> i;

+    if ((b & mask) == 0)

     {

-      UInt64 highPart = firstByte & (mask - 1);

-      value += (highPart << (i * 8));

+      UInt64 high = b & (mask - 1);

+      value |= (high << (i * 8));

       processed = i + 1;

       return value;

     }

+    

     if (size == 0)

     {

       processed = 0;

       return 0;

     }

+    

     value |= ((UInt64)*p << (i * 8));

     p++;

     size--;

-    mask >>= 1;

   }

+  

   processed = 9;

   return value;

 }

@@ -344,6 +280,7 @@
   for (;;)

   {

     UInt32 readSize = kBufSize - kHeaderSize;

+    if (searchHeaderSizeLimit)

     {

       UInt64 rem = *searchHeaderSizeLimit - offset;

       if (readSize > rem)

@@ -351,10 +288,12 @@
       if (readSize == 0)

         return S_FALSE;

     }

+    

     UInt32 processed = 0;

     RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));

     if (processed == 0)

       return S_FALSE;

+    

     for (UInt32 pos = 0;;)

     {

       const Byte *p = buf + pos + 1;

@@ -376,6 +315,7 @@
         return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);

       }

     }

+    

     offset += processed;

     memmove(buf, buf + processed, kHeaderSize);

   }

@@ -415,13 +355,15 @@
 

 void CInByte2::ParseFolder(CFolder &folder)

 {

-  CNum numCoders = ReadNum();

+  UInt32 numCoders = ReadNum();

+

+  if (numCoders == 0)

+    ThrowUnsupported();

 

   folder.Coders.SetSize(numCoders);

 

-  CNum numInStreams = 0;

-  CNum numOutStreams = 0;

-  CNum i;

+  UInt32 numInStreams = 0;

+  UInt32 i;

   for (i = 0; i < numCoders; i++)

   {

     CCoderInfo &coder = folder.Coders[i];

@@ -441,14 +383,14 @@
 

       if ((mainByte & 0x10) != 0)

       {

-        coder.NumInStreams = ReadNum();

-        coder.NumOutStreams = ReadNum();

+        coder.NumStreams = ReadNum();

+        /* numOutStreams = */ ReadNum();

       }

       else

       {

-        coder.NumInStreams = 1;

-        coder.NumOutStreams = 1;

+        coder.NumStreams = 1;

       }

+      

       if ((mainByte & 0x20) != 0)

       {

         CNum propsSize = ReadNum();

@@ -458,27 +400,27 @@
       else

         coder.Props.Free();

     }

-    numInStreams += coder.NumInStreams;

-    numOutStreams += coder.NumOutStreams;

+    numInStreams += coder.NumStreams;

   }

 

-  CNum numBindPairs = numOutStreams - 1;

-  folder.BindPairs.SetSize(numBindPairs);

-  for (i = 0; i < numBindPairs; i++)

+  UInt32 numBonds = numCoders - 1;

+  folder.Bonds.SetSize(numBonds);

+  for (i = 0; i < numBonds; i++)

   {

-    CBindPair &bp = folder.BindPairs[i];

-    bp.InIndex = ReadNum();

-    bp.OutIndex = ReadNum();

+    CBond &bp = folder.Bonds[i];

+    bp.PackIndex = ReadNum();

+    bp.UnpackIndex = ReadNum();

   }

 

-  if (numInStreams < numBindPairs)

+  if (numInStreams < numBonds)

     ThrowUnsupported();

-  CNum numPackStreams = numInStreams - numBindPairs;

+  UInt32 numPackStreams = numInStreams - numBonds;

   folder.PackStreams.SetSize(numPackStreams);

+  

   if (numPackStreams == 1)

   {

     for (i = 0; i < numInStreams; i++)

-      if (folder.FindBindPairForInStream(i) < 0)

+      if (folder.FindBond_for_PackStream(i) < 0)

       {

         folder.PackStreams[0] = i;

         break;

@@ -509,12 +451,12 @@
     return;

 

   size_t offset = NameOffsets[index];

-  size_t size = NameOffsets[index + 1] - offset - 1;

+  size_t size = NameOffsets[index + 1] - offset;

 

-  if (size >= (1 << 20))

+  if (size >= (1 << 28))

     return;

 

-  wchar_t *s = path.GetBuffer((unsigned)size);

+  wchar_t *s = path.GetBuf((unsigned)size - 1);

 

   const Byte *p = ((const Byte *)NamesBuf + offset * 2);

 

@@ -533,7 +475,7 @@
 

   #endif

 

-  path.ReleaseBuffer((unsigned)size);

+  path.ReleaseBuf_SetLen((unsigned)size - 1);

 }

 

 HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()

@@ -592,7 +534,7 @@
   {

     unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);

     const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;

-    do

+    for (; len != 0; len--)

     {

       p -= 2;

       --s;

@@ -601,7 +543,7 @@
         c = WCHAR_PATH_SEPARATOR;

       *s = c;

     }

-    while (--len);

+

     const CFileItem &file = Files[cur];

     cur = file.Parent;

     if (cur < 0)

@@ -639,6 +581,9 @@
   }

 }

 

+#define k_Scan_NumCoders_MAX 64

+#define k_Scan_NumCodersStreams_in_Folder_MAX 64

+

 void CInArchive::ReadPackInfo(CFolders &f)

 {

   CNum numPackStreams = ReadNum();

@@ -692,27 +637,31 @@
     folders.FoCodersDataOffset.Alloc(numFolders + 1);

     folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);

 

-    CRecordVector<bool> InStreamUsed;

-    CRecordVector<bool> OutStreamUsed;

+    CBoolVector StreamUsed;

+    CBoolVector CoderUsed;

 

     CNum packStreamIndex = 0;

     CNum fo;

     CInByte2 *inByte = _inByteBack;

+    

     for (fo = 0; fo < numFolders; fo++)

     {

-      UInt32 numOutStreams = 0;

       UInt32 indexOfMainStream = 0;

       UInt32 numPackStreams = 0;

       folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;

 

-      numOutStreams = 0;

       CNum numInStreams = 0;

       CNum numCoders = inByte->ReadNum();

+    

+      if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)

+        ThrowUnsupported();

+

       for (CNum ci = 0; ci < numCoders; ci++)

       {

         Byte mainByte = inByte->ReadByte();

         if ((mainByte & 0xC0) != 0)

           ThrowUnsupported();

+        

         unsigned idSize = (mainByte & 0xF);

         if (idSize > 8)

           ThrowUnsupported();

@@ -725,19 +674,21 @@
         inByte->SkipDataNoCheck(idSize);

         if (folders.ParsedMethods.IDs.Size() < 128)

           folders.ParsedMethods.IDs.AddToUniqueSorted(id);

+        

         CNum coderInStreams = 1;

-        CNum coderOutStreams = 1;

         if ((mainByte & 0x10) != 0)

         {

           coderInStreams = inByte->ReadNum();

-          coderOutStreams = inByte->ReadNum();

+          if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)

+            ThrowUnsupported();

+          if (inByte->ReadNum() != 1)

+            ThrowUnsupported();

         }

+

         numInStreams += coderInStreams;

-        if (numInStreams < coderInStreams)

+        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)

           ThrowUnsupported();

-        numOutStreams += coderOutStreams;

-        if (numOutStreams < coderOutStreams)

-          ThrowUnsupported();

+        

         if ((mainByte & 0x20) != 0)

         {

           CNum propsSize = inByte->ReadNum();

@@ -759,7 +710,7 @@
         }

       }

       

-      if (numOutStreams == 1 && numInStreams == 1)

+      if (numCoders == 1 && numInStreams == 1)

       {

         indexOfMainStream = 0;

         numPackStreams = 1;

@@ -767,60 +718,64 @@
       else

       {

         UInt32 i;

-        if (numOutStreams == 0)

-          ThrowUnsupported();

-        CNum numBindPairs = numOutStreams - 1;

-        if (numInStreams < numBindPairs)

-          ThrowUnsupported();

-        if (numInStreams >= 256 || numOutStreams >= 256)

+        CNum numBonds = numCoders - 1;

+        if (numInStreams < numBonds)

           ThrowUnsupported();

         

-        InStreamUsed.ClearAndSetSize(numInStreams);

-        for (i = 0; i < numInStreams; i++)

-          InStreamUsed[i] = false;

+        BoolVector_Fill_False(StreamUsed, numInStreams);

+        BoolVector_Fill_False(CoderUsed, numCoders);

         

-        OutStreamUsed.ClearAndSetSize(numOutStreams);

-        for (i = 0; i < numOutStreams; i++)

-          OutStreamUsed[i] = false;

-        

-        for (i = 0; i < numBindPairs; i++)

+        for (i = 0; i < numBonds; i++)

         {

           CNum index = ReadNum();

-          if (index >= numInStreams || InStreamUsed[index])

+          if (index >= numInStreams || StreamUsed[index])

             ThrowUnsupported();

-          InStreamUsed[index] = true;

+          StreamUsed[index] = true;

+          

           index = ReadNum();

-          if (index >= numOutStreams || OutStreamUsed[index])

+          if (index >= numCoders || CoderUsed[index])

             ThrowUnsupported();

-          OutStreamUsed[index] = true;

+          CoderUsed[index] = true;

         }

         

-        numPackStreams = numInStreams - numBindPairs;

+        numPackStreams = numInStreams - numBonds;

         

         if (numPackStreams != 1)

           for (i = 0; i < numPackStreams; i++)

-            inByte->ReadNum(); // PackStreams

+          {

+            CNum index = inByte->ReadNum(); // PackStreams

+            if (index >= numInStreams || StreamUsed[index])

+              ThrowUnsupported();

+            StreamUsed[index] = true;

+          }

           

-        for (i = 0; i < numOutStreams; i++)

-          if (!OutStreamUsed[i])

+        for (i = 0; i < numCoders; i++)

+          if (!CoderUsed[i])

           {

             indexOfMainStream = i;

             break;

           }

-        if (i == numOutStreams)

+          

+        if (i == numCoders)

           ThrowUnsupported();

       }

+      

       folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;

-      numCodersOutStreams += numOutStreams;

+      numCodersOutStreams += numCoders;

       folders.FoStartPackStreamIndex[fo] = packStreamIndex;

+      if (numPackStreams > folders.NumPackStreams - packStreamIndex)

+        ThrowIncorrect();

       packStreamIndex += numPackStreams;

       folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;

     }

+    

     size_t dataSize = _inByteBack->GetPtr() - startBufPtr;

     folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;

     folders.FoStartPackStreamIndex[fo] = packStreamIndex;

     folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;

     folders.CodersData.CopyFrom(startBufPtr, dataSize);

+

+    // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();

   }

 

   WaitId(NID::kCodersUnpackSize);

@@ -1105,13 +1060,7 @@
     unpackSizes,

     digests);

   

-  CDecoder decoder(

-    #ifdef _ST_MODE

-    false

-    #else

-    true

-    #endif

-    );

+  CDecoder decoder(_useMixerMT);

 

   for (CNum i = 0; i < folders.NumFolders; i++)

   {

@@ -1127,14 +1076,20 @@
     outStreamSpec->Init(data, unpackSize);

     

     HRESULT result = decoder.Decode(

-      EXTERNAL_CODECS_LOC_VARS

-      _stream, baseOffset + dataOffset,

-      folders, i,

-      outStream, NULL

-      _7Z_DECODER_CRYPRO_VARS

-      #if !defined(_7ZIP_ST) && !defined(_SFX)

-      , false, 1

-      #endif

+        EXTERNAL_CODECS_LOC_VARS

+        _stream, baseOffset + dataOffset,

+        folders, i,

+        NULL, // *unpackSize

+        

+        outStream,

+        NULL, // *compressProgress

+        NULL  // **inStreamMainRes

+        

+        _7Z_DECODER_CRYPRO_VARS

+        #if !defined(_7ZIP_ST) && !defined(_SFX)

+          , false // mtMode

+          , 1     // numThreads

+        #endif

       );

     RINOK(result);

     

@@ -1142,7 +1097,10 @@
       if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])

         ThrowIncorrect();

   }

-  HeadersSize += folders.PackPositions[folders.NumPackStreams];

+

+  if (folders.PackPositions)

+    HeadersSize += folders.PackPositions[folders.NumPackStreams];

+

   return S_OK;

 }

 

@@ -1195,9 +1153,8 @@
   if (type == NID::kFilesInfo)

   {

   

-  CNum numFiles = ReadNum();

+  const CNum numFiles = ReadNum();

   db.Files.ClearAndSetSize(numFiles);

-  CNum i;

   /*

   db.Files.Reserve(numFiles);

   CNum i;

@@ -1208,7 +1165,7 @@
   db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);

   // if (!db.PackSizes.IsEmpty())

     db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);

-  if (numFiles > 0  && !digests.Defs.IsEmpty())

+  if (numFiles > 0 && !digests.Defs.IsEmpty())

     db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);

 

   CBoolVector emptyStreamVector;

@@ -1219,8 +1176,8 @@
 

   for (;;)

   {

-    UInt64 type = ReadID();

-    if (type == NID::kEnd)

+    const UInt64 type2 = ReadID();

+    if (type2 == NID::kEnd)

       break;

     UInt64 size = ReadNumber();

     if (size > _inByteBack->GetRem())

@@ -1229,9 +1186,9 @@
     switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);

     bool addPropIdToList = true;

     bool isKnownType = true;

-    if (type > ((UInt32)1 << 30))

+    if (type2 > ((UInt32)1 << 30))

       isKnownType = false;

-    else switch((UInt32)type)

+    else switch ((UInt32)type2)

     {

       case NID::kName:

       {

@@ -1265,7 +1222,7 @@
         ReadBoolVector2(db.Files.Size(), boolVector);

         CStreamSwitch streamSwitch;

         streamSwitch.Set(this, &dataVector);

-        for (i = 0; i < numFiles; i++)

+        for (CNum i = 0; i < numFiles; i++)

         {

           CFileItem &file = db.Files[i];

           file.AttribDefined = boolVector[i];

@@ -1308,7 +1265,7 @@
       {

         ReadBoolVector(numFiles, emptyStreamVector);

         numEmptyStreams = 0;

-        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)

+        for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)

           if (emptyStreamVector[i])

             numEmptyStreams++;

 

@@ -1382,28 +1339,34 @@
     if (isKnownType)

     {

       if (addPropIdToList)

-        db.ArcInfo.FileInfoPopIDs.Add(type);

+        db.ArcInfo.FileInfoPopIDs.Add(type2);

     }

     else

     {

       db.UnsupportedFeatureWarning = true;

       _inByteBack->SkipRem();

     }

-    // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02)

+    // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)

     if (_inByteBack->GetRem() != 0)

       ThrowIncorrect();

   }

 

   type = ReadID(); // Read (NID::kEnd) end of headers

 

+  if (numFiles - numEmptyStreams != unpackSizes.Size())

+    ThrowUnsupported();

+

   CNum emptyFileIndex = 0;

   CNum sizeIndex = 0;

 

   CNum numAntiItems = 0;

+

+  CNum i;

+

   for (i = 0; i < numEmptyStreams; i++)

     if (antiFileVector[i])

       numAntiItems++;

-    

+

   for (i = 0; i < numFiles; i++)

   {

     CFileItem &file = db.Files[i];

@@ -1444,13 +1407,13 @@
 

 void CDbEx::FillLinks()

 {

-  FolderStartFileIndex.ClearAndSetSize(NumFolders);

-  

-  FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());

+  FolderStartFileIndex.Alloc(NumFolders);

+  FileIndexToFolderIndexMap.Alloc(Files.Size());

   

   CNum folderIndex = 0;

   CNum indexInFolder = 0;

   unsigned i;

+

   for (i = 0; i < Files.Size(); i++)

   {

     bool emptyStream = !Files[i].HasStream;

@@ -1489,6 +1452,7 @@
   if (indexInFolder != 0)

     ThrowIncorrect();

   */

+  

   for (;;)

   {

     if (folderIndex >= NumFolders)

diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index d78eca2..260d8f7 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -26,8 +26,8 @@
 #define _7Z_DECODER_CRYPRO_VARS_DECL

 #define _7Z_DECODER_CRYPRO_VARS

 #else

-#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined

-#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined

+#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password

+#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password

 #endif

 

 struct CParsedMethods

@@ -39,6 +39,11 @@
   CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}

 };

 

+struct CFolderEx: public CFolder

+{

+  unsigned UnpackCoder;

+};

+

 struct CFolders

 {

   CNum NumPackStreams;

@@ -47,10 +52,10 @@
   CObjArray<UInt64> PackPositions; // NumPackStreams + 1

   // CUInt32DefVector PackCRCs; // we don't use PackCRCs now

 

-  CUInt32DefVector FolderCRCs;              // NumFolders

+  CUInt32DefVector FolderCRCs;             // NumFolders

   CObjArray<CNum> NumUnpackStreamsVector;  // NumFolders

 

-  CObjArray<UInt64> CoderUnpackSizes;      // including unpack sizes of bind coders

+  CObjArray<UInt64> CoderUnpackSizes;      // including unpack sizes of bond coders

   CObjArray<CNum> FoToCoderUnpackSizes;    // NumFolders + 1

   CObjArray<CNum> FoStartPackStreamIndex;  // NumFolders + 1

   CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders

@@ -61,10 +66,15 @@
   CParsedMethods ParsedMethods;

 

   void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;

+  void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const

+  {

+    ParseFolderInfo(folderIndex, folder);

+    folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];

+  }

   

   unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const

   {

-    return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];

+    return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);

   }

 

   UInt64 GetFolderUnpackSize(unsigned folderIndex) const

@@ -77,6 +87,8 @@
     return PackPositions[index + 1] - PackPositions[index];

   }

 

+  CFolders(): NumPackStreams(0), NumFolders(0) {}

+

   void Clear()

   {

     NumPackStreams = 0;

@@ -103,9 +115,9 @@
   CUInt64DefVector ATime;

   CUInt64DefVector MTime;

   CUInt64DefVector StartPos;

-  CRecordVector<bool> IsAnti;

+  CBoolVector IsAnti;

   /*

-  CRecordVector<bool> IsAux;

+  CBoolVector IsAux;

   CByteBuffer SecureBuf;

   CRecordVector<UInt32> SecureIDs;

   */

@@ -148,13 +160,14 @@
   bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }

   // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }

 

-  const void * GetName(unsigned index) const

+  /*

+  const void* GetName(unsigned index) const

   {

     if (!NameOffsets || !NamesBuf)

       return NULL;

-    return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);

+    return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);

   };

-

+  */

   void GetPath(unsigned index, UString &path) const;

   HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();

 };

@@ -181,8 +194,9 @@
 struct CDbEx: public CDatabase

 {

   CInArchiveInfo ArcInfo;

-  CRecordVector<CNum> FolderStartFileIndex;

-  CRecordVector<CNum> FileIndexToFolderIndexMap;

+  

+  CObjArray<CNum> FolderStartFileIndex;

+  CObjArray<CNum> FileIndexToFolderIndexMap;

 

   UInt64 HeadersSize;

   UInt64 PhySize;

@@ -234,8 +248,8 @@
     

     // SecureOffsets.Clear();

     ArcInfo.Clear();

-    FolderStartFileIndex.Clear();

-    FileIndexToFolderIndexMap.Clear();

+    FolderStartFileIndex.Free();

+    FileIndexToFolderIndexMap.Free();

 

     HeadersSize = 0;

     PhySize = 0;

@@ -243,22 +257,22 @@
 

   void FillLinks();

   

-  UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const

+  UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const

   {

     return ArcInfo.DataStartPosition +

         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];

   }

   

-  UInt64 GetFolderFullPackSize(unsigned folderIndex) const

+  UInt64 GetFolderFullPackSize(CNum folderIndex) const

   {

     return

       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -

       PackPositions[FoStartPackStreamIndex[folderIndex]];

   }

   

-  UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const

+  UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const

   {

-    unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;

+    size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;

     return PackPositions[i + 1] - PackPositions[i];

   }

 

@@ -327,6 +341,8 @@
 

   UInt64 HeadersSize;

 

+  bool _useMixerMT;

+

   void AddByteStream(const Byte *buffer, size_t size);

   

   void DeleteByteStream(bool needUpdatePos)

@@ -340,7 +356,6 @@
     }

   }

 

-private:

   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);

   

   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }

@@ -396,7 +411,11 @@
       _7Z_DECODER_CRYPRO_VARS_DECL

       );

 public:

-  CInArchive(): _numInByteBufs(0) { }

+  CInArchive(bool useMixerMT):

+      _numInByteBufs(0),

+      _useMixerMT(useMixerMT)

+      {}

+  

   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive

   void Close();

 

diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 90e6869..935ee43 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -13,8 +13,6 @@
 namespace NArchive {

 namespace N7z {

 

-const UInt64 k_AES = 0x06F10701;

-

 typedef UInt32 CNum;

 const CNum kNumMax     = 0x7FFFFFFF;

 const CNum kNumNoIndex = 0xFFFFFFFF;

@@ -23,71 +21,70 @@
 {

   CMethodId MethodID;

   CByteBuffer Props;

-  CNum NumInStreams;

-  CNum NumOutStreams;

+  UInt32 NumStreams;

   

-  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

+  bool IsSimpleCoder() const { return NumStreams == 1; }

 };

 

-struct CBindPair

+struct CBond

 {

-  CNum InIndex;

-  CNum OutIndex;

+  UInt32 PackIndex;

+  UInt32 UnpackIndex;

 };

 

 struct CFolder

 {

+  CLASS_NO_COPY(CFolder)

+public:

   CObjArray2<CCoderInfo> Coders;

-  CObjArray2<CBindPair> BindPairs;

-  CObjArray2<CNum> PackStreams;

+  CObjArray2<CBond> Bonds;

+  CObjArray2<UInt32> PackStreams;

 

-  CNum GetNumOutStreams() const

-  {

-    CNum result = 0;

-    FOR_VECTOR(i, Coders)

-      result += Coders[i].NumOutStreams;

-    return result;

-  }

+  CFolder() {}

 

-  int FindBindPairForInStream(CNum inStreamIndex) const

-  {

-    FOR_VECTOR(i, BindPairs)

-      if (BindPairs[i].InIndex == inStreamIndex)

-        return i;

-    return -1;

-  }

-  int FindBindPairForOutStream(CNum outStreamIndex) const

-  {

-    FOR_VECTOR(i, BindPairs)

-      if (BindPairs[i].OutIndex == outStreamIndex)

-        return i;

-    return -1;

-  }

-  int FindPackStreamArrayIndex(CNum inStreamIndex) const

+  bool IsDecodingSupported() const { return Coders.Size() <= 32; }

+

+  int Find_in_PackStreams(UInt32 packStream) const

   {

     FOR_VECTOR(i, PackStreams)

-      if (PackStreams[i] == inStreamIndex)

+      if (PackStreams[i] == packStream)

         return i;

     return -1;

   }

 

-  int GetIndexOfMainOutStream() const

+  int FindBond_for_PackStream(UInt32 packStream) const

   {

-    for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)

-      if (FindBindPairForOutStream(i) < 0)

+    FOR_VECTOR(i, Bonds)

+      if (Bonds[i].PackIndex == packStream)

         return i;

-    throw 1;

+    return -1;

   }

+  

+  /*

+  int FindBond_for_UnpackStream(UInt32 unpackStream) const

+  {

+    FOR_VECTOR(i, Bonds)

+      if (Bonds[i].UnpackIndex == unpackStream)

+        return i;

+    return -1;

+  }

+

+  int FindOutCoder() const

+  {

+    for (int i = (int)Coders.Size() - 1; i >= 0; i--)

+      if (FindBond_for_UnpackStream(i) < 0)

+        return i;

+    return -1;

+  }

+  */

 

   bool IsEncrypted() const

   {

-    for (int i = Coders.Size() - 1; i >= 0; i--)

+    FOR_VECTOR(i, Coders)

       if (Coders[i].MethodID == k_AES)

         return true;

     return false;

   }

-

-  bool CheckStructure(unsigned numUnpackSizes) const;

 };

 

 struct CUInt32DefVector

diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index cf776ce..0989978 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -199,7 +199,7 @@
     mask >>= 1;

   }

   WriteByte(firstByte);

-  for (;i > 0; i--)

+  for (; i > 0; i--)

   {

     WriteByte((Byte)value);

     value >>= 8;

@@ -254,31 +254,33 @@
 {

   WriteNumber(folder.Coders.Size());

   unsigned i;

+  

   for (i = 0; i < folder.Coders.Size(); i++)

   {

     const CCoderInfo &coder = folder.Coders[i];

     {

-      size_t propsSize = coder.Props.Size();

-      

       UInt64 id = coder.MethodID;

-      int idSize;

+      unsigned idSize;

       for (idSize = 1; idSize < sizeof(id); idSize++)

         if ((id >> (8 * idSize)) == 0)

           break;

-      Byte longID[15];

-      for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)

-        longID[t] = (Byte)(id & 0xFF);

-      Byte b;

-      b = (Byte)(idSize & 0xF);

+      idSize &= 0xF;

+      Byte temp[16];

+      for (unsigned t = idSize; t != 0; t--, id >>= 8)

+        temp[t] = (Byte)(id & 0xFF);

+  

+      Byte b = (Byte)(idSize);

       bool isComplex = !coder.IsSimpleCoder();

       b |= (isComplex ? 0x10 : 0);

-      b |= ((propsSize != 0) ? 0x20 : 0 );

-      WriteByte(b);

-      WriteBytes(longID, idSize);

+

+      size_t propsSize = coder.Props.Size();

+      b |= ((propsSize != 0) ? 0x20 : 0);

+      temp[0] = b;

+      WriteBytes(temp, idSize + 1);

       if (isComplex)

       {

-        WriteNumber(coder.NumInStreams);

-        WriteNumber(coder.NumOutStreams);

+        WriteNumber(coder.NumStreams);

+        WriteNumber(1); // NumOutStreams;

       }

       if (propsSize == 0)

         continue;

@@ -286,17 +288,17 @@
       WriteBytes(coder.Props, propsSize);

     }

   }

-  for (i = 0; i < folder.BindPairs.Size(); i++)

+  

+  for (i = 0; i < folder.Bonds.Size(); i++)

   {

-    const CBindPair &bindPair = folder.BindPairs[i];

-    WriteNumber(bindPair.InIndex);

-    WriteNumber(bindPair.OutIndex);

+    const CBond &bond = folder.Bonds[i];

+    WriteNumber(bond.PackIndex);

+    WriteNumber(bond.UnpackIndex);

   }

+  

   if (folder.PackStreams.Size() > 1)

     for (i = 0; i < folder.PackStreams.Size(); i++)

-    {

       WriteNumber(folder.PackStreams[i]);

-    }

 }

 

 void COutArchive::WriteBoolVector(const CBoolVector &boolVector)

@@ -521,7 +523,10 @@
   UInt64 unpackSize;

   RINOK(encoder.Encode(

       EXTERNAL_CODECS_LOC_VARS

-      stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))

+      stream,

+      // NULL,

+      &dataSize64,

+      folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))

   return S_OK;

 }

 

@@ -535,13 +540,13 @@
   */

   _useAlign = true;

 

-  unsigned i;

-  

-  UInt64 packedSize = 0;

-  for (i = 0; i < db.PackSizes.Size(); i++)

-    packedSize += db.PackSizes[i];

+  {

+    UInt64 packSize = 0;

+    FOR_VECTOR (i, db.PackSizes)

+      packSize += db.PackSizes[i];

+    headerOffset = packSize;

+  }

 

-  headerOffset = packedSize;

 

   WriteByte(NID::kHeader);

 

@@ -555,7 +560,7 @@
 

     CRecordVector<UInt64> unpackSizes;

     CUInt32DefVector digests;

-    for (i = 0; i < db.Files.Size(); i++)

+    FOR_VECTOR (i, db.Files)

     {

       const CFileItem &file = db.Files[i];

       if (!file.HasStream)

@@ -583,14 +588,17 @@
     CBoolVector emptyStreamVector;

     emptyStreamVector.ClearAndSetSize(db.Files.Size());

     unsigned numEmptyStreams = 0;

-    for (i = 0; i < db.Files.Size(); i++)

-      if (db.Files[i].HasStream)

-        emptyStreamVector[i] = false;

-      else

-      {

-        emptyStreamVector[i] = true;

-        numEmptyStreams++;

-      }

+    {

+      FOR_VECTOR (i, db.Files)

+        if (db.Files[i].HasStream)

+          emptyStreamVector[i] = false;

+        else

+        {

+          emptyStreamVector[i] = true;

+          numEmptyStreams++;

+        }

+    }

+

     if (numEmptyStreams != 0)

     {

       WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);

@@ -600,7 +608,8 @@
       antiVector.ClearAndSetSize(numEmptyStreams);

       bool thereAreEmptyFiles = false, thereAreAntiItems = false;

       unsigned cur = 0;

-      for (i = 0; i < db.Files.Size(); i++)

+      

+      FOR_VECTOR (i, db.Files)

       {

         const CFileItem &file = db.Files[i];

         if (file.HasStream)

@@ -667,17 +676,21 @@
     CBoolVector boolVector;

     boolVector.ClearAndSetSize(db.Files.Size());

     unsigned numDefined = 0;

-    for (i = 0; i < db.Files.Size(); i++)

+    

     {

-      bool defined = db.Files[i].AttribDefined;

-      boolVector[i] = defined;

-      if (defined)

-        numDefined++;

+      FOR_VECTOR (i, db.Files)

+      {

+        bool defined = db.Files[i].AttribDefined;

+        boolVector[i] = defined;

+        if (defined)

+          numDefined++;

+      }

     }

+    

     if (numDefined != 0)

     {

       WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);

-      for (i = 0; i < db.Files.Size(); i++)

+      FOR_VECTOR (i, db.Files)

       {

         const CFileItem &file = db.Files[i];

         if (file.AttribDefined)

diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index 07dbd63..86034f3 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -29,6 +29,8 @@
   }

   void WriteBytes(const void *data, size_t size)

   {

+    if (size == 0)

+      return;

     if (size > _size - _pos)

       throw 1;

     memcpy(_data + _pos, data, size);

@@ -92,7 +94,7 @@
   CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.

 

   CRecordVector<CNum> NumUnpackStreamsVector;

-  CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders

+  CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders

 

   void OutFoldersClear()

   {

diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
index 345c61b..388ac76 100644
--- a/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -13,8 +13,8 @@
 

 struct CPropMap

 {

-  UInt64 FilePropID;

-  STATPROPSTG StatPROPSTG;

+  UInt32 FilePropID;

+  CStatProp StatProp;

 };

 

 static const CPropMap kPropMap[] =

@@ -24,18 +24,18 @@
   { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },

   

   #ifdef _MULTI_PACK

-  { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },

-  { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },

-  { 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },

-  { 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },

-  { 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },

+  { 100, { "Pack0", kpidPackedSize0, VT_UI8 } },

+  { 101, { "Pack1", kpidPackedSize1, VT_UI8 } },

+  { 102, { "Pack2", kpidPackedSize2, VT_UI8 } },

+  { 103, { "Pack3", kpidPackedSize3, VT_UI8 } },

+  { 104, { "Pack4", kpidPackedSize4, VT_UI8 } },

   #endif

 

   { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },

   { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },

   { NID::kATime, { NULL, kpidATime, VT_FILETIME } },

   { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },

-  { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },

+  { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },

 

   { NID::kCRC, { NULL, kpidCRC, VT_UI4 } },

   

@@ -44,20 +44,12 @@
 

   #ifndef _SFX

   ,

-  { 97, { NULL,kpidEncrypted, VT_BOOL } },

-  { 98, { NULL,kpidMethod, VT_BSTR } },

-  { 99, { NULL,kpidBlock, VT_UI4 } }

+  { 97, { NULL, kpidEncrypted, VT_BOOL } },

+  { 98, { NULL, kpidMethod, VT_BSTR } },

+  { 99, { NULL, kpidBlock, VT_UI4 } }

   #endif

 };

 

-static int FindPropInMap(UInt64 filePropID)

-{

-  for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)

-    if (kPropMap[i].FilePropID == filePropID)

-      return i;

-  return -1;

-}

-

 static void CopyOneItem(CRecordVector<UInt64> &src,

     CRecordVector<UInt64> &dest, UInt32 item)

 {

@@ -98,7 +90,7 @@
   _fileInfoPopIDs.Clear();

 

   #ifdef _7Z_VOL

-  if(_volumes.Size() < 1)

+  if (_volumes.Size() < 1)

     return;

   const CVolume &volume = _volumes.Front();

   const CArchiveDatabaseEx &_db = volume.Database;

@@ -131,6 +123,7 @@
   _fileInfoPopIDs.Add(98);

   _fileInfoPopIDs.Add(99);

   #endif

+

   #ifdef _MULTI_PACK

   _fileInfoPopIDs.Add(100);

   _fileInfoPopIDs.Add(101);

@@ -155,16 +148,27 @@
 

 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)

 {

-  if ((int)index >= _fileInfoPopIDs.Size())

+  if (index >= _fileInfoPopIDs.Size())

     return E_INVALIDARG;

-  int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);

-  if (indexInMap == -1)

-    return E_INVALIDARG;

-  const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;

-  *propID = srcItem.propid;

-  *varType = srcItem.vt;

-  *name = 0;

-  return S_OK;

+  UInt64 id = _fileInfoPopIDs[index];

+  for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)

+  {

+    const CPropMap &pr = kPropMap[i];

+    if (pr.FilePropID == id)

+    {

+      const CStatProp &st = pr.StatProp;

+      *propID = st.PropID;

+      *varType = st.vt;

+      /*

+      if (st.lpwstrName)

+        *name = ::SysAllocString(st.lpwstrName);

+      else

+      */

+        *name = NULL;

+      return S_OK;

+    }

+  }

+  return E_INVALIDARG;

 }

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
index ae4e890..3e8cfb6 100644
--- a/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -9,17 +9,13 @@
 namespace NArchive {

 namespace N7z {

 

-IMP_CreateArcIn

-IMP_CreateArcOut

+static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};

 

-static CArcInfo g_ArcInfo =

-  { "7z", "7z", 0, 7,

-  6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},

+REGISTER_ARC_IO_DECREMENT_SIG(

+  "7z", "7z", NULL, 7,

+  k_Signature_Dec,

   0,

   NArcInfoFlags::kFindSignature,

-  REF_CreateArc_Pair };

-

-REGISTER_ARC_DEC_SIG(7z)

-// REGISTER_ARC(7z)

+  NULL);

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
index 0058ac2..0994128 100644
--- a/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -3,10 +3,10 @@
 #ifndef __7Z_SPEC_STREAM_H

 #define __7Z_SPEC_STREAM_H

 

-#include "../../IStream.h"

-#include "../../ICoder.h"

 #include "../../../Common/MyCom.h"

 

+#include "../../ICoder.h"

+

 class CSequentialInStreamSizeCount2:

   public ISequentialInStream,

   public ICompressGetSubStreamSize,

@@ -18,14 +18,14 @@
 public:

   void Init(ISequentialInStream *stream)

   {

-    _stream = stream;

-    _getSubStreamSize = 0;

-    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);

     _size = 0;

+    _getSubStreamSize.Release();

+    _stream = stream;

+    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);

   }

   UInt64 GetSize() const { return _size; }

 

-  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

+  MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)

 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

 

diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 87f3e0d..509a330 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -13,7 +13,6 @@
 #include "../../Compress/CopyCoder.h"

 

 #include "../Common/ItemNameUtils.h"

-#include "../Common/OutStreamWithCRC.h"

 

 #include "7zDecode.h"

 #include "7zEncode.h"

@@ -25,9 +24,396 @@
 namespace NArchive {

 namespace N7z {

 

-#ifdef MY_CPU_X86_OR_AMD64

-#define USE_86_FILTER

-#endif

+

+#define k_X86 k_BCJ

+

+struct CFilterMode

+{

+  UInt32 Id;

+  UInt32 Delta;

+

+  CFilterMode(): Id(0), Delta(0) {}

+

+  void SetDelta()

+  {

+    if (Id == k_IA64)

+      Delta = 16;

+    else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC)

+      Delta = 4;

+    else if (Id == k_ARMT)

+      Delta = 2;

+    else

+      Delta = 0;

+  }

+};

+

+

+/* ---------- PE ---------- */

+

+#define MZ_SIG 0x5A4D

+

+#define PE_SIG 0x00004550

+#define PE_OptHeader_Magic_32 0x10B

+#define PE_OptHeader_Magic_64 0x20B

+#define PE_SectHeaderSize 40

+#define PE_SECT_EXECUTE 0x20000000

+

+static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)

+{

+  if (size < 512 || GetUi16(buf) != MZ_SIG)

+    return 0;

+

+  const Byte *p;

+  UInt32 peOffset, optHeaderSize, filterId;

+

+  peOffset = GetUi32(buf + 0x3C);

+  if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)

+    return 0;

+  p = buf + peOffset;

+  if (GetUi32(p) != PE_SIG)

+    return 0;

+  p += 4;

+  

+  switch (GetUi16(p))

+  {

+    case 0x014C:

+    case 0x8664:  filterId = k_X86; break;

+    

+    /*

+    IMAGE_FILE_MACHINE_ARM   0x01C0  // ARM LE

+    IMAGE_FILE_MACHINE_THUMB 0x01C2  // ARM Thumb / Thumb-2 LE

+    IMAGE_FILE_MACHINE_ARMNT 0x01C4  // ARM Thumb-2, LE

+    Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).

+    */

+

+    case 0x01C0:                            // WinCE old

+    case 0x01C2:  filterId = k_ARM; break;  // WinCE new

+    case 0x01C4:  filterId = k_ARMT; break; // WinRT

+

+    case 0x0200:  filterId = k_IA64; break;

+    default:  return 0;

+  }

+

+  optHeaderSize = GetUi16(p + 16);

+  if (optHeaderSize > (1 << 10))

+    return 0;

+

+  p += 20; /* headerSize */

+

+  switch (GetUi16(p))

+  {

+    case PE_OptHeader_Magic_32:

+    case PE_OptHeader_Magic_64:

+      break;

+    default:

+      return 0;

+  }

+

+  filterMode->Id = filterId;

+  return 1;

+}

+

+

+/* ---------- ELF ---------- */

+

+#define ELF_SIG 0x464C457F

+

+#define ELF_CLASS_32  1

+#define ELF_CLASS_64  2

+

+#define ELF_DATA_2LSB 1

+#define ELF_DATA_2MSB 2

+

+static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }

+static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }

+// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); }

+

+static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)

+{

+  Bool /* is32, */ be;

+  UInt32 filterId;

+

+  if (size < 512 || buf[6] != 1) /* ver */

+    return 0;

+

+  if (GetUi32(buf) != ELF_SIG)

+    return 0;

+

+  switch (buf[4])

+  {

+    case ELF_CLASS_32: /* is32 = True; */ break;

+    case ELF_CLASS_64: /* is32 = False; */ break;

+    default: return 0;

+  }

+

+  switch (buf[5])

+  {

+    case ELF_DATA_2LSB: be = False; break;

+    case ELF_DATA_2MSB: be = True; break;

+    default: return 0;

+  }

+

+  switch (Get16(buf + 0x12, be))

+  {

+    case 3:

+    case 6:

+    case 62: filterId = k_X86; break;

+    case 2:

+    case 18:

+    case 43: filterId = k_SPARC; break;

+    case 20:

+    case 21: if (!be) return 0; filterId = k_PPC; break;

+    case 40: if ( be) return 0; filterId = k_ARM; break;

+    

+    /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes.

+       So we don't use IA-64 filter for IA-64 ELF */

+    // case 50: if ( be) return 0; filterId = k_IA64; break;

+

+    default: return 0;

+  }

+

+  filterMode->Id = filterId;

+  return 1;

+}

+

+

+

+/* ---------- Mach-O ---------- */

+

+#define MACH_SIG_BE_32 0xCEFAEDFE

+#define MACH_SIG_BE_64 0xCFFAEDFE

+#define MACH_SIG_LE_32 0xFEEDFACE

+#define MACH_SIG_LE_64 0xFEEDFACF

+

+#define MACH_ARCH_ABI64 (1 << 24)

+#define MACH_MACHINE_386 7

+#define MACH_MACHINE_ARM 12

+#define MACH_MACHINE_SPARC 14

+#define MACH_MACHINE_PPC 18

+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)

+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)

+

+static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)

+{

+  UInt32 filterId, numCommands, commandsSize;

+

+  if (size < 512)

+    return 0;

+

+  Bool /* mode64, */ be;

+  switch (GetUi32(buf))

+  {

+    case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;

+    case MACH_SIG_BE_64: /* mode64 = True;  */ be = True; break;

+    case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;

+    case MACH_SIG_LE_64: /* mode64 = True;  */ be = False; break;

+    default: return 0;

+  }

+

+  switch (Get32(buf + 4, be))

+  {

+    case MACH_MACHINE_386:

+    case MACH_MACHINE_AMD64: filterId = k_X86; break;

+    case MACH_MACHINE_ARM:   if ( be) return 0; filterId = k_ARM; break;

+    case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;

+    case MACH_MACHINE_PPC:

+    case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;

+    default: return 0;

+  }

+

+  numCommands = Get32(buf + 0x10, be);

+  commandsSize = Get32(buf + 0x14, be);

+

+  if (commandsSize > (1 << 24) || numCommands > (1 << 18))

+    return 0;

+

+  filterMode->Id = filterId;

+  return 1;

+}

+

+

+/* ---------- WAV ---------- */

+

+#define WAV_SUBCHUNK_fmt  0x20746D66

+#define WAV_SUBCHUNK_data 0x61746164

+

+#define RIFF_SIG 0x46464952

+

+static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)

+{

+  UInt32 subChunkSize, pos;

+  if (size < 0x2C)

+    return False;

+

+  if (GetUi32(buf + 0) != RIFF_SIG ||

+      GetUi32(buf + 8) != 0x45564157 || // WAVE

+      GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)

+    return False;

+  subChunkSize = GetUi32(buf + 0x10);

+  /* [0x14 = format] = 1 (PCM) */

+  if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)

+    return False;

+  

+  unsigned numChannels = GetUi16(buf + 0x16);

+  unsigned bitsPerSample = GetUi16(buf + 0x22);

+

+  if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256)

+    return False;

+

+  pos = 0x14 + subChunkSize;

+

+  const int kNumSubChunksTests = 10;

+  // Do we need to scan more than 3 sub-chunks?

+  for (int i = 0; i < kNumSubChunksTests; i++)

+  {

+    if (pos + 8 > size)

+      return False;

+    subChunkSize = GetUi32(buf + pos + 4);

+    if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)

+    {

+      unsigned delta = numChannels * (bitsPerSample >> 3);

+      if (delta >= 256)

+        return False;

+      filterMode->Id = k_Delta;

+      filterMode->Delta = delta;

+      return True;

+    }

+    if (subChunkSize > (1 << 16))

+      return False;

+    pos += subChunkSize + 8;

+  }

+  return False;

+}

+

+static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)

+{

+  filterMode->Id = 0;

+  filterMode->Delta = 0;

+

+  if (Parse_EXE(buf, size, filterMode)) return True;

+  if (Parse_ELF(buf, size, filterMode)) return True;

+  if (Parse_MACH(buf, size, filterMode)) return True;

+  return Parse_WAV(buf, size, filterMode);

+}

+

+

+

+

+struct CFilterMode2: public CFilterMode

+{

+  bool Encrypted;

+  unsigned GroupIndex;

+  

+  CFilterMode2(): Encrypted(false) {}

+

+  int Compare(const CFilterMode2 &m) const

+  {

+    if (!Encrypted)

+    {

+      if (m.Encrypted)

+        return -1;

+    }

+    else if (!m.Encrypted)

+      return 1;

+    

+    if (Id < m.Id) return -1;

+    if (Id > m.Id) return 1;

+

+    if (Delta < m.Delta) return -1;

+    if (Delta > m.Delta) return 1;

+

+    return 0;

+  }

+  

+  bool operator ==(const CFilterMode2 &m) const

+  {

+    return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted;

+  }

+};

+

+static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)

+{

+  unsigned i;

+  for (i = 0; i < filters.Size(); i++)

+  {

+    const CFilterMode2 &m2 = filters[i];

+    if (m == m2)

+      return i;

+    /*

+    if (m.Encrypted != m2.Encrypted)

+    {

+      if (!m.Encrypted)

+        break;

+      continue;

+    }

+    

+    if (m.Id < m2.Id)  break;

+    if (m.Id != m2.Id) continue;

+

+    if (m.Delta < m2.Delta) break;

+    if (m.Delta != m2.Delta) continue;

+    */

+  }

+  // filters.Insert(i, m);

+  // return i;

+  return filters.Add(m);

+}

+

+static inline bool Is86Filter(CMethodId m)

+{

+  return (m == k_BCJ || m == k_BCJ2);

+}

+

+static inline bool IsExeFilter(CMethodId m)

+{

+  switch (m)

+  {

+    case k_BCJ:

+    case k_BCJ2:

+    case k_ARM:

+    case k_ARMT:

+    case k_PPC:

+    case k_SPARC:

+    case k_IA64:

+      return true;

+  }

+  return false;

+}

+

+static unsigned Get_FilterGroup_for_Folder(

+    CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)

+{

+  CFilterMode2 m;

+  m.Id = 0;

+  m.Delta = 0;

+  m.Encrypted = f.IsEncrypted();

+

+  if (extractFilter)

+  {

+    const CCoderInfo &coder = f.Coders[f.UnpackCoder];

+  

+    if (coder.MethodID == k_Delta)

+    {

+      if (coder.Props.Size() == 1)

+      {

+        m.Delta = (unsigned)coder.Props[0] + 1;

+        m.Id = k_Delta;

+      }

+    }

+    else if (IsExeFilter(coder.MethodID))

+    {

+      m.Id = (UInt32)coder.MethodID;

+      if (m.Id == k_BCJ2)

+        m.Id = k_BCJ;

+      m.SetDelta();

+    }

+  }

+  

+  return GetGroup(filters, m);

+}

+

+

+

 

 static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,

     UInt64 position, UInt64 size, ICompressProgressInfo *progress)

@@ -44,21 +430,12 @@
   return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);

 }

 

-static int GetReverseSlashPos(const UString &name)

+/*

+unsigned CUpdateItem::GetExtensionPos() const

 {

-  int slashPos = name.ReverseFind(L'/');

-  #ifdef _WIN32

-  int slash1Pos = name.ReverseFind(L'\\');

-  slashPos = MyMax(slashPos, slash1Pos);

-  #endif

-  return slashPos;

-}

-

-int CUpdateItem::GetExtensionPos() const

-{

-  int slashPos = GetReverseSlashPos(Name);

-  int dotPos = Name.ReverseFind(L'.');

-  if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))

+  int slashPos = Name.ReverseFind_PathSepar();

+  int dotPos = Name.ReverseFind_Dot();

+  if (dotPos <= slashPos)

     return Name.Len();

   return dotPos + 1;

 }

@@ -67,6 +444,7 @@
 {

   return Name.Ptr(GetExtensionPos());

 }

+*/

 

 #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

 

@@ -91,7 +469,7 @@
   return CompareBuffers(c1.Props, c2.Props);

 }

 

-static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)

+static int CompareBonds(const CBond &b1, const CBond &b2)

 {

   RINOZ_COMP(b1.InIndex, b2.InIndex);

   return MyCompare(b1.OutIndex, b2.OutIndex);

@@ -105,11 +483,11 @@
   int i;

   for (i = 0; i < s1; i++)

     RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));

-  s1 = f1.BindPairs.Size();

-  s2 = f2.BindPairs.Size();

+  s1 = f1.Bonds.Size();

+  s2 = f2.Bonds.Size();

   RINOZ_COMP(s1, s2);

   for (i = 0; i < s1; i++)

-    RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));

+    RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));

   return 0;

 }

 */

@@ -123,36 +501,34 @@
 

 struct CFolderRepack

 {

-  int FolderIndex;

-  int Group;

+  unsigned FolderIndex;

   CNum NumCopyFiles;

 };

 

-static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)

+/*

+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)

 {

-  RINOZ_COMP(p1->Group, p2->Group);

   int i1 = p1->FolderIndex;

   int i2 = p2->FolderIndex;

-  /*

   // In that version we don't want to parse folders here, so we don't compare folders

   // probably it must be improved in future

-  const CDbEx &db = *(const CDbEx *)param;

-  RINOZ(CompareFolders(

-      db.Folders[i1],

-      db.Folders[i2]));

-  */

+  // const CDbEx &db = *(const CDbEx *)param;

+  // RINOZ(CompareFolders(

+  //     db.Folders[i1],

+  //     db.Folders[i2]));

+

   return MyCompare(i1, i2);

-  /*

-  RINOZ_COMP(

-      db.NumUnpackStreamsVector[i1],

-      db.NumUnpackStreamsVector[i2]);

-  if (db.NumUnpackStreamsVector[i1] == 0)

-    return 0;

-  return CompareFiles(

-      db.Files[db.FolderStartFileIndex[i1]],

-      db.Files[db.FolderStartFileIndex[i2]]);

-  */

+  

+  // RINOZ_COMP(

+  //     db.NumUnpackStreamsVector[i1],

+  //     db.NumUnpackStreamsVector[i2]);

+  // if (db.NumUnpackStreamsVector[i1] == 0)

+  //   return 0;

+  // return CompareFiles(

+  //     db.Files[db.FolderStartFileIndex[i1]],

+  //     db.Files[db.FolderStartFileIndex[i2]]);

 }

+*/

 

 /*

   we sort empty files and dirs in such order:

@@ -162,7 +538,7 @@
   - Dir.Anti (reverse name sorted)

 */

 

-static int CompareEmptyItems(const int *p1, const int *p2, void *param)

+static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)

 {

   const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;

   const CUpdateItem &u1 = updateItems[*p1];

@@ -182,11 +558,11 @@
 }

 

 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"

@@ -195,25 +571,28 @@
   " iso bin nrg mdf img pdi tar cpio xpi"

   " vfd vhd vud vmc vsv"

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

+  " inl inc idl acf asa"

+  " h hpp hxx c cpp cxx m mm go swift"

+  " rc java cs rs pas bas vb cls ctl frm dlg def"

   " f77 f f90 f95"

-  " asm sql manifest dep "

-  " mak clw csproj vcproj sln dsp dsw "

-  " class "

-  " bat cmd"

+  " asm s"

+  " sql manifest dep"

+  " mak clw csproj vcproj sln dsp dsw"

+  " class"

+  " bat cmd bash sh"

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

+  " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"

   " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"

   " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"

   " 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 int GetExtIndex(const char *ext)

+static unsigned GetExtIndex(const char *ext)

 {

-  int extIndex = 1;

+  unsigned extIndex = 1;

   const char *p = g_Exts;

   for (;;)

   {

@@ -222,7 +601,7 @@
       return extIndex;

     if (c == ' ')

       continue;

-    int pos = 0;

+    unsigned pos = 0;

     for (;;)

     {

       char c2 = ext[pos++];

@@ -248,8 +627,8 @@
 {

   const CUpdateItem *UpdateItem;

   UInt32 Index;

-  UInt32 ExtensionPos;

-  UInt32 NamePos;

+  unsigned ExtensionPos;

+  unsigned NamePos;

   unsigned ExtensionIndex;

   

   CRefItem() {};

@@ -262,10 +641,10 @@
   {

     if (sortByType)

     {

-      int slashPos = GetReverseSlashPos(ui.Name);

+      int slashPos = ui.Name.ReverseFind_PathSepar();

       NamePos = slashPos + 1;

-      int dotPos = ui.Name.ReverseFind(L'.');

-      if (dotPos < 0 || dotPos < slashPos)

+      int dotPos = ui.Name.ReverseFind_Dot();

+      if (dotPos <= slashPos)

         ExtensionPos = ui.Name.Len();

       else

       {

@@ -396,35 +775,193 @@
 struct CSolidGroup

 {

   CRecordVector<UInt32> Indices;

+

+  CRecordVector<CFolderRepack> folderRefs;

 };

 

-static const wchar_t *g_ExeExts[] =

+static const char * const g_ExeExts[] =

 {

-    L"dll"

-  , L"exe"

-  , L"ocx"

-  , L"sfx"

-  , L"sys"

+    "dll"

+  , "exe"

+  , "ocx"

+  , "sfx"

+  , "sys"

 };

 

 static bool IsExeExt(const wchar_t *ext)

 {

-  for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)

-    if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)

+  for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++)

+    if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i]))

       return true;

   return false;

 }

 

-

-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)

+struct CAnalysis

 {

-  m.Id = methodID;

-  m.NumInStreams = numInStreams;

-  m.NumOutStreams = 1;

+  CMyComPtr<IArchiveUpdateCallbackFile> Callback;

+  CByteBuffer Buffer;

+

+  bool ParseWav;

+  bool ParseExe;

+  bool ParseAll;

+

+  CAnalysis():

+      ParseWav(true),

+      ParseExe(false),

+      ParseAll(false)

+  {}

+

+  HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);

+};

+

+static const size_t kAnalysisBufSize = 1 << 14;

+

+HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)

+{

+  filterMode.Id = 0;

+  filterMode.Delta = 0;

+

+  CFilterMode filterModeTemp = filterMode;

+

+  int slashPos = ui.Name.ReverseFind_PathSepar();

+  int dotPos = ui.Name.ReverseFind_Dot();

+

+  // if (dotPos > slashPos)

+  {

+    bool needReadFile = ParseAll;

+

+    bool probablyIsSameIsa = false;

+

+    if (!needReadFile || !Callback)

+    {

+      const wchar_t *ext;

+      if (dotPos > slashPos)

+        ext = ui.Name.Ptr(dotPos + 1);

+      else

+        ext = ui.Name.RightPtr(0);

+      

+      // p7zip uses the trick to store posix attributes in high 16 bits

+      if (ui.Attrib & 0x8000)

+      {

+        unsigned st_mode = ui.Attrib >> 16;

+        // st_mode = 00111;

+        if ((st_mode & 00111) && (ui.Size >= 2048))

+        {

+          #ifndef _WIN32

+          probablyIsSameIsa = true;

+          #endif

+          needReadFile = true;

+        }

+      }

+

+      if (IsExeExt(ext))

+      {

+        needReadFile = true;

+        #ifdef _WIN32

+        probablyIsSameIsa = true;

+        needReadFile = ParseExe;

+        #endif

+      }

+      else if (StringsAreEqualNoCase_Ascii(ext, "wav"))

+      {

+        needReadFile = ParseWav;

+      }

+      /*

+      else if (!needReadFile && ParseUnixExt)

+      {

+        if (StringsAreEqualNoCase_Ascii(ext, "so")

+          || StringsAreEqualNoCase_Ascii(ext, ""))

+          

+          needReadFile = true;

+      }

+      */

+    }

+

+    if (needReadFile && Callback)

+    {

+      if (Buffer.Size() != kAnalysisBufSize)

+      {

+        Buffer.Alloc(kAnalysisBufSize);

+      }

+      {

+        CMyComPtr<ISequentialInStream> stream;

+        HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);

+        if (result == S_OK && stream)

+        {

+          size_t size = kAnalysisBufSize;

+          result = ReadStream(stream, Buffer, &size);

+          stream.Release();

+          // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));

+          if (result == S_OK)

+          {

+            Bool parseRes = ParseFile(Buffer, size, &filterModeTemp);

+            if (parseRes && filterModeTemp.Delta == 0)

+            {

+              filterModeTemp.SetDelta();

+              if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta)

+              {

+                if (ui.Size % filterModeTemp.Delta != 0)

+                {

+                  parseRes = false;

+                }

+              }

+            }

+            if (!parseRes)

+            {

+              filterModeTemp.Id = 0;

+              filterModeTemp.Delta = 0;

+            }

+          }

+        }

+      }

+    }

+    else if ((needReadFile && !Callback) || probablyIsSameIsa)

+    {

+      #ifdef MY_CPU_X86_OR_AMD64

+      if (probablyIsSameIsa)

+        filterModeTemp.Id = k_X86;

+      #endif

+    }

+  }

+  

+  filterMode = filterModeTemp;

+  return S_OK;

 }

 

-static void AddBcj2Methods(CCompressionMethodMode &mode)

+static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)

 {

+  m.Id = methodID;

+  m.NumStreams = numStreams;

+}

+

+static HRESULT AddBondForFilter(CCompressionMethodMode &mode)

+{

+  for (unsigned c = 1; c < mode.Methods.Size(); c++)

+  {

+    if (!mode.IsThereBond_to_Coder(c))

+    {

+      CBond2 bond;

+      bond.OutCoder = 0;

+      bond.OutStream = 0;

+      bond.InCoder = c;

+      mode.Bonds.Add(bond);

+      return S_OK;

+    }

+  }

+  return E_INVALIDARG;

+}

+

+static HRESULT AddFilterBond(CCompressionMethodMode &mode)

+{

+  if (!mode.Bonds.IsEmpty())

+    return AddBondForFilter(mode);

+  return S_OK;

+}

+

+static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)

+{

+  // mode.Methods[0] must be k_BCJ2 method !

+

   CMethodFull m;

   GetMethodFull(k_LZMA, 1, m);

   

@@ -433,54 +970,121 @@
   m.AddProp32(NCoderPropID::kNumThreads, 1);

   m.AddProp32(NCoderPropID::kLitPosBits, 2);

   m.AddProp32(NCoderPropID::kLitContextBits, 0);

-  // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");

+  // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");

+

+  unsigned methodIndex = mode.Methods.Size();

+

+  if (mode.Bonds.IsEmpty())

+  {

+    for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)

+    {

+      CBond2 bond;

+      bond.OutCoder = i;

+      bond.OutStream = 0;

+      bond.InCoder = i + 1;

+      mode.Bonds.Add(bond);

+    }

+  }

 

   mode.Methods.Add(m);

   mode.Methods.Add(m);

   

-  CBind bind;

-  bind.OutCoder = 0;

-  bind.InStream = 0;

-  bind.InCoder = 1;  bind.OutStream = 0;  mode.Binds.Add(bind);

-  bind.InCoder = 2;  bind.OutStream = 1;  mode.Binds.Add(bind);

-  bind.InCoder = 3;  bind.OutStream = 2;  mode.Binds.Add(bind);

+  RINOK(AddBondForFilter(mode));

+  CBond2 bond;

+  bond.OutCoder = 0;

+  bond.InCoder = methodIndex;      bond.OutStream = 1;  mode.Bonds.Add(bond);

+  bond.InCoder = methodIndex + 1;  bond.OutStream = 2;  mode.Bonds.Add(bond);

+  return S_OK;

 }

 

-static void MakeExeMethod(CCompressionMethodMode &mode,

-    bool useFilters, bool addFilter, bool bcj2Filter)

+static HRESULT MakeExeMethod(CCompressionMethodMode &mode,

+    const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter)

 {

-  if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)

-    return;

-  if (mode.Methods.Size() == 2)

+  if (mode.Filter_was_Inserted)

   {

-    if (mode.Methods[0].Id == k_BCJ2)

-      AddBcj2Methods(mode);

-    return;

+    const CMethodFull &m = mode.Methods[0];

+    CMethodId id = m.Id;

+    if (id == k_BCJ2)

+      return AddBcj2Methods(mode);

+    if (!m.IsSimpleCoder())

+      return E_NOTIMPL;

+    // if (Bonds.IsEmpty()) we can create bonds later

+    return AddFilterBond(mode);

   }

-  if (!addFilter)

-    return;

-  bcj2Filter = bcj2Filter;

-  #ifdef USE_86_FILTER

-  if (bcj2Filter)

+

+  if (filterMode.Id == 0)

+    return S_OK;

+

+  CMethodFull &m = mode.Methods.InsertNew(0);

+

   {

-    CMethodFull m;

+    FOR_VECTOR(k, mode.Bonds)

+    {

+      CBond2 &bond = mode.Bonds[k];

+      bond.InCoder++;

+      bond.OutCoder++;

+    }

+  }

+

+  HRESULT res;

+  

+  if (bcj2Filter && Is86Filter(filterMode.Id))

+  {

     GetMethodFull(k_BCJ2, 4, m);

-    mode.Methods.Insert(0, m);

-    AddBcj2Methods(mode);

+    res = AddBcj2Methods(mode);

   }

   else

   {

-    CMethodFull m;

-    GetMethodFull(k_BCJ, 1, m);

-    mode.Methods.Insert(0, m);

-    CBind bind;

-    bind.OutCoder = 0;

-    bind.InStream = 0;

-    bind.InCoder = 1;

-    bind.OutStream = 0;

-    mode.Binds.Add(bind);

+    GetMethodFull(filterMode.Id, 1, m);

+    if (filterMode.Id == k_Delta)

+      m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);

+    res = AddFilterBond(mode);

+

+    int alignBits = -1;

+    if (filterMode.Id == k_Delta || filterMode.Delta != 0)

+    {

+           if (filterMode.Delta == 1) alignBits = 0;

+      else if (filterMode.Delta == 2) alignBits = 1;

+      else if (filterMode.Delta == 4) alignBits = 2;

+      else if (filterMode.Delta == 8) alignBits = 3;

+      else if (filterMode.Delta == 16) alignBits = 4;

+    }

+    else

+    {

+      // alignBits = GetAlignForFilterMethod(filterMode.Id);

+    }

+    

+    if (res == S_OK && alignBits >= 0)

+    {

+      unsigned nextCoder = 1;

+      if (!mode.Bonds.IsEmpty())

+      {

+        nextCoder = mode.Bonds.Back().InCoder;

+      }

+      if (nextCoder < mode.Methods.Size())

+      {

+        CMethodFull &nextMethod = mode.Methods[nextCoder];

+        if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)

+        {

+          if (!nextMethod.Are_Lzma_Model_Props_Defined())

+          {

+            if (alignBits != 0)

+            {

+              if (alignBits > 2 || filterMode.Id == k_Delta)

+                nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits);

+              unsigned lc = 0;

+              if (alignBits < 3)

+                lc = 3 - alignBits;

+              nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);

+              nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits);

+            }

+          }

+        }

+      }

+    }

   }

-  #endif

+

+  return res;

 }

 

 

@@ -503,133 +1107,336 @@
   // file.IsAltStream = ui.IsAltStream;

 }

 

+class CRepackInStreamWithSizes:

+  public ISequentialInStream,

+  public ICompressGetSubStreamSize,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialInStream> _stream;

+  // UInt64 _size;

+  const CBoolVector *_extractStatuses;

+  UInt32 _startIndex;

+public:

+  const CDbEx *_db;

+

+  void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)

+  {

+    _startIndex = startIndex;

+    _extractStatuses = extractStatuses;

+    // _size = 0;

+    _stream = stream;

+  }

+  // UInt64 GetSize() const { return _size; }

+

+  MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+

+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

+};

+

+STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  return _stream->Read(data, size, processedSize);

+  /*

+  UInt32 realProcessedSize;

+  HRESULT result = _stream->Read(data, size, &realProcessedSize);

+  _size += realProcessedSize;

+  if (processedSize)

+    *processedSize = realProcessedSize;

+  return result;

+  */

+}

+

+STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)

+{

+  *value = 0;

+  if (subStream >= _extractStatuses->Size())

+    return S_FALSE; // E_FAIL;

+  unsigned index = (unsigned)subStream;

+  if ((*_extractStatuses)[index])

+  {

+    const CFileItem &fi = _db->Files[_startIndex + index];

+    if (fi.HasStream)

+      *value = fi.Size;

+  }

+  return S_OK;

+}

+

+

+class CRepackStreamBase

+{

+protected:

+  bool _needWrite;

+  bool _fileIsOpen;

+  bool _calcCrc;

+  UInt32 _crc;

+  UInt64 _rem;

+

+  const CBoolVector *_extractStatuses;

+  UInt32 _startIndex;

+  unsigned _currentIndex;

+

+  HRESULT OpenFile();

+  HRESULT CloseFile();

+  HRESULT ProcessEmptyFiles();

+

+public:

+  const CDbEx *_db;

+  CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;

+  CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback;

+

+  HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);

+  HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }

+};

+

+HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)

+{

+  _startIndex = startIndex;

+  _extractStatuses = extractStatuses;

+

+  _currentIndex = 0;

+  _fileIsOpen = false;

+  

+  return ProcessEmptyFiles();

+}

+

+HRESULT CRepackStreamBase::OpenFile()

+{

+  UInt32 arcIndex = _startIndex + _currentIndex;

+  const CFileItem &fi = _db->Files[arcIndex];

+  

+  _needWrite = (*_extractStatuses)[_currentIndex];

+  if (_opCallback)

+  {

+    RINOK(_opCallback->ReportOperation(

+        NEventIndexType::kInArcIndex, arcIndex,

+        _needWrite ?

+            NUpdateNotifyOp::kRepack :

+            NUpdateNotifyOp::kSkip));

+  }

+

+  _crc = CRC_INIT_VAL;

+  _calcCrc = (fi.CrcDefined && !fi.IsDir);

+

+  _fileIsOpen = true;

+  _rem = fi.Size;

+  return S_OK;

+}

+

+const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;

+

+HRESULT CRepackStreamBase::CloseFile()

+{

+  UInt32 arcIndex = _startIndex + _currentIndex;

+  const CFileItem &fi = _db->Files[arcIndex];

+  _fileIsOpen = false;

+  _currentIndex++;

+  if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))

+    return S_OK;

+

+  if (_extractCallback)

+  {

+    RINOK(_extractCallback->ReportExtractResult(

+        NEventIndexType::kInArcIndex, arcIndex,

+        NExtract::NOperationResult::kCRCError));

+  }

+  // return S_FALSE;

+  return k_My_HRESULT_CRC_ERROR;

+}

+

+HRESULT CRepackStreamBase::ProcessEmptyFiles()

+{

+  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)

+  {

+    RINOK(OpenFile());

+    RINOK(CloseFile());

+  }

+  return S_OK;

+}

+  

+

+

+#ifndef _7ZIP_ST

+

 class CFolderOutStream2:

+  public CRepackStreamBase,

   public ISequentialOutStream,

   public CMyUnknownImp

 {

-  COutStreamWithCRC *_crcStreamSpec;

-  CMyComPtr<ISequentialOutStream> _crcStream;

-  const CDbEx *_db;

-  const CBoolVector *_extractStatuses;

-  CMyComPtr<ISequentialOutStream> _outStream;

-  UInt32 _startIndex;

-  unsigned _currentIndex;

-  bool _fileIsOpen;

-  UInt64 _rem;

-

-  void OpenFile();

-  void CloseFile();

-  HRESULT CloseFileAndSetResult();

-  HRESULT ProcessEmptyFiles();

 public:

-  MY_UNKNOWN_IMP

-  

-  CFolderOutStream2()

-  {

-    _crcStreamSpec = new COutStreamWithCRC;

-    _crcStream = _crcStreamSpec;

-  }

+  CMyComPtr<ISequentialOutStream> _stream;

 

-  HRESULT Init(const CDbEx *db, UInt32 startIndex,

-      const CBoolVector *extractStatuses, ISequentialOutStream *outStream);

-  void ReleaseOutStream();

-  HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }

+  MY_UNKNOWN_IMP

 

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

-HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,

-    const CBoolVector *extractStatuses, ISequentialOutStream *outStream)

-{

-  _db = db;

-  _startIndex = startIndex;

-  _extractStatuses = extractStatuses;

-  _outStream = outStream;

-

-  _currentIndex = 0;

-  _fileIsOpen = false;

-  return ProcessEmptyFiles();

-}

-

-void CFolderOutStream2::ReleaseOutStream()

-{

-  _outStream.Release();

-  _crcStreamSpec->ReleaseStream();

-}

-

-void CFolderOutStream2::OpenFile()

-{

-  _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);

-  _crcStreamSpec->Init(true);

-  _fileIsOpen = true;

-  _rem = _db->Files[_startIndex + _currentIndex].Size;

-}

-

-void CFolderOutStream2::CloseFile()

-{

-  _crcStreamSpec->ReleaseStream();

-  _fileIsOpen = false;

-  _currentIndex++;

-}

-

-HRESULT CFolderOutStream2::CloseFileAndSetResult()

-{

-  const CFileItem &file = _db->Files[_startIndex + _currentIndex];

-  CloseFile();

-  return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;

-}

-

-HRESULT CFolderOutStream2::ProcessEmptyFiles()

-{

-  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)

-  {

-    OpenFile();

-    RINOK(CloseFileAndSetResult());

-  }

-  return S_OK;

-}

-

 STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

+  

   while (size != 0)

   {

     if (_fileIsOpen)

     {

-      UInt32 cur = size < _rem ? size : (UInt32)_rem;

-      RINOK(_crcStream->Write(data, cur, &cur));

-      if (cur == 0)

-        break;

+      UInt32 cur = (size < _rem ? size : (UInt32)_rem);

+      HRESULT result = S_OK;

+      if (_needWrite)

+        result = _stream->Write(data, cur, &cur);

+      if (_calcCrc)

+        _crc = CrcUpdate(_crc, data, cur);

+      if (processedSize)

+        *processedSize += cur;

       data = (const Byte *)data + cur;

       size -= cur;

       _rem -= cur;

-      if (processedSize != NULL)

-        *processedSize += cur;

       if (_rem == 0)

       {

-        RINOK(CloseFileAndSetResult());

+        RINOK(CloseFile());

         RINOK(ProcessEmptyFiles());

-        continue;

       }

+      RINOK(result);

+      if (cur == 0)

+        break;

+      continue;

     }

-    else

+

+    RINOK(ProcessEmptyFiles());

+    if (_currentIndex == _extractStatuses->Size())

     {

-      RINOK(ProcessEmptyFiles());

-      if (_currentIndex == _extractStatuses->Size())

-      {

-        // we don't support partial extracting

-        return E_FAIL;

-      }

-      OpenFile();

+      // we don't support write cut here

+      return E_FAIL;

     }

+    RINOK(OpenFile());

   }

+

   return S_OK;

 }

 

-class CThreadDecoder: public CVirtThread

+#endif

+

+

+

+static const UInt32 kTempBufSize = 1 << 16;

+

+class CFolderInStream2:

+  public CRepackStreamBase,

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  Byte *_buf;

+public:

+  CMyComPtr<ISequentialInStream> _inStream;

+  HRESULT Result;

+

+  MY_UNKNOWN_IMP

+

+  CFolderInStream2():

+      Result(S_OK)

+  {

+    _buf = new Byte[kTempBufSize];

+  }

+

+  ~CFolderInStream2()

+  {

+    delete []_buf;

+  }

+

+  void Init() { Result = S_OK; }

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  

+  while (size != 0)

+  {

+    if (_fileIsOpen)

+    {

+      UInt32 cur = (size < _rem ? size : (UInt32)_rem);

+      

+      void *buf;

+      if (_needWrite)

+        buf = data;

+      else

+      {

+        buf = _buf;

+        if (cur > kTempBufSize)

+          cur = kTempBufSize;

+      }

+

+      HRESULT result = _inStream->Read(buf, cur, &cur);

+      _crc = CrcUpdate(_crc, buf, cur);

+      _rem -= cur;

+

+      if (_needWrite)

+      {

+        data = (Byte *)data + cur;

+        size -= cur;

+        if (processedSize)

+          *processedSize += cur;

+      }

+

+      if (result != S_OK)

+        Result = result;

+

+      if (_rem == 0)

+      {

+        RINOK(CloseFile());

+        RINOK(ProcessEmptyFiles());

+      }

+

+      RINOK(result);

+      

+      if (cur == 0)

+        return E_FAIL;

+

+      continue;

+    }

+

+    RINOK(ProcessEmptyFiles());

+    if (_currentIndex == _extractStatuses->Size())

+    {

+      return S_OK;

+    }

+    RINOK(OpenFile());

+  }

+  

+  return S_OK;

+}

+

+

+class CThreadDecoder

+  #ifndef _7ZIP_ST

+    : public CVirtThread

+  #endif

 {

 public:

+  CDecoder Decoder;

+

+  CThreadDecoder(bool multiThreadMixer):

+      Decoder(multiThreadMixer)

+  {

+    #ifndef _7ZIP_ST

+    if (multiThreadMixer)

+    {

+      MtMode = false;

+      NumThreads = 1;

+      FosSpec = new CFolderOutStream2;

+      Fos = FosSpec;

+      Result = E_FAIL;

+    }

+    #endif

+    // UnpackSize = 0;

+    // send_UnpackSize = false;

+  }

+

+  #ifndef _7ZIP_ST

+  

   HRESULT Result;

   CMyComPtr<IInStream> InStream;

 

@@ -639,33 +1446,30 @@
   UInt64 StartPos;

   const CFolders *Folders;

   int FolderIndex;

+

+  // bool send_UnpackSize;

+  // UInt64 UnpackSize;

+  

   #ifndef _NO_CRYPTO

   CMyComPtr<ICryptoGetTextPassword> getTextPassword;

   #endif

 

   DECL_EXTERNAL_CODECS_LOC_VARS2;

-  CDecoder Decoder;

 

   #ifndef _7ZIP_ST

   bool MtMode;

   UInt32 NumThreads;

   #endif

 

-  CThreadDecoder():

-    Decoder(true)

-  {

-    #ifndef _7ZIP_ST

-    MtMode = false;

-    NumThreads = 1;

-    #endif

-    FosSpec = new CFolderOutStream2;

-    Fos = FosSpec;

-    Result = E_FAIL;

-  }

+  

   ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }

   virtual void Execute();

+

+  #endif

 };

 

+#ifndef _7ZIP_ST

+

 void CThreadDecoder::Execute()

 {

   try

@@ -673,6 +1477,7 @@
     #ifndef _NO_CRYPTO

       bool isEncrypted = false;

       bool passwordIsDefined = false;

+      UString password;

     #endif

     

     Result = Decoder.Decode(

@@ -680,8 +1485,14 @@
       InStream,

       StartPos,

       *Folders, FolderIndex,

+      

+      // send_UnpackSize ? &UnpackSize : NULL,

+      NULL, // unpackSize : FULL unpack

+      

       Fos,

-      NULL

+      NULL, // compressProgress

+      NULL  // *inStreamMainRes

+

       _7Z_DECODER_CRYPRO_VARS

       #ifndef _7ZIP_ST

         , MtMode, NumThreads

@@ -692,21 +1503,15 @@
   {

     Result = E_FAIL;

   }

+  

+  /*

   if (Result == S_OK)

     Result = FosSpec->CheckFinishedState();

-  FosSpec->ReleaseOutStream();

+  */

+  FosSpec->_stream.Release();

 }

 

-bool static Is86FilteredFolder(const CFolder &f)

-{

-  FOR_VECTOR(i, f.Coders)

-  {

-    CMethodId m = f.Coders[i].MethodID;

-    if (m == k_BCJ || m == k_BCJ2)

-      return true;

-  }

-  return false;

-}

+#endif

 

 #ifndef _NO_CRYPTO

 

@@ -728,14 +1533,8 @@
 

 #endif

 

-static const int kNumGroupsMax = 4;

 

-static bool Is86Group(int group) { return (group & 1) != 0; }

-static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }

-static int GetGroupIndex(bool encrypted, int bcjFiltered)

-  { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }

-

-static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2)

+static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)

 {

   file = inDb.Files[index];

   file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);

@@ -767,6 +1566,12 @@
   if (numSolidFiles == 0)

     numSolidFiles = 1;

 

+  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;

+  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);

+

+  CMyComPtr<IArchiveExtractCallbackMessage> extractCallback;

+  updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback);

+

   // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();

 

   /*

@@ -776,21 +1581,39 @@
     return E_NOTIMPL;

   */

 

-  UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0;

+  UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0;

   if (startBlockSize > 0 && !options.RemoveSfxBlock)

   {

     RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));

   }

 

   CIntArr fileIndexToUpdateIndexMap;

-  CRecordVector<CFolderRepack> folderRefs;

   UInt64 complexity = 0;

   UInt64 inSizeForReduce2 = 0;

   bool needEncryptedRepack = false;

-  if (db != 0)

+

+  CRecordVector<CFilterMode2> filters;

+  CObjectVector<CSolidGroup> groups;

+  bool thereAreRepacks = false;

+

+  bool useFilters = options.UseFilters;

+  if (useFilters)

+  {

+    const CCompressionMethodMode &method = *options.Method;

+

+    FOR_VECTOR (i, method.Methods)

+      if (IsFilterMethod(method.Methods[i].Id))

+      {

+        useFilters = false;

+        break;

+      }

+  }

+  

+  if (db)

   {

     fileIndexToUpdateIndexMap.Alloc(db->Files.Size());

     unsigned i;

+    

     for (i = 0; i < db->Files.Size(); i++)

       fileIndexToUpdateIndexMap[i] = -1;

 

@@ -798,15 +1621,16 @@
     {

       int index = updateItems[i].IndexInArchive;

       if (index != -1)

-        fileIndexToUpdateIndexMap[index] = i;

+        fileIndexToUpdateIndexMap[(unsigned)index] = i;

     }

 

-    for (i = 0; i < (int)db->NumFolders; i++)

+    for (i = 0; i < db->NumFolders; i++)

     {

       CNum indexInFolder = 0;

       CNum numCopyItems = 0;

       CNum numUnpackStreams = db->NumUnpackStreamsVector[i];

       UInt64 repackSize = 0;

+      

       for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)

       {

         const CFileItem &file = db->Files[fi];

@@ -828,41 +1652,51 @@
       CFolderRepack rep;

       rep.FolderIndex = i;

       rep.NumCopyFiles = numCopyItems;

-      CFolder f;

-      db->ParseFolderInfo(i, f);

-      bool isEncrypted = f.IsEncrypted();

-      rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));

-      folderRefs.Add(rep);

-      if (numCopyItems == numUnpackStreams)

+      CFolderEx f;

+      db->ParseFolderEx(i, f);

+

+      const bool isEncrypted = f.IsEncrypted();

+      const bool needCopy = (numCopyItems == numUnpackStreams);

+      const bool extractFilter = (useFilters || needCopy);

+

+      unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);

+      

+      while (groupIndex >= groups.Size())

+        groups.AddNew();

+

+      groups[groupIndex].folderRefs.Add(rep);

+      

+      if (needCopy)

         complexity += db->GetFolderFullPackSize(i);

       else

       {

+        thereAreRepacks = true;

         complexity += repackSize;

-        if (repackSize > inSizeForReduce2)

+        if (inSizeForReduce2 < repackSize)

           inSizeForReduce2 = repackSize;

         if (isEncrypted)

           needEncryptedRepack = true;

       }

     }

-    folderRefs.Sort(CompareFolderRepacks, (void *)db);

   }

 

   UInt64 inSizeForReduce = 0;

-  unsigned i;

-  for (i = 0; i < updateItems.Size(); i++)

   {

-    const CUpdateItem &ui = updateItems[i];

-    if (ui.NewData)

+    FOR_VECTOR (i, updateItems)

     {

-      complexity += ui.Size;

-      if (numSolidFiles != 1)

-        inSizeForReduce += ui.Size;

-      else if (ui.Size > inSizeForReduce)

-        inSizeForReduce = ui.Size;

+      const CUpdateItem &ui = updateItems[i];

+      if (ui.NewData)

+      {

+        complexity += ui.Size;

+        if (numSolidFiles != 1)

+          inSizeForReduce += ui.Size;

+        else if (inSizeForReduce < ui.Size)

+          inSizeForReduce = ui.Size;

+      }

     }

   }

 

-  if (inSizeForReduce2 > inSizeForReduce)

+  if (inSizeForReduce < inSizeForReduce2)

     inSizeForReduce = inSizeForReduce2;

 

   RINOK(updateCallback->SetTotal(complexity));

@@ -871,52 +1705,88 @@
   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(updateCallback, true);

 

+  #ifndef _7ZIP_ST

+  

   CStreamBinder sb;

-  RINOK(sb.CreateEvents());

+  if (options.MultiThreadMixer)

+  {

+    RINOK(sb.CreateEvents());

+  }

+  

+  #endif

 

-  CThreadDecoder threadDecoder;

-  if (!folderRefs.IsEmpty())

+  CThreadDecoder threadDecoder(options.MultiThreadMixer);

+  

+  #ifndef _7ZIP_ST

+  if (options.MultiThreadMixer && thereAreRepacks)

   {

     #ifdef EXTERNAL_CODECS

     threadDecoder.__externalCodecs = __externalCodecs;

     #endif

     RINOK(threadDecoder.Create());

   }

-

-  CObjectVector<CSolidGroup> groups;

-  for (i = 0; i < kNumGroupsMax; i++)

-    groups.AddNew();

+  #endif

 

   {

+    CAnalysis analysis;

+    if (options.AnalysisLevel == 0)

+    {

+      analysis.ParseWav = false;

+      analysis.ParseExe = false;

+      analysis.ParseAll = false;

+    }

+    else

+    {

+      analysis.Callback = opCallback;

+      if (options.AnalysisLevel > 0)

+      {

+        analysis.ParseWav = true;

+        if (options.AnalysisLevel >= 7)

+        {

+          analysis.ParseExe = true;

+          if (options.AnalysisLevel >= 9)

+            analysis.ParseAll = true;

+        }

+      }

+    }

+

     // ---------- Split files to groups ----------

 

-    bool useFilters = options.UseFilters;

     const CCompressionMethodMode &method = *options.Method;

-    if (method.Methods.Size() != 1 || method.Binds.Size() != 0)

-      useFilters = false;

-    for (i = 0; i < updateItems.Size(); i++)

+    

+    FOR_VECTOR (i, updateItems)

     {

       const CUpdateItem &ui = updateItems[i];

       if (!ui.NewData || !ui.HasStream())

         continue;

-      bool filteredGroup = false;

+

+      CFilterMode2 fm;

       if (useFilters)

       {

-        int dotPos = ui.Name.ReverseFind(L'.');

-        if (dotPos >= 0)

-          filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));

+        RINOK(analysis.GetFilterGroup(i, ui, fm));

       }

-      groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);

+      fm.Encrypted = method.PasswordIsDefined;

+

+      unsigned groupIndex = GetGroup(filters, fm);

+      while (groupIndex >= groups.Size())

+        groups.AddNew();

+      groups[groupIndex].Indices.Add(i);

     }

   }

 

+

   #ifndef _NO_CRYPTO

 

   CCryptoGetTextPassword *getPasswordSpec = NULL;

+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;

   if (needEncryptedRepack)

   {

     getPasswordSpec = new CCryptoGetTextPassword;

+    getTextPassword = getPasswordSpec;

+    

+    #ifndef _7ZIP_ST

     threadDecoder.getTextPassword = getPasswordSpec;

+    #endif

 

     if (options.Method->PasswordIsDefined)

       getPasswordSpec->Password = options.Method->Password;

@@ -926,7 +1796,7 @@
         return E_NOTIMPL;

       CMyComBSTR password;

       RINOK(getDecoderPassword->CryptoGetTextPassword(&password));

-      if ((BSTR)password)

+      if (password)

         getPasswordSpec->Password = password;

     }

   }

@@ -986,7 +1856,10 @@
 

   {

     /* ---------- Write non-AUX dirs and Empty files ---------- */

-    CRecordVector<int> emptyRefs;

+    CUIntVector emptyRefs;

+    

+    unsigned i;

+

     for (i = 0; i < updateItems.Size(); i++)

     {

       const CUpdateItem &ui = updateItems[i];

@@ -1003,7 +1876,9 @@
       */

       emptyRefs.Add(i);

     }

+    

     emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);

+    

     for (i = 0; i < emptyRefs.Size(); i++)

     {

       const CUpdateItem &ui = updateItems[emptyRefs[i]];

@@ -1030,17 +1905,36 @@
     }

   }

 

-  unsigned folderRefIndex = 0;

   lps->ProgressOffset = 0;

 

-  for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)

   {

-    const CSolidGroup &group = groups[groupIndex];

+    // ---------- Sort Filters ----------

+    

+    FOR_VECTOR (i, filters)

+    {

+      filters[i].GroupIndex = i;

+    }

+    filters.Sort2();

+  }

+

+  for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)

+  {

+    const CFilterMode2 &filterMode = filters[groupIndex];

 

     CCompressionMethodMode method = *options.Method;

-    MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);

+    {

+      HRESULT res = MakeExeMethod(method, filterMode,

+        #ifdef _7ZIP_ST

+          false

+        #else

+          options.MaxFilter && options.MultiThreadMixer

+        #endif

+        );

 

-    if (IsEncryptedGroup(groupIndex))

+      RINOK(res);

+    }

+

+    if (filterMode.Encrypted)

     {

       if (!method.PasswordIsDefined)

       {

@@ -1059,83 +1953,266 @@
 

     CEncoder encoder(method);

 

-    for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)

+    // ---------- Repack and copy old solid blocks ----------

+

+    const CSolidGroup &group = groups[filterMode.GroupIndex];

+    

+    FOR_VECTOR(folderRefIndex, group.folderRefs)

     {

-      const CFolderRepack &rep = folderRefs[folderRefIndex];

-      if (rep.Group != groupIndex)

-        break;

-      int folderIndex = rep.FolderIndex;

+      const CFolderRepack &rep = group.folderRefs[folderRefIndex];

+

+      unsigned folderIndex = rep.FolderIndex;

       

-      if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])

+      CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

+

+      if (rep.NumCopyFiles == numUnpackStreams)

       {

+        if (opCallback)

+        {

+          RINOK(opCallback->ReportOperation(

+              NEventIndexType::kBlockIndex, (UInt32)folderIndex,

+              NUpdateNotifyOp::kReplicate));

+

+          // ---------- Copy old solid block ----------

+          {

+            CNum indexInFolder = 0;

+            for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)

+            {

+              if (db->Files[fi].HasStream)

+              {

+                indexInFolder++;

+                RINOK(opCallback->ReportOperation(

+                    NEventIndexType::kInArcIndex, (UInt32)fi,

+                    NUpdateNotifyOp::kReplicate));

+              }

+            }

+          }

+        }

+

         UInt64 packSize = db->GetFolderFullPackSize(folderIndex);

         RINOK(WriteRange(inStream, archive.SeqStream,

-          db->GetFolderStreamPos(folderIndex, 0), packSize, progress));

+            db->GetFolderStreamPos(folderIndex, 0), packSize, progress));

         lps->ProgressOffset += packSize;

         

         CFolder &folder = newDatabase.Folders.AddNew();

         db->ParseFolderInfo(folderIndex, folder);

         CNum startIndex = db->FoStartPackStreamIndex[folderIndex];

-        for (unsigned j = 0; j < folder.PackStreams.Size(); j++)

+        FOR_VECTOR(j, folder.PackStreams)

         {

           newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));

           // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);

           // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);

         }

 

-        UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];

-        UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];

+        size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];

+        size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];

         for (; indexStart < indexEnd; indexStart++)

           newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);

       }

       else

       {

+        // ---------- Repack old solid block ----------

+

         CBoolVector extractStatuses;

         

-        CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

         CNum indexInFolder = 0;

-        

+

+        if (opCallback)

+        {

+          RINOK(opCallback->ReportOperation(

+              NEventIndexType::kBlockIndex, (UInt32)folderIndex,

+              NUpdateNotifyOp::kRepack))

+        }

+

+        /* We could reduce data size of decoded folder, if we don't need to repack

+           last files in folder. But the gain in speed is small in most cases.

+           So we unpack full folder. */

+           

+        UInt64 sizeToEncode = 0;

+  

+        /*

+        UInt64 importantUnpackSize = 0;

+        unsigned numImportantFiles = 0;

+        UInt64 decodeSize = 0;

+        */

+

         for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)

         {

           bool needExtract = false;

-          if (db->Files[fi].HasStream)

+          const CFileItem &file = db->Files[fi];

+  

+          if (file.HasStream)

           {

             indexInFolder++;

             int updateIndex = fileIndexToUpdateIndexMap[fi];

             if (updateIndex >= 0 && !updateItems[updateIndex].NewData)

               needExtract = true;

+            // decodeSize += file.Size;

           }

+          

           extractStatuses.Add(needExtract);

+          if (needExtract)

+          {

+            sizeToEncode += file.Size;

+            /*

+            numImportantFiles = extractStatuses.Size();

+            importantUnpackSize = decodeSize;

+            */

+          }

         }

 

+        // extractStatuses.DeleteFrom(numImportantFiles);

+

         unsigned startPackIndex = newDatabase.PackSizes.Size();

         UInt64 curUnpackSize;

         {

-          CMyComPtr<ISequentialInStream> sbInStream;

-          {

-            CMyComPtr<ISequentialOutStream> sbOutStream;

-            sb.CreateStreams(&sbInStream, &sbOutStream);

-            sb.ReInit();

-            RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));

-          }

-          

-          threadDecoder.InStream = inStream;

-          threadDecoder.Folders = (const CFolders *)db;

-          threadDecoder.FolderIndex = folderIndex;

-          threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);

-          

-          threadDecoder.Start();

-          

-          RINOK(encoder.Encode(

-              EXTERNAL_CODECS_LOC_VARS

-              sbInStream, NULL, &inSizeForReduce,

-              newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,

-              archive.SeqStream, newDatabase.PackSizes, progress));

-          

-          threadDecoder.WaitExecuteFinish();

-        }

 

-        RINOK(threadDecoder.Result);

+          CMyComPtr<ISequentialInStream> sbInStream;

+          CRepackStreamBase *repackBase;

+          CFolderInStream2 *FosSpec2 = NULL;

+

+          CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;

+          CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;

+          {

+            #ifndef _7ZIP_ST

+            if (options.MultiThreadMixer)

+            {

+              repackBase = threadDecoder.FosSpec;

+              CMyComPtr<ISequentialOutStream> sbOutStream;

+              sb.CreateStreams(&sbInStream, &sbOutStream);

+              sb.ReInit();

+              

+              threadDecoder.FosSpec->_stream = sbOutStream;

+              

+              threadDecoder.InStream = inStream;

+              threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);

+              threadDecoder.Folders = (const CFolders *)db;

+              threadDecoder.FolderIndex = folderIndex;

+             

+              // threadDecoder.UnpackSize = importantUnpackSize;

+              // threadDecoder.send_UnpackSize = true;

+            }

+            else

+            #endif

+            {

+              FosSpec2 = new CFolderInStream2;

+              FosSpec2->Init();

+              sbInStream = FosSpec2;

+              repackBase = FosSpec2;

+

+              #ifndef _NO_CRYPTO

+              bool isEncrypted = false;

+              bool passwordIsDefined = false;

+              UString password;

+              #endif

+              

+              CMyComPtr<ISequentialInStream> decodedStream;

+              HRESULT res = threadDecoder.Decoder.Decode(

+                  EXTERNAL_CODECS_LOC_VARS

+                  inStream,

+                  db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,

+                  *db, folderIndex,

+                  // &importantUnpackSize, // *unpackSize

+                  NULL, // *unpackSize : FULL unpack

+                

+                  NULL, // *outStream

+                  NULL, // *compressProgress

+                  &decodedStream

+                

+                  _7Z_DECODER_CRYPRO_VARS

+                  #ifndef _7ZIP_ST

+                    , false // mtMode

+                    , 1 // numThreads

+                  #endif

+                );

+          

+              RINOK(res);

+              if (!decodedStream)

+                return E_FAIL;

+

+              FosSpec2->_inStream = decodedStream;

+            }

+

+            repackBase->_db = db;

+            repackBase->_opCallback = opCallback;

+            repackBase->_extractCallback = extractCallback;

+

+            UInt32 startIndex = db->FolderStartFileIndex[folderIndex];

+            RINOK(repackBase->Init(startIndex, &extractStatuses));

+

+            inStreamSizeCountSpec->_db = db;

+            inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);

+

+            #ifndef _7ZIP_ST

+            if (options.MultiThreadMixer)

+            {

+              threadDecoder.Start();

+            }

+            #endif

+          }

+

+

+          HRESULT encodeRes = encoder.Encode(

+              EXTERNAL_CODECS_LOC_VARS

+              inStreamSizeCount,

+              // NULL,

+              &inSizeForReduce,

+              newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,

+              archive.SeqStream, newDatabase.PackSizes, progress);

+

+          if (encodeRes == k_My_HRESULT_CRC_ERROR)

+            return E_FAIL;

+

+          #ifndef _7ZIP_ST

+          if (options.MultiThreadMixer)

+          {

+            // 16.00: hang was fixed : for case if decoding was not finished.

+            // We close CBinderInStream and it calls CStreamBinder::CloseRead()

+            inStreamSizeCount.Release();

+            sbInStream.Release();

+            

+            threadDecoder.WaitExecuteFinish();

+            

+            HRESULT decodeRes = threadDecoder.Result;

+            // if (res == k_My_HRESULT_CRC_ERROR)

+            if (decodeRes == S_FALSE)

+            {

+              if (extractCallback)

+              {

+                RINOK(extractCallback->ReportExtractResult(

+                    NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],

+                    // NEventIndexType::kBlockIndex, (UInt32)folderIndex,

+                    NExtract::NOperationResult::kDataError));

+              }

+              return E_FAIL;

+            }

+            RINOK(decodeRes);

+            if (encodeRes == S_OK)

+              if (sb.ProcessedSize != sizeToEncode)

+                encodeRes = E_FAIL;

+          }

+          else

+          #endif

+          {

+            if (FosSpec2->Result == S_FALSE)

+            {

+              if (extractCallback)

+              {

+                RINOK(extractCallback->ReportExtractResult(

+                    NEventIndexType::kBlockIndex, (UInt32)folderIndex,

+                    NExtract::NOperationResult::kDataError));

+              }

+              return E_FAIL;

+            }

+            RINOK(FosSpec2->Result);

+          }

+

+          RINOK(encodeRes);

+          RINOK(repackBase->CheckFinishedState());

+

+          if (curUnpackSize != sizeToEncode)

+            return E_FAIL;

+        }

 

         for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

           lps->OutSize += newDatabase.PackSizes[startPackIndex];

@@ -1144,8 +2221,6 @@
       

       newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);

       

-      CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

-      

       CNum indexInFolder = 0;

       for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)

       {

@@ -1187,14 +2262,21 @@
       }

     }

 

+

+    // ---------- Compress files to new solid blocks ----------

+

     unsigned numFiles = group.Indices.Size();

     if (numFiles == 0)

       continue;

     CRecordVector<CRefItem> refItems;

     refItems.ClearAndSetSize(numFiles);

-    bool sortByType = (numSolidFiles > 1);

+    bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);

+    

+    unsigned i;

+

     for (i = 0; i < numFiles; i++)

       refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);

+

     CSortParam sortParam;

     // sortParam.TreeFolders = &treeFolders;

     sortParam.SortByType = sortByType;

@@ -1222,10 +2304,11 @@
     for (i = 0; i < numFiles;)

     {

       UInt64 totalSize = 0;

-      int numSubFiles;

-      UString prevExtension;

-      for (numSubFiles = 0; i + numSubFiles < numFiles &&

-          numSubFiles < numSolidFiles; numSubFiles++)

+      unsigned numSubFiles;

+      

+      const wchar_t *prevExtension = NULL;

+      

+      for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)

       {

         const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];

         totalSize += ui.Size;

@@ -1233,17 +2316,21 @@
           break;

         if (options.SolidExtension)

         {

-          UString ext = ui.GetExtension();

+          int slashPos = ui.Name.ReverseFind_PathSepar();

+          int dotPos = ui.Name.ReverseFind_Dot();

+          const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1);

           if (numSubFiles == 0)

             prevExtension = ext;

-          else

-            if (!ext.IsEqualToNoCase(prevExtension))

-              break;

+          else if (!StringsAreEqualNoCase(ext, prevExtension))

+            break;

         }

       }

+

       if (numSubFiles < 1)

         numSubFiles = 1;

 

+      RINOK(lps->SetCur());

+

       CFolderInStream *inStreamSpec = new CFolderInStream;

       CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);

       inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);

@@ -1252,10 +2339,15 @@
       UInt64 curFolderUnpackSize;

       RINOK(encoder.Encode(

           EXTERNAL_CODECS_LOC_VARS

-          solidInStream, NULL, &inSizeForReduce,

+          solidInStream,

+          // NULL,

+          &inSizeForReduce,

           newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,

           archive.SeqStream, newDatabase.PackSizes, progress));

 

+      if (!inStreamSpec->WasFinished())

+        return E_FAIL;

+

       for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

         lps->OutSize += newDatabase.PackSizes[startPackIndex];

 

@@ -1263,9 +2355,11 @@
       // for ()

       // newDatabase.PackCRCsDefined.Add(false);

       // newDatabase.PackCRCs.Add(0);

-      

+

       CNum numUnpackStreams = 0;

-      for (int subIndex = 0; subIndex < numSubFiles; subIndex++)

+      UInt64 skippedSize = 0;

+      

+      for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)

       {

         const CUpdateItem &ui = updateItems[indices[i + subIndex]];

         CFileItem file;

@@ -1290,12 +2384,15 @@
         */

         if (!inStreamSpec->Processed[subIndex])

         {

+          skippedSize += ui.Size;

           continue;

-          // file.Name += L".locked";

+          // file.Name.AddAscii(".locked");

         }

 

         file.Crc = inStreamSpec->CRCs[subIndex];

         file.Size = inStreamSpec->Sizes[subIndex];

+        

+        // if (file.Size >= 0) // test purposes

         if (file.Size != 0)

         {

           file.CrcDefined = true;

@@ -1307,6 +2404,7 @@
           file.CrcDefined = false;

           file.HasStream = false;

         }

+

         /*

         file.Parent = ui.ParentFolderIndex;

         if (ui.TreeFolderIndex >= 0)

@@ -1316,20 +2414,23 @@
         */

         newDatabase.AddFile(file, file2, name);

       }

+

       // numUnpackStreams = 0 is very bad case for locked files

       // v3.13 doesn't understand it.

       newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);

       i += numSubFiles;

+

+      if (skippedSize != 0 && complexity >= skippedSize)

+      {

+        complexity -= skippedSize;

+        RINOK(updateCallback->SetTotal(complexity));

+      }

     }

   }

 

-  if (folderRefIndex != folderRefs.Size())

-    return E_FAIL;

-

   RINOK(lps->SetCur());

 

   /*

-  folderRefs.ClearAndFree();

   fileIndexToUpdateIndexMap.ClearAndFree();

   groups.ClearAndFree();

   */

@@ -1350,13 +2451,18 @@
     {

       const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];

       size_t size = buf.GetCapacity();

-      memcpy(newDatabase.SecureBuf + pos, buf, size);

+      if (size != 0)

+        memcpy(newDatabase.SecureBuf + pos, buf, size);

       newDatabase.SecureSizes.Add((UInt32)size);

       pos += size;

     }

   }

   */

   newDatabase.ReserveDown();

+

+  if (opCallback)

+    RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader));

+

   return S_OK;

 }

 

diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index 070bc30..06a0b05 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -65,6 +65,7 @@
   // int SecureIndex; // 0 means (no_security)

 

   bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }

+  // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes

 

   CUpdateItem():

       // ParentSortIndex(-1),

@@ -77,26 +78,44 @@
       MTimeDefined(false)

       // SecureIndex(0)

       {}

-  void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };

+  void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }

 

-  int GetExtensionPos() const;

-  UString GetExtension() const;

+  // unsigned GetExtensionPos() const;

+  // UString GetExtension() const;

 };

 

 struct CUpdateOptions

 {

   const CCompressionMethodMode *Method;

   const CCompressionMethodMode *HeaderMethod;

-  bool UseFilters;

-  bool MaxFilter;

+  bool UseFilters; // use additional filters for some files

+  bool MaxFilter;  // use BCJ2 filter instead of BCJ

+  int AnalysisLevel;

 

   CHeaderOptions HeaderOptions;

 

   UInt64 NumSolidFiles;

   UInt64 NumSolidBytes;

   bool SolidExtension;

+  

+  bool UseTypeSorting;

+  

   bool RemoveSfxBlock;

-  bool VolumeMode;

+  bool MultiThreadMixer;

+

+  CUpdateOptions():

+      Method(NULL),

+      HeaderMethod(NULL),

+      UseFilters(false),

+      MaxFilter(false),

+      AnalysisLevel(-1),

+      NumSolidFiles((UInt64)(Int64)(-1)),

+      NumSolidBytes((UInt64)(Int64)(-1)),

+      SolidExtension(false),

+      UseTypeSorting(true),

+      RemoveSfxBlock(false),

+      MultiThreadMixer(true)

+    {}

 };

 

 HRESULT Update(

diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
index 839245e..a3fe6dd 100644
--- a/CPP/7zip/Archive/Archive.def
+++ b/CPP/7zip/Archive/Archive.def
@@ -1,6 +1,12 @@
 EXPORTS

   CreateObject PRIVATE

+

   GetHandlerProperty PRIVATE

   GetNumberOfFormats PRIVATE

   GetHandlerProperty2 PRIVATE

-  CreateObject PRIVATE

+  GetIsArc PRIVATE

+

+  SetCodecs PRIVATE

+

+  SetLargePageMode PRIVATE

+  SetCaseSensitive PRIVATE

diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
index 09bd9b9..de744b5 100644
--- a/CPP/7zip/Archive/Archive2.def
+++ b/CPP/7zip/Archive/Archive2.def
@@ -1,11 +1,19 @@
 EXPORTS

   CreateObject PRIVATE

+

   GetHandlerProperty PRIVATE

   GetNumberOfFormats PRIVATE

   GetHandlerProperty2 PRIVATE

+  GetIsArc PRIVATE

+

   GetNumberOfMethods PRIVATE

   GetMethodProperty PRIVATE

+  CreateDecoder PRIVATE

+  CreateEncoder PRIVATE

+

   GetHashers PRIVATE

+

+  SetCodecs PRIVATE

+

   SetLargePageMode PRIVATE

   SetCaseSensitive PRIVATE

-  GetIsArc PRIVATE
\ No newline at end of file
diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp
index 1295331..94f2fff 100644
--- a/CPP/7zip/Archive/ArchiveExports.cpp
+++ b/CPP/7zip/Archive/ArchiveExports.cpp
@@ -22,17 +22,19 @@
     const char *p = arcInfo->Name;

     if (p[0] == '7' && p[1] == 'z' && p[2] == 0)

       g_DefaultArcIndex = g_NumArcs;

-    g_Arcs[g_NumArcs] = arcInfo;

-    g_NumArcs++;

+    g_Arcs[g_NumArcs++] = arcInfo;

   }

 }

 

 DEFINE_GUID(CLSID_CArchiveHandler,

-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

+    k_7zip_GUID_Data1,

+    k_7zip_GUID_Data2,

+    k_7zip_GUID_Data3_Common,

+    0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

 

 #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])

 

-static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)

+static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)

 {

   if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)

     value->vt = VT_BSTR;

@@ -41,18 +43,18 @@
 

 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)

 {

-  return SetPropString((const char *)&guid, sizeof(GUID), value);

+  return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);

 }

 

-int FindFormatCalssId(const GUID *clsID)

+int FindFormatCalssId(const GUID *clsid)

 {

-  GUID cls = *clsID;

+  GUID cls = *clsid;

   CLS_ARC_ID_ITEM(cls) = 0;

   if (cls != CLSID_CArchiveHandler)

     return -1;

-  Byte id = CLS_ARC_ID_ITEM(*clsID);

+  Byte id = CLS_ARC_ID_ITEM(*clsid);

   for (unsigned i = 0; i < g_NumArcs; i++)

-    if (g_Arcs[i]->ClassId == id)

+    if (g_Arcs[i]->Id == id)

       return (int)i;

   return -1;

 }

@@ -101,7 +103,7 @@
     case NArchive::NHandlerPropID::kClassID:

     {

       GUID clsId = CLSID_CArchiveHandler;

-      CLS_ARC_ID_ITEM(clsId) = arc.ClassId;

+      CLS_ARC_ID_ITEM(clsId) = arc.Id;

       return SetPropGUID(clsId, value);

     }

     case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;

@@ -115,12 +117,12 @@
     // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;

 

     case NArchive::NHandlerPropID::kSignature:

-      if (!arc.IsMultiSignature())

-        return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);

+      if (arc.SignatureSize != 0 && !arc.IsMultiSignature())

+        return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);

       break;

     case NArchive::NHandlerPropID::kMultiSignature:

-      if (arc.IsMultiSignature())

-        return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);

+      if (arc.SignatureSize != 0 && arc.IsMultiSignature())

+        return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);

       break;

   }

   prop.Detach(value);

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index ed82d98..aeb1d38 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -4,116 +4,1041 @@
 

 #include "CoderMixer2.h"

 

-namespace NCoderMixer {

+#ifdef USE_MIXER_ST

 

-CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):

-  _srcBindInfo(srcBindInfo)

+STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);

+  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;

+}

 

-  UInt32 j;

-  _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams);

-  DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams);

 

-  for (j = 0; j < NumSrcInStreams; j++)

+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::OutStreamFinish()

+{

+  HRESULT result = S_OK;

+  if (_stream)

   {

-    _srcInToDestOutMap[j] = 0;

-    DestOutToSrcInMap[j] = 0;

+    CMyComPtr<IOutStreamFinish> outStreamFinish;

+    _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);

+    if (outStreamFinish)

+      result = outStreamFinish->OutStreamFinish();

   }

+  return result;

+}

 

-  _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams);

-  _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams);

+#endif

 

-  for (j = 0; j < _numSrcOutStreams; j++)

+

+

+

+namespace NCoderMixer2 {

+

+static void BoolVector_Fill_False(CBoolVector &v, unsigned size)

+{

+  v.ClearAndSetSize(size);

+  bool *p = &v[0];

+  for (unsigned i = 0; i < size; i++)

+    p[i] = false;

+}

+

+class CBondsChecks

+{

+  CBoolVector _coderUsed;

+

+  bool Init();

+  bool CheckCoder(unsigned coderIndex);

+public:

+  const CBindInfo *BindInfo;

+

+  bool Check();

+};

+

+bool CBondsChecks::CheckCoder(unsigned coderIndex)

+{

+  const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];

+

+  if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])

+    return false;

+  _coderUsed[coderIndex] = true;

+  

+  UInt32 start = BindInfo->Coder_to_Stream[coderIndex];

+

+  for (unsigned i = 0; i < coder.NumStreams; i++)

   {

-    _srcOutToDestInMap[j] = 0;

-    _destInToSrcOutMap[j] = 0;

-  }

-

-  UInt32 destInOffset = 0;

-  UInt32 destOutOffset = 0;

-  UInt32 srcInOffset = NumSrcInStreams;

-  UInt32 srcOutOffset = _numSrcOutStreams;

-

-  for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)

-  {

-    const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];

-

-    srcInOffset -= srcCoderInfo.NumInStreams;

-    srcOutOffset -= srcCoderInfo.NumOutStreams;

+    UInt32 ind = start + i;

     

-    UInt32 j;

-    for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)

-    {

-      UInt32 index = srcInOffset + j;

-      _srcInToDestOutMap[index] = destOutOffset;

-      DestOutToSrcInMap[destOutOffset] = index;

-    }

-    for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)

-    {

-      UInt32 index = srcOutOffset + j;

-      _srcOutToDestInMap[index] = destInOffset;

-      _destInToSrcOutMap[destInOffset] = index;

-    }

+    if (BindInfo->IsStream_in_PackStreams(ind))

+      continue;

+    

+    int bond = BindInfo->FindBond_for_PackStream(ind);

+    if (bond < 0)

+      return false;

+    if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))

+      return false;

   }

+  

+  return true;

 }

 

-void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)

+bool CBondsChecks::Check()

 {

-  destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size());

-  destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size());

-  destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size());

-  destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size());

+  BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());

+  

+  if (!CheckCoder(BindInfo->UnpackCoder))

+    return false;

 

-  unsigned i;

-  for (i = _srcBindInfo.Coders.Size(); i != 0;)

-  {

-    i--;

-    const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];

-    CCoderStreamsInfo destCoderInfo;

-    destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;

-    destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;

-    destBindInfo.Coders.AddInReserved(destCoderInfo);

-  }

-  for (i = _srcBindInfo.BindPairs.Size(); i != 0;)

-  {

-    i--;

-    const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];

-    CBindPair destBindPair;

-    destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];

-    destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];

-    destBindInfo.BindPairs.AddInReserved(destBindPair);

-  }

-  for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)

-    destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);

-  for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)

-    destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);

+  FOR_VECTOR(i, _coderUsed)

+    if (!_coderUsed[i])

+      return false;

+

+  return true;

 }

 

-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

-    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)

+void CBindInfo::ClearMaps()

 {

-  sizes.ClearAndSetSize(numItems);

-  sizePointers.ClearAndSetSize(numItems);

-  for(UInt32 i = 0; i < numItems; i++)

+  Coder_to_Stream.Clear();

+  Stream_to_Coder.Clear();

+}

+

+bool CBindInfo::CalcMapsAndCheck()

+{

+  ClearMaps();

+

+  UInt32 numStreams = 0;

+

+  if (Coders.Size() == 0)

+    return false;

+  if (Coders.Size() - 1 != Bonds.Size())

+    return false;

+

+  FOR_VECTOR(i, Coders)

   {

-    if (!srcSizes || !srcSizes[i])

+    Coder_to_Stream.Add(numStreams);

+    

+    const CCoderStreamsInfo &c = Coders[i];

+    

+    for (unsigned j = 0; j < c.NumStreams; j++)

+      Stream_to_Coder.Add(i);

+

+    numStreams += c.NumStreams;

+  }

+

+  if (numStreams != GetNum_Bonds_and_PackStreams())

+    return false;

+

+  CBondsChecks bc;

+  bc.BindInfo = this;

+  return bc.Check();

+}

+

+

+void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)

+{

+  if (unpackSize)

+  {

+    UnpackSize = *unpackSize;

+    UnpackSizePointer = &UnpackSize;

+  }

+  else

+  {

+    UnpackSize = 0;

+    UnpackSizePointer = NULL;

+  }

+  

+  PackSizes.ClearAndSetSize((unsigned)NumStreams);

+  PackSizePointers.ClearAndSetSize((unsigned)NumStreams);

+  

+  for (unsigned i = 0; i < NumStreams; i++)

+  {

+    if (packSizes && packSizes[i])

     {

-      sizes[i] = 0;

-      sizePointers[i] = NULL;

+      PackSizes[i] = *(packSizes[i]);

+      PackSizePointers[i] = &PackSizes[i];

     }

     else

     {

-      sizes[i] = *(srcSizes[i]);

-      sizePointers[i] = &sizes[i];

+      PackSizes[i] = 0;

+      PackSizePointers[i] = NULL;

     }

   }

 }

 

-void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)

+bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)

 {

-  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

-  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

+  if (coderIndex == _bi.UnpackCoder)

+    return true;

+  

+  int bond = _bi.FindBond_for_UnpackStream(coderIndex);

+  if (bond < 0)

+    throw 20150213;

+  

+  /*

+  UInt32 coderIndex, coderStreamIndex;

+  _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex);

+  */

+  UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];

+  

+  if (!IsFilter_Vector[nextCoder])

+    return false;

+  

+  return Is_UnpackSize_Correct_for_Coder(nextCoder);

 }

 

+bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)

+{

+  if (_bi.IsStream_in_PackStreams(streamIndex))

+    return true;

+  

+  int bond = _bi.FindBond_for_PackStream(streamIndex);

+  if (bond < 0)

+    throw 20150213;

+

+  UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;

+

+  if (!IsFilter_Vector[nextCoder])

+    return false;

+  

+  return Is_PackSize_Correct_for_Coder(nextCoder);

+}

+

+bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)

+{

+  UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];

+  UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;

+  for (UInt32 i = 0; i < numStreams; i++)

+    if (!Is_PackSize_Correct_for_Stream(startIndex + i))

+      return false;

+  return true;

+}

+

+bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)

+{

+  if (IsExternal_Vector[coderIndex])

+    return true;

+  UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];

+  UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;

+  for (UInt32 i = 0; i < numStreams; i++)

+  {

+    UInt32 si = startIndex + i;

+    if (_bi.IsStream_in_PackStreams(si))

+      continue;

+  

+    int bond = _bi.FindBond_for_PackStream(si);

+    if (bond < 0)

+      throw 20150213;

+

+    if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))

+      return true;

+  }

+  return false;

+}

+

+

+

+

+#ifdef USE_MIXER_ST

+

+CMixerST::CMixerST(bool encodeMode):

+    CMixer(encodeMode)

+    {}

+

+CMixerST::~CMixerST() {}

+

+void CMixerST::AddCoder(const CCreatedCoder &cod)

+{

+  IsFilter_Vector.Add(cod.IsFilter);

+  IsExternal_Vector.Add(cod.IsExternal);

+  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];

+  CCoderST &c2 = _coders.AddNew();

+  c2.NumStreams = cod.NumStreams;

+  c2.Coder = cod.Coder;

+  c2.Coder2 = cod.Coder2;

+

+  /*

+  if (isFilter)

+  {

+    c2.CanRead = true;

+    c2.CanWrite = true;

+  }

+  else

+  */

+  {

+    IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.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[(unsigned)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[(unsigned)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::FinishStream(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<IOutStreamFinish> finish;

+  coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);

+  HRESULT res = S_OK;

+  if (finish)

+  {

+    res = finish->OutStreamFinish();

+  }

+  return GetError(res, FinishCoder(coderIndex));

+}

+

+

+HRESULT CMixerST::FinishCoder(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, FinishStream(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;

+  }

+  

+  if (useFirst)

+    ci = firstAllowed;

+  else if (firstNonFilter >= 0)

+    ci = firstNonFilter;

+

+  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];

+

+    if (EncodeMode)

+    {

+      CMyComPtr<ICompressInitEncoder> initEncoder;

+      coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);

+      if (initEncoder)

+        RINOK(initEncoder->InitEncoder());

+    }

+    else

+    {

+      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, FinishCoder(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();

+}

+

+#endif

+

+

+

+

+

+

+#ifdef USE_MIXER_MT

+

+

+void CCoderMT::Execute()

+{

+  try

+  {

+    Code(NULL);

+  }

+  catch(...)

+  {

+    Result = E_FAIL;

+  }

+}

+

+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];

+  */

+

+  CReleaser releaser(*this);

+  

+  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);

+}

+

+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(const CCreatedCoder &cod)

+{

+  IsFilter_Vector.Add(cod.IsFilter);

+  IsExternal_Vector.Add(cod.IsExternal);

+  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];

+  CCoderMT &c2 = _coders.AddNew();

+  c2.NumStreams = cod.NumStreams;

+  c2.Coder = cod.Coder;

+  c2.Coder2 = cod.Coder2;

+  c2.EncodeMode = EncodeMode;

+}

+

+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;

+}

+

+#endif

+

 }

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
index 7618bb2..ce4797f 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -8,172 +8,430 @@
 

 #include "../../ICoder.h"

 

-namespace NCoderMixer {

+#include "../../Common/CreateCoder.h"

 

-struct CBindPair

+#ifdef _7ZIP_ST

+  #define USE_MIXER_ST

+#else

+  #define USE_MIXER_MT

+  #ifndef _SFX

+    #define USE_MIXER_ST

+  #endif

+#endif

+

+#ifdef USE_MIXER_MT

+#include "../../Common/StreamBinder.h"

+#include "../../Common/VirtThread.h"

+#endif

+

+

+

+#ifdef USE_MIXER_ST

+

+class CSequentialInStreamCalcSize:

+  public ISequentialInStream,

+  public CMyUnknownImp

 {

-  UInt32 InIndex;

-  UInt32 OutIndex;

+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 IOutStreamFinish,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+public:

+  MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)

+  

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(OutStreamFinish)();

+  

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init() { _size = 0; }

+  UInt64 GetSize() const { return _size; }

+};

+

+#endif

+

+

+  

+namespace NCoderMixer2 {

+

+struct CBond

+{

+  UInt32 PackIndex;

+  UInt32 UnpackIndex;

+

+  UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }

+  UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }

+};

+

+

 struct CCoderStreamsInfo

 {

-  UInt32 NumInStreams;

-  UInt32 NumOutStreams;

+  UInt32 NumStreams;

 };

 

+

 struct CBindInfo

 {

   CRecordVector<CCoderStreamsInfo> Coders;

-  CRecordVector<CBindPair> BindPairs;

-  CRecordVector<UInt32> InStreams;

-  CRecordVector<UInt32> OutStreams;

+  CRecordVector<CBond> Bonds;

+  CRecordVector<UInt32> PackStreams;

+  unsigned UnpackCoder;

+

+  unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }

+

+  int FindBond_for_PackStream(UInt32 packStream) const

+  {

+    FOR_VECTOR (i, Bonds)

+      if (Bonds[i].PackIndex == packStream)

+        return i;

+    return -1;

+  }

+

+  int FindBond_for_UnpackStream(UInt32 unpackStream) const

+  {

+    FOR_VECTOR (i, Bonds)

+      if (Bonds[i].UnpackIndex == unpackStream)

+        return i;

+    return -1;

+  }

+

+  bool SetUnpackCoder()

+  {

+    bool isOk = false;

+    FOR_VECTOR(i, Coders)

+    {

+      if (FindBond_for_UnpackStream(i) < 0)

+      {

+        if (isOk)

+          return false;

+        UnpackCoder = i;

+        isOk = true;

+      }

+    }

+    return isOk;

+  }

+  

+  bool IsStream_in_PackStreams(UInt32 streamIndex) const

+  {

+    return FindStream_in_PackStreams(streamIndex) >= 0;

+  }

+

+  int FindStream_in_PackStreams(UInt32 streamIndex) const

+  {

+    FOR_VECTOR(i, PackStreams)

+      if (PackStreams[i] == streamIndex)

+        return i;

+    return -1;

+  }

+

+  

+  // that function is used before Maps is calculated

+

+  UInt32 GetStream_for_Coder(UInt32 coderIndex) const

+  {

+    UInt32 streamIndex = 0;

+    for (UInt32 i = 0; i < coderIndex; i++)

+      streamIndex += Coders[i].NumStreams;

+    return streamIndex;

+  }

+  

+  // ---------- Maps Section ----------

+  

+  CRecordVector<UInt32> Coder_to_Stream;

+  CRecordVector<UInt32> Stream_to_Coder;

+

+  void ClearMaps();

+  bool CalcMapsAndCheck();

+

+  // ---------- End of Maps Section ----------

 

   void Clear()

   {

     Coders.Clear();

-    BindPairs.Clear();

-    InStreams.Clear();

-    OutStreams.Clear();

-  }

+    Bonds.Clear();

+    PackStreams.Clear();

 

-  /*

-  UInt32 GetCoderStartOutStream(UInt32 coderIndex) const

-  {

-    UInt32 numOutStreams = 0;

-    for (UInt32 i = 0; i < coderIndex; i++)

-      numOutStreams += Coders[i].NumOutStreams;

-    return numOutStreams;

+    ClearMaps();

   }

-  */

-

-

-  void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const

+  

+  void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const

   {

-    numInStreams = 0;

-    numOutStreams = 0;

-    FOR_VECTOR (i, Coders)

-    {

-      const CCoderStreamsInfo &coderStreamsInfo = Coders[i];

-      numInStreams += coderStreamsInfo.NumInStreams;

-      numOutStreams += coderStreamsInfo.NumOutStreams;

-    }

-  }

-

-  int FindBinderForInStream(UInt32 inStream) const

-  {

-    FOR_VECTOR (i, BindPairs)

-      if (BindPairs[i].InIndex == inStream)

-        return i;

-    return -1;

-  }

-  int FindBinderForOutStream(UInt32 outStream) const

-  {

-    FOR_VECTOR (i, BindPairs)

-      if (BindPairs[i].OutIndex == outStream)

-        return i;

-    return -1;

-  }

-

-  UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const

-  {

-    UInt32 streamIndex = 0;

-    for (UInt32 i = 0; i < coderIndex; i++)

-      streamIndex += Coders[i].NumInStreams;

-    return streamIndex;

-  }

-

-  UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const

-  {

-    UInt32 streamIndex = 0;

-    for (UInt32 i = 0; i < coderIndex; i++)

-      streamIndex += Coders[i].NumOutStreams;

-    return streamIndex;

-  }

-

-

-  void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,

-      UInt32 &coderStreamIndex) const

-  {

-    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)

-    {

-      UInt32 curSize = Coders[coderIndex].NumInStreams;

-      if (streamIndex < curSize)

-      {

-        coderStreamIndex = streamIndex;

-        return;

-      }

-      streamIndex -= curSize;

-    }

-    throw 1;

-  }

-  void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,

-      UInt32 &coderStreamIndex) const

-  {

-    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)

-    {

-      UInt32 curSize = Coders[coderIndex].NumOutStreams;

-      if (streamIndex < curSize)

-      {

-        coderStreamIndex = streamIndex;

-        return;

-      }

-      streamIndex -= curSize;

-    }

-    throw 1;

+    coderIndex = Stream_to_Coder[streamIndex];

+    coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];

   }

 };

 

-class CBindReverseConverter

+

+

+class CCoder

 {

-  UInt32 _numSrcOutStreams;

-  NCoderMixer::CBindInfo _srcBindInfo;

-  CRecordVector<UInt32> _srcInToDestOutMap;

-  CRecordVector<UInt32> _srcOutToDestInMap;

-  CRecordVector<UInt32> _destInToSrcOutMap;

+  CLASS_NO_COPY(CCoder);

 public:

-  UInt32 NumSrcInStreams;

-  CRecordVector<UInt32> DestOutToSrcInMap;

-

-  CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);

-  void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);

-};

-

-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

-    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);

-

-struct CCoderInfo2

-{

   CMyComPtr<ICompressCoder> Coder;

   CMyComPtr<ICompressCoder2> Coder2;

-  UInt32 NumInStreams;

-  UInt32 NumOutStreams;

+  UInt32 NumStreams;

 

-  CRecordVector<UInt64> InSizes;

-  CRecordVector<UInt64> OutSizes;

-  CRecordVector<const UInt64 *> InSizePointers;

-  CRecordVector<const UInt64 *> OutSizePointers;

+  UInt64 UnpackSize;

+  const UInt64 *UnpackSizePointer;

 

-  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):

-      NumInStreams(numInStreams),

-      NumOutStreams(numOutStreams) {}

-  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

+  CRecordVector<UInt64> PackSizes;

+  CRecordVector<const UInt64 *> PackSizePointers;

+

+  CCoder() {}

+

+  void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);

+

+  IUnknown *GetUnknown() const

+  {

+    return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;

+  }

 

   HRESULT QueryInterface(REFGUID iid, void** pp) const

   {

-    IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;

-    return p->QueryInterface(iid, pp);

+    return GetUnknown()->QueryInterface(iid, pp);

   }

 };

 

-class CCoderMixer2

+

+

+class CMixer

 {

+  bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);

+

+protected:

+  CBindInfo _bi;

+

+  int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const

+  {

+    if (EncodeMode == forInputStream)

+      return _bi.FindBond_for_UnpackStream(streamIndex);

+    else

+      return _bi.FindBond_for_PackStream(streamIndex);

+  }

+

+  CBoolVector IsFilter_Vector;

+  CBoolVector IsExternal_Vector;

+  bool EncodeMode;

 public:

-  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;

+  unsigned MainCoderIndex;

+

+  CMixer(bool encodeMode):

+      EncodeMode(encodeMode),

+      MainCoderIndex(0)

+      {}

+

+  /*

+  Sequence of calling:

+

+      SetBindInfo();

+      for each coder

+        AddCoder();

+      SelectMainCoder();

+ 

+      for each file

+      {

+        ReInit()

+        for each coder

+          SetCoderInfo();

+        Code();

+      }

+  */

+

+  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)

+  {

+    _bi = bindInfo;

+    IsFilter_Vector.Clear();

+    MainCoderIndex = 0;

+    return S_OK;

+  }

+

+  virtual void AddCoder(const CCreatedCoder &cod) = 0;

+  virtual CCoder &GetCoder(unsigned index) = 0;

+  virtual void SelectMainCoder(bool useFirst) = 0;

   virtual void ReInit() = 0;

-  virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;

+  virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;

+  virtual HRESULT Code(

+      ISequentialInStream * const *inStreams,

+      ISequentialOutStream * const *outStreams,

+      ICompressProgressInfo *progress) = 0;

+  virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;

+

+  bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);

+  bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);

+  bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);

 };

 

+

+

+

+#ifdef USE_MIXER_ST

+

+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 FinishStream(UInt32 streamIndex);

+  HRESULT FinishCoder(UInt32 coderIndex);

+

+public:

+  CObjectVector<CCoderST> _coders;

+  

+  CObjectVector<CStBinderStream> _binderStreams;

+

+  MY_UNKNOWN_IMP

+

+  CMixerST(bool encodeMode);

+  ~CMixerST();

+

+  virtual void AddCoder(const CCreatedCoder &cod);

+  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

+

+

+

+

+#ifdef USE_MIXER_MT

+

+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;

+

+  void Release()

+  {

+    InStreamPointers.Clear();

+    OutStreamPointers.Clear();

+    unsigned i;

+    for (i = 0; i < InStreams.Size(); i++)

+      InStreams[i].Release();

+    for (i = 0; i < OutStreams.Size(); i++)

+      OutStreams[i].Release();

+  }

+

+  class CReleaser

+  {

+    CLASS_NO_COPY(CReleaser)

+    CCoderMT &_c;

+  public:

+    CReleaser(CCoderMT &c): _c(c) {}

+    ~CReleaser() { _c.Release(); }

+  };

+

+  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(const CCreatedCoder &cod);

+  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

+

 }

 

 #endif

diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
deleted file mode 100644
index 1e9c13e..0000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-// CoderMixer2MT.cpp

-

-#include "StdAfx.h"

-

-#include "CoderMixer2MT.h"

-

-namespace NCoderMixer {

-

-CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):

-    CCoderInfo2(numInStreams, numOutStreams)

-{

-  InStreams.ClearAndReserve(NumInStreams);

-  OutStreams.ClearAndReserve(NumOutStreams);

-}

-

-void CCoder2::Execute() { Code(NULL); }

-

-void CCoder2::Code(ICompressProgressInfo *progress)

-{

-  InStreamPointers.ClearAndReserve(NumInStreams);

-  OutStreamPointers.ClearAndReserve(NumOutStreams);

-  UInt32 i;

-  for (i = 0; i < NumInStreams; i++)

-  {

-    if (InSizePointers[i])

-      InSizePointers[i] = &InSizes[i];

-    InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);

-  }

-  for (i = 0; i < NumOutStreams; i++)

-  {

-    if (OutSizePointers[i])

-      OutSizePointers[i] = &OutSizes[i];

-    OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);

-  }

-  if (Coder)

-    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],

-        InSizePointers[0], OutSizePointers[0], progress);

-  else

-    Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,

-      &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);

-  {

-    unsigned i;

-    for (i = 0; i < InStreams.Size(); i++)

-      InStreams[i].Release();

-    for (i = 0; i < OutStreams.Size(); i++)

-      OutStreams[i].Release();

-  }

-}

-

-/*

-void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)

-{

-  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

-  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

-}

-*/

-

-//////////////////////////////////////

-// CCoderMixer2MT

-

-HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)

-{

-  _bindInfo = bindInfo;

-  _streamBinders.Clear();

-  FOR_VECTOR (i, _bindInfo.BindPairs)

-  {

-    RINOK(_streamBinders.AddNew().CreateEvents());

-  }

-  return S_OK;

-}

-

-void CCoderMixer2MT::AddCoderCommon()

-{

-  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];

-  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);

-  _coders.Add(threadCoderInfo);

-}

-

-void CCoderMixer2MT::AddCoder(ICompressCoder *coder)

-{

-  AddCoderCommon();

-  _coders.Back().Coder = coder;

-}

-

-void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)

-{

-  AddCoderCommon();

-  _coders.Back().Coder2 = coder;

-}

-

-

-void CCoderMixer2MT::ReInit()

-{

-  FOR_VECTOR (i, _streamBinders)

-    _streamBinders[i].ReInit();

-}

-

-

-HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)

-{

-  /*

-  if (_coders.Size() != _bindInfo.Coders.Size())

-    throw 0;

-  */

-  unsigned i;

-  for (i = 0; i < _coders.Size(); i++)

-  {

-    CCoder2 &coderInfo = _coders[i];

-    const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];

-    coderInfo.InStreams.Clear();

-    UInt32 j;

-    for (j = 0; j < coderStreamsInfo.NumInStreams; j++)

-      coderInfo.InStreams.Add(NULL);

-    coderInfo.OutStreams.Clear();

-    for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)

-      coderInfo.OutStreams.Add(NULL);

-  }

-

-  for (i = 0; i < _bindInfo.BindPairs.Size(); i++)

-  {

-    const CBindPair &bindPair = _bindInfo.BindPairs[i];

-    UInt32 inCoderIndex, inCoderStreamIndex;

-    UInt32 outCoderIndex, outCoderStreamIndex;

-    _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);

-    _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);

-

-    _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);

-    }

-  }

-

-  for (i = 0; i < _bindInfo.InStreams.Size(); i++)

-  {

-    UInt32 inCoderIndex, inCoderStreamIndex;

-    _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);

-    _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];

-  }

-  

-  for (i = 0; i < _bindInfo.OutStreams.Size(); i++)

-  {

-    UInt32 outCoderIndex, outCoderStreamIndex;

-    _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);

-    _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];

-  }

-  return S_OK;

-}

-

-HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)

-{

-  FOR_VECTOR (i, _coders)

-    if (_coders[i].Result == code)

-      return code;

-  return S_OK;

-}

-

-STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,

-      const UInt64 ** /* inSizes */,

-      UInt32 numInStreams,

-      ISequentialOutStream **outStreams,

-      const UInt64 ** /* outSizes */,

-      UInt32 numOutStreams,

-      ICompressProgressInfo *progress)

-{

-  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||

-      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())

-    return E_INVALIDARG;

-

-  Init(inStreams, outStreams);

-

-  unsigned i;

-  for (i = 0; i < _coders.Size(); i++)

-    if (i != _progressCoderIndex)

-    {

-      RINOK(_coders[i].Create());

-    }

-

-  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/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
deleted file mode 100644
index 78d0c19..0000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// CoderMixer2MT.h

-

-#ifndef __CODER_MIXER2_MT_H

-#define __CODER_MIXER2_MT_H

-

-#include "CoderMixer2.h"

-#include "../../../Common/MyCom.h"

-#include "../../Common/StreamBinder.h"

-#include "../../Common/VirtThread.h"

-

-namespace NCoderMixer {

-

-struct CCoder2: public CCoderInfo2, public CVirtThread

-{

-  CRecordVector<ISequentialInStream*> InStreamPointers;

-  CRecordVector<ISequentialOutStream*> OutStreamPointers;

-

-public:

-  HRESULT Result;

-  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;

-  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;

-

-  CCoder2(UInt32 numInStreams, UInt32 numOutStreams);

-  ~CCoder2() { CVirtThread::WaitThreadFinish(); }

-  // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

-  virtual void Execute();

-  void Code(ICompressProgressInfo *progress);

-};

-

-

-/*

-  SetBindInfo()

-  for each coder

-    AddCoder[2]()

-  SetProgressIndex(UInt32 coderIndex);

- 

-  for each file

-  {

-    ReInit()

-    for each coder

-      SetCoderInfo

-    Code

-  }

-*/

-

-class CCoderMixer2MT:

-  public ICompressCoder2,

-  public CCoderMixer2,

-  public CMyUnknownImp

-{

-  CBindInfo _bindInfo;

-  CObjectVector<CStreamBinder> _streamBinders;

-  unsigned _progressCoderIndex;

-

-  void AddCoderCommon();

-  HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);

-  HRESULT ReturnIfError(HRESULT code);

-public:

-  CObjectVector<CCoder2> _coders;

-  MY_UNKNOWN_IMP

-

-  STDMETHOD(Code)(ISequentialInStream **inStreams,

-      const UInt64 **inSizes,

-      UInt32 numInStreams,

-      ISequentialOutStream **outStreams,

-      const UInt64 **outSizes,

-      UInt32 numOutStreams,

-      ICompressProgressInfo *progress);

-

-  HRESULT SetBindInfo(const CBindInfo &bindInfo);

-  void AddCoder(ICompressCoder *coder);

-  void AddCoder2(ICompressCoder2 *coder);

-  void SetProgressCoderIndex(unsigned coderIndex) {  _progressCoderIndex = coderIndex; }

-

-  void ReInit();

-  void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)

-    {  _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }

-  UInt64 GetWriteProcessedSize(UInt32 binderIndex) const

-    {  return _streamBinders[binderIndex].ProcessedSize; }

-};

-

-}

-#endif

diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
deleted file mode 100644
index 62d05af..0000000
--- a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// CrossThreadProgress.cpp

-

-#include "StdAfx.h"

-

-#include "CrossThreadProgress.h"

-

-STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

-{

-  InSize = inSize;

-  OutSize = outSize;

-  ProgressEvent.Set();

-  WaitEvent.Lock();

-  return Result;

-}

-

diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
deleted file mode 100644
index d414958..0000000
--- a/CPP/7zip/Archive/Common/CrossThreadProgress.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// CrossThreadProgress.h

-

-#ifndef __CROSSTHREADPROGRESS_H

-#define __CROSSTHREADPROGRESS_H

-

-#include "../../ICoder.h"

-#include "../../../Windows/Synchronization.h"

-#include "../../../Common/MyCom.h"

-

-class CCrossThreadProgress:

-  public ICompressProgressInfo,

-  public CMyUnknownImp

-{

-public:

-  const UInt64 *InSize;

-  const UInt64 *OutSize;

-  HRESULT Result;

-  NWindows::NSynchronization::CAutoResetEvent ProgressEvent;

-  NWindows::NSynchronization::CAutoResetEvent WaitEvent;

-

-  HRes Create()

-  {

-    RINOK(ProgressEvent.CreateIfNotCreated());

-    return WaitEvent.CreateIfNotCreated();

-  }

-  void Init()

-  {

-    ProgressEvent.Reset();

-    WaitEvent.Reset();

-  }

-

-  MY_UNKNOWN_IMP

-

-  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

-};

-

-#endif

diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 2c920bc..3200fd2 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -29,6 +29,7 @@
   UInt32 level = _level;

   if (level != (UInt32)(Int32)-1)

     SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);

+  

   #ifndef _7ZIP_ST

   SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

   #endif

@@ -41,6 +42,8 @@
   #endif

   

   _level = (UInt32)(Int32)-1;

+  _analysisLevel = -1;

+

   _autoFilter = true;

   _crcSize = 4;

   _filterMethod.Clear();

@@ -60,8 +63,17 @@
     _level = 9;

     return ParsePropToUInt32(name, value, _level);

   }

+

+  if (name.IsPrefixedBy_Ascii_NoCase("yx"))

+  {

+    name.Delete(0, 2);

+    UInt32 v = 9;

+    RINOK(ParsePropToUInt32(name, value, v));

+    _analysisLevel = (int)v;

+    return S_OK;

+  }

   

-  if (name == L"crc")

+  if (name.IsEqualTo("crc"))

   {

     name.Delete(0, 3);

     _crcSize = 4;

@@ -69,15 +81,16 @@
   }

   

   UInt32 number;

-  int index = ParseStringToUInt32(name, number);

+  unsigned index = ParseStringToUInt32(name, number);

   UString realName = name.Ptr(index);

   if (index == 0)

   {

-    if (name.IsPrefixedBy(L"mt"))

+    if (name.IsPrefixedBy_Ascii_NoCase("mt"))

     {

       #ifndef _7ZIP_ST

       RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));

       #endif

+      

       return S_OK;

     }

     if (name.IsEqualTo("f"))

@@ -87,7 +100,7 @@
         return res;

       if (value.vt != VT_BSTR)

         return E_INVALIDARG;

-      return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);

+      return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);

     }

     number = 0;

   }

@@ -101,14 +114,15 @@
 void CSingleMethodProps::Init()

 {

   Clear();

+  _level = (UInt32)(Int32)-1;

+  

   #ifndef _7ZIP_ST

   _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();

-  AddNumThreadsProp(_numThreads);

+  AddProp_NumThreads(_numThreads);

   #endif

-  _level = (UInt32)(Int32)-1;

 }

 

-HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

+HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)

 {

   Init();

   for (UInt32 i = 0; i < numProps; i++)

@@ -123,17 +137,19 @@
       UInt32 a = 9;

       RINOK(ParsePropToUInt32(name.Ptr(1), value, a));

       _level = a;

-      AddLevelProp(a);

+      AddProp_Level(a);

     }

-    else if (name.IsPrefixedBy(L"mt"))

+    else if (name.IsPrefixedBy_Ascii_NoCase("mt"))

     {

       #ifndef _7ZIP_ST

       RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));

-      AddNumThreadsProp(_numThreads);

+      AddProp_NumThreads(_numThreads);

       #endif

     }

     else

-      return ParseMethodFromPROPVARIANT(names[i], value);

+    {

+      RINOK(ParseMethodFromPROPVARIANT(names[i], value));

+    }

   }

   return S_OK;

 }

diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 8fc3d26..44dee09 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -10,6 +10,7 @@
 class CMultiMethodProps

 {

   UInt32 _level;

+  int _analysisLevel;

 public:

   #ifndef _7ZIP_ST

   UInt32 _numThreads;

@@ -37,6 +38,7 @@
   }

 

   int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }

+  int GetAnalysisLevel() const { return _analysisLevel; }

 

   void Init();

 

@@ -57,7 +59,7 @@
   void Init();

   CSingleMethodProps() { Init(); }

   int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }

-  HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);

+  HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);

 };

 

 }

diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
index 3613ab2..39d1521 100644
--- a/CPP/7zip/Archive/Common/MultiStream.cpp
+++ b/CPP/7zip/Archive/Common/MultiStream.cpp
@@ -119,9 +119,9 @@
 /*

 STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  if(processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

-  while(size > 0)

+  while (size > 0)

   {

     if (_streamIndex >= Streams.Size())

     {

@@ -157,7 +157,7 @@
     _absPos += realProcessed;

     if (_absPos > _length)

       _length = _absPos;

-    if(processedSize != NULL)

+    if (processedSize)

       *processedSize += realProcessed;

     if (subStream.Pos == subStream.Size)

     {

diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
index 4267d46..c43e72a 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)

@@ -16,12 +18,15 @@
 #include "../ICoder.h"

 #include "../IPassword.h"

 

+#include "../Common/CreateCoder.h"

+

 #include "IArchive.h"

 

 HINSTANCE g_hInstance;

 

 #define NT_CHECK_FAIL_ACTION return FALSE;

 

+#ifdef _WIN32

 extern "C"

 BOOL WINAPI DllMain(

   #ifdef UNDER_CE

@@ -33,23 +38,29 @@
 {

   if (dwReason == DLL_PROCESS_ATTACH)

   {

+    // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH");

     g_hInstance = (HINSTANCE)hInstance;

     NT_CHECK;

   }

+  /*

+  if (dwReason == DLL_PROCESS_DETACH)

+  {

+    OutputDebugStringA("7z.dll DLL_PROCESS_DETACH");

+  }

+  */

   return TRUE;

 }

+#endif

 

 DEFINE_GUID(CLSID_CArchiveHandler,

-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

-

-static const UInt16 kDecodeId = 0x2790;

-

-DEFINE_GUID(CLSID_CCodec,

-0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);

+    k_7zip_GUID_Data1,

+    k_7zip_GUID_Data2,

+    k_7zip_GUID_Data3_Common,

+    0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

 

 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);

 STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);

-STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);

+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);

 

 STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)

 {

@@ -80,3 +91,32 @@
   g_CaseSensitive = (caseSensitive != 0);

   return S_OK;

 }

+

+#ifdef EXTERNAL_CODECS

+

+CExternalCodecs g_ExternalCodecs;

+

+STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)

+{

+  COM_TRY_BEGIN

+

+  // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");

+  if (compressCodecsInfo)

+  {

+    g_ExternalCodecs.GetCodecs = compressCodecsInfo;

+    return g_ExternalCodecs.Load();

+  }

+  g_ExternalCodecs.ClearAndRelease();

+  return S_OK;

+

+  COM_TRY_END

+}

+

+#else

+

+STDAPI SetCodecs(ICompressCodecsInfo *)

+{

+  return S_OK;

+}

+

+#endif

diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index 5e831c9..5c0957e 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -82,10 +82,22 @@
         kUnexpectedEnd,

         kDataAfterEnd,

         kIsNotArc,

-        kHeadersError

+        kHeadersError,

+        kWrongPassword

       };

     }

   }

+

+  namespace NEventIndexType

+  {

+    enum

+    {

+      kNoIndex = 0,

+      kInArcIndex,

+      kBlockIndex,

+      kOutArcIndex

+    };

+  }

   

   namespace NUpdate

   {

@@ -110,17 +122,59 @@
 };

 

 /*

-IArchiveExtractCallback::GetStream

-  Result:

+IArchiveExtractCallback::

+

+7-Zip doesn't call IArchiveExtractCallback functions

+  GetStream()

+  PrepareOperation()

+  SetOperationResult()

+from different threads simultaneously.

+But 7-Zip can call functions for IProgress or ICompressProgressInfo functions

+from another threads simultaneously with calls for IArchiveExtractCallback interface.

+

+IArchiveExtractCallback::GetStream()

+  UInt32 index - index of item in Archive

+  Int32 askExtractMode  (Extract::NAskMode)

+    if (askMode != NExtract::NAskMode::kExtract)

+    {

+      then the callee can not real stream: (*inStream == NULL)

+    }

+  

+  Out:

       (*inStream == NULL) - for directories

       (*inStream == NULL) - if link (hard link or symbolic link) was created

+      if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract)

+      {

+        then the caller must skip extracting of that file.

+      }

+

+  returns:

+    S_OK     : OK

+    S_FALSE  : data error (for decoders)

+

+if (IProgress::SetTotal() was called)

+{

+  IProgress::SetCompleted(completeValue) uses

+    packSize   - for some stream formats (xz, gz, bz2, lzma, z, ppmd).

+    unpackSize - for another formats.

+}

+else

+{

+  IProgress::SetCompleted(completeValue) uses packSize.

+}

+

+SetOperationResult()

+  7-Zip calls SetOperationResult at the end of extracting,

+  so the callee can close the file, set attributes, timestamps and security information.

+

+  Int32 opRes (NExtract::NOperationResult)

 */

 

 #define INTERFACE_IArchiveExtractCallback(x) \

   INTERFACE_IProgress(x) \

   STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \

   STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \

-  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

+  STDMETHOD(SetOperationResult)(Int32 opRes) x; \

 

 ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)

 {

@@ -128,6 +182,25 @@
 };

 

 

+

+/*

+IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object

+  by Extract() or UpdateItems() functions to report about extracting errors

+ReportExtractResult()

+  UInt32 indexType (NEventIndexType)

+  UInt32 index

+  Int32 opRes (NExtract::NOperationResult)

+*/

+

+#define INTERFACE_IArchiveExtractCallbackMessage(x) \

+  STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \

+

+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)

+{

+  INTERFACE_IArchiveExtractCallbackMessage(PURE)

+};

+

+

 #define INTERFACE_IArchiveOpenVolumeCallback(x) \

   STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \

   STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \

@@ -183,9 +256,6 @@
   Some IInArchive handlers will work incorrectly in that case.

 */

 

-/* MSVC allows the code where there is throw() in declaration of function,

-   but there is no throw() in definition of function. */

-

 #ifdef _MSC_VER

   #define MY_NO_THROW_DECL_ONLY throw()

 #else

@@ -202,7 +272,7 @@
   STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \

   STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \

   STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \

-  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x;

+  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \

 

 ARCHIVE_INTERFACE(IInArchive, 0x60)

 {

@@ -223,12 +293,14 @@
   const UInt32 kMask_ZeroEnd   = 1 << 4;

   // const UInt32 kMask_BigEndian = 1 << 5;

   const UInt32 kMask_Utf       = 1 << 6;

-  // const UInt32 kMask_Utf8  = kMask_Utf | 0;

+  const UInt32 kMask_Utf8  = kMask_Utf | 0;

   const UInt32 kMask_Utf16 = kMask_Utf | 1;

   // const UInt32 kMask_Utf32 = kMask_Utf | 2;

 

   const UInt32 kNotDefined = 0;

   const UInt32 kRaw = 1;

+

+  const UInt32 kUtf8z  = kMask_Utf8  | kMask_ZeroEnd;

   const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;

 };

 

@@ -324,6 +396,8 @@
   - GetStream()

   - GetProperty(kpidHardLink)

 

+SetOperationResult()

+  Int32 opRes (NExtract::NOperationResult::kOK)

 */

 

 #define INTERFACE_IArchiveUpdateCallback(x) \

@@ -348,6 +422,40 @@
   INTERFACE_IArchiveUpdateCallback2(PURE);

 };

 

+namespace NUpdateNotifyOp

+{

+  enum

+  {

+    kAdd = 0,

+    kUpdate,

+    kAnalyze,

+    kReplicate,

+    kRepack,

+    kSkip,

+    kDelete,

+    kHeader

+

+    // kNumDefined

+  };

+};

+

+/*

+IArchiveUpdateCallbackFile::ReportOperation

+  UInt32 indexType (NEventIndexType)

+  UInt32 index

+  UInt32 notifyOp (NUpdateNotifyOp)

+*/

+

+#define INTERFACE_IArchiveUpdateCallbackFile(x) \

+  STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \

+  STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \

+

+ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83)

+{

+  INTERFACE_IArchiveUpdateCallbackFile(PURE);

+};

+

+

 /*

 UpdateItems()

 -------------

@@ -382,7 +490,7 @@
 

 ARCHIVE_INTERFACE(ISetProperties, 0x03)

 {

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE;

+  STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;

 };

 

 ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)

@@ -406,12 +514,26 @@
     { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \

     *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID];  *name = 0; return S_OK; } \

 

+

+struct CStatProp

+{

+  const char *Name;

+  UInt32 PropID;

+  VARTYPE vt;

+};

+

+namespace NWindows {

+namespace NCOM {

+// PropVariant.cpp

+BSTR AllocBstrFromAscii(const char *s) throw();

+}}

+

 #define IMP_IInArchive_GetProp_WITH_NAME(k) \

   (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \

     { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \

-    const STATPROPSTG &srcItem = k[index]; \

-    *propID = srcItem.propid; *varType = srcItem.vt; \

-    if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \

+    const CStatProp &prop = k[index]; \

+    *propID = (PROPID)prop.PropID; *varType = prop.vt; \

+    *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \

 

 #define IMP_IInArchive_Props \

   STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \

diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index a372033..cd9e89a 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -9,11 +9,12 @@
 

 #include "../../Windows/PropVariant.h"

 

-#include "../Common/CreateCoder.h"

+#include "../Common/FilterCoder.h"

 #include "../Common/ProgressUtils.h"

 #include "../Common/RegisterArc.h"

 #include "../Common/StreamUtils.h"

 

+#include "../Compress/BcjCoder.h"

 #include "../Compress/LzmaDecoder.h"

 

 #include "Common/DummyOutStream.h"

@@ -75,14 +76,14 @@
 

 class CDecoder

 {

-  CMyComPtr<ICompressCoder> _lzmaDecoder;

   CMyComPtr<ISequentialOutStream> _bcjStream;

+  CFilterCoder *_filterCoder;

+  CMyComPtr<ICompressCoder> _lzmaDecoder;

 public:

   NCompress::NLzma::CDecoder *_lzmaDecoderSpec;

 

   ~CDecoder();

-  HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS

-      bool filtered, ISequentialInStream *inStream);

+  HRESULT Create(bool filtered, ISequentialInStream *inStream);

 

   HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);

 

@@ -94,11 +95,7 @@
     { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }

 };

 

-static const UInt32 k_BCJ = 0x03030103;

-  

-HRESULT CDecoder::Create(

-    DECL_EXTERNAL_CODECS_LOC_VARS

-    bool filteredMode, ISequentialInStream *inStream)

+HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)

 {

   if (!_lzmaDecoder)

   {

@@ -111,13 +108,10 @@
   {

     if (!_bcjStream)

     {

-      CMyComPtr<ICompressCoder> coder;

-      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));

-      if (!coder)

-        return E_NOTIMPL;

-      coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);

-      if (!_bcjStream)

-        return E_NOTIMPL;

+      _filterCoder = new CFilterCoder(false);

+      CMyComPtr<ICompressCoder> coder = _filterCoder;

+      _filterCoder->Filter = new NCompress::NBcj::CCoder(false);

+      _bcjStream = _filterCoder;

     }

   }

 

@@ -143,17 +137,13 @@
     RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));

   }

 

-  CMyComPtr<ICompressSetOutStream> setOutStream;

-

   bool filteredMode = (header.FilterID == 1);

 

   if (filteredMode)

   {

-    _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);

-    if (!setOutStream)

-      return E_NOTIMPL;

-    RINOK(setOutStream->SetOutStream(outStream));

+    RINOK(_filterCoder->SetOutStream(outStream));

     outStream = _bcjStream;

+    RINOK(_filterCoder->SetOutStreamSize(NULL));

   }

 

   const UInt64 *Size = header.HasSize() ? &header.Size : NULL;

@@ -161,18 +151,16 @@
 

   if (filteredMode)

   {

-    CMyComPtr<IOutStreamFlush> flush;

-    _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);

-    if (flush)

     {

-      HRESULT res2 = flush->Flush();

+      HRESULT res2 = _filterCoder->OutStreamFinish();

       if (res == S_OK)

         res = res2;

     }

-    HRESULT res2 = setOutStream->ReleaseOutStream();

+    HRESULT res2 = _filterCoder->ReleaseOutStream();

     if (res == S_OK)

       res = res2;

   }

+  

   RINOK(res);

 

   if (header.HasSize())

@@ -186,7 +174,6 @@
 class CHandler:

   public IInArchive,

   public IArchiveOpenSeq,

-  PUBLIC_ISetCompressCodecsInfo

   public CMyUnknownImp

 {

   CHeader _header;

@@ -210,15 +197,8 @@
   UInt64 _unpackSize;

   UInt64 _numStreams;

 

-  DECL_EXTERNAL_CODECS_VARS

-  DECL_ISetCompressCodecsInfo

-

 public:

-  MY_QUERYINTERFACE_BEGIN2(IInArchive)

-  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)

-  QUERY_ENTRY_ISetCompressCodecsInfo

-  MY_QUERYINTERFACE_END

-  MY_ADDREF_RELEASE

+  MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)

 

   INTERFACE_IInArchive(;)

   STDMETHOD(OpenSeq)(ISequentialInStream *stream);

@@ -427,6 +407,7 @@
     Int32 testMode, IArchiveExtractCallback *extractCallback)

 {

   COM_TRY_BEGIN

+

   if (numItems == 0)

     return S_OK;

   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))

@@ -466,9 +447,7 @@
     _needSeekToStart = true;

 

   CDecoder decoder;

-  HRESULT result = decoder.Create(

-      EXTERNAL_CODECS_VARS

-      _lzma86, _seqStream);

+  HRESULT result = decoder.Create(_lzma86, _seqStream);

   RINOK(result);

  

   bool firstItem = true;

@@ -562,43 +541,33 @@
 

   outStream.Release();

   return extractCallback->SetOperationResult(opResult);

+

   COM_TRY_END

 }

 

-IMPL_ISetCompressCodecsInfo

-

 namespace NLzmaAr {

 

-IMP_CreateArcIn_2(CHandler(false))

+// 2, { 0x5D, 0x00 },

 

-static CArcInfo g_ArcInfo =

-  { "lzma", "lzma", 0, 0xA,

-  0, { 0 },

-  // 2, { 0x5D, 0x00 },

+REGISTER_ARC_I_CLS_NO_SIG(

+  CHandler(false),

+  "lzma", "lzma", 0, 0xA,

   0,

   NArcInfoFlags::kStartOpen |

   NArcInfoFlags::kKeepName,

-  CreateArc, NULL,

-  IsArc_Lzma };

-

-REGISTER_ARC(Lzma)

-

+  IsArc_Lzma)

+ 

 }

 

 namespace NLzma86Ar {

 

-IMP_CreateArcIn_2(CHandler(true))

-

-static CArcInfo g_ArcInfo =

-  { "lzma86", "lzma86", 0, 0xB,

-  0, { 0 },

+REGISTER_ARC_I_CLS_NO_SIG(

+  CHandler(true),

+  "lzma86", "lzma86", 0, 0xB,

   0,

   NArcInfoFlags::kKeepName,

-  CreateArc, NULL,

-  IsArc_Lzma86 };

-

-REGISTER_ARC(Lzma86)

-

+  IsArc_Lzma86)

+ 

 }

 

 }}

diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index 47829f3..f20680d 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -71,68 +71,53 @@
   UString _changedPart;

   bool _splitStyle;

   

-  UString GetNextName()

+  bool GetNextName(UString &s)

   {

-    UString newName;

-    if (_splitStyle)

     {

-      int i;

-      int numLetters = _changedPart.Len();

-      for (i = numLetters - 1; i >= 0; i--)

+      unsigned i = _changedPart.Len();

+      for (;;)

       {

-        wchar_t c = _changedPart[i];

-        if (c == 'z')

+        wchar_t c = _changedPart[--i];

+        

+        if (_splitStyle)

         {

-          newName.InsertAtFront('a');

-          continue;

+          if (c == 'z')

+          {

+            _changedPart.ReplaceOneCharAtPos(i, L'a');

+            if (i == 0)

+              return false;

+            continue;

+          }

+          else if (c == 'Z')

+          {

+            _changedPart.ReplaceOneCharAtPos(i, L'A');

+            if (i == 0)

+              return false;

+            continue;

+          }

         }

-        else if (c == 'Z')

+        else

         {

-          newName.InsertAtFront('A');

-          continue;

+          if (c == '9')

+          {

+            _changedPart.ReplaceOneCharAtPos(i, L'0');

+            if (i == 0)

+            {

+              _changedPart.InsertAtFront(L'1');

+              break;

+            }

+            continue;

+          }

         }

+

         c++;

-        if ((c == 'z' || c == 'Z') && i == 0)

-        {

-          _unchangedPart += c;

-          wchar_t newChar = (c == 'z') ? L'a' : L'A';

-          newName.Empty();

-          numLetters++;

-          for (int k = 0; k < numLetters; k++)

-            newName += newChar;

-          break;

-        }

-        newName.InsertAtFront(c);

-        i--;

-        for (; i >= 0; i--)

-          newName.InsertAtFront(_changedPart[i]);

+        _changedPart.ReplaceOneCharAtPos(i, c);

         break;

       }

     }

-    else

-    {

-      int i;

-      int numLetters = _changedPart.Len();

-      for (i = numLetters - 1; i >= 0; i--)

-      {

-        wchar_t c = _changedPart[i];

-        if (c == '9')

-        {

-          newName.InsertAtFront('0');

-          if (i == 0)

-            newName.InsertAtFront('1');

-          continue;

-        }

-        c++;

-        newName.InsertAtFront(c);

-        i--;

-        for (; i >= 0; i--)

-          newName.InsertAtFront(_changedPart[i]);

-        break;

-      }

-    }

-    _changedPart = newName;

-    return _unchangedPart + _changedPart;

+    

+    s = _unchangedPart + _changedPart;

+    return true;

   }

 };

 

@@ -156,7 +141,7 @@
     name = prop.bstrVal;

   }

   

-  int dotPos = name.ReverseFind('.');

+  int dotPos = name.ReverseFind_Dot();

   const UString prefix = name.Left(dotPos + 1);

   const UString ext = name.Ptr(dotPos + 1);

   UString ext2 = ext;

@@ -196,17 +181,21 @@
   seqName._splitStyle = splitStyle;

   

   if (prefix.Len() < 1)

-    _subName = L"file";

+    _subName.SetFromAscii("file");

   else

     _subName.SetFrom(prefix, prefix.Len() - 1);

   

   UInt64 size;

   {

+    /*

     NCOM::CPropVariant prop;

     RINOK(volumeCallback->GetProperty(kpidSize, &prop));

     if (prop.vt != VT_UI8)

       return E_INVALIDARG;

     size = prop.uhVal.QuadPart;

+    */

+    RINOK(stream->Seek(0, STREAM_SEEK_END, &size));

+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

   }

   

   _totalSize += size;

@@ -214,33 +203,39 @@
   _streams.Add(stream);

   

   {

-    UInt64 numFiles = _streams.Size();

+    const UInt64 numFiles = _streams.Size();

     RINOK(callback->SetCompleted(&numFiles, NULL));

   }

   

   for (;;)

   {

-    const UString fullName = seqName.GetNextName();

+    UString fullName;

+    if (!seqName.GetNextName(fullName))

+      break;

     CMyComPtr<IInStream> nextStream;

     HRESULT result = volumeCallback->GetStream(fullName, &nextStream);

     if (result == S_FALSE)

       break;

     if (result != S_OK)

       return result;

-    if (!stream)

+    if (!nextStream)

       break;

     {

+      /*

       NCOM::CPropVariant prop;

       RINOK(volumeCallback->GetProperty(kpidSize, &prop));

       if (prop.vt != VT_UI8)

         return E_INVALIDARG;

       size = prop.uhVal.QuadPart;

+      */

+      RINOK(nextStream->Seek(0, STREAM_SEEK_END, &size));

+      RINOK(nextStream->Seek(0, STREAM_SEEK_SET, NULL));

     }

     _totalSize += size;

     _sizes.Add(size);

     _streams.Add(nextStream);

     {

-      UInt64 numFiles = _streams.Size();

+      const UInt64 numFiles = _streams.Size();

       RINOK(callback->SetCompleted(&numFiles, NULL));

     }

   }

@@ -355,15 +350,10 @@
   COM_TRY_END

 }

 

-IMP_CreateArcIn

-

-static CArcInfo g_ArcInfo =

-  { "Split", "001", 0, 0xEA,

-  0, { 0 },

+REGISTER_ARC_I_NO_SIG(

+  "Split", "001", 0, 0xEA,

   0,

   0,

-  CreateArc };

-

-REGISTER_ARC(Split)

+  NULL)

 

 }}

diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index e787c16..5616aa1 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -10,6 +10,8 @@
 #include "../../Common/Defs.h"

 #include "../../Common/IntToString.h"

 

+#include "../../Windows/PropVariant.h"

+

 #include "../ICoder.h"

 

 #include "../Common/CWrappers.h"

@@ -21,7 +23,11 @@
 

 #include "IArchive.h"

 

+#ifndef EXTRACT_ONLY

 #include "Common/HandlerOut.h"

+#endif

+

+#include "XzHandler.h"

 

 using namespace NWindows;

 

@@ -32,92 +38,36 @@
 

 }}

 

-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

-static void SzFree(void *, void *address) { MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 namespace NArchive {

 namespace NXz {

 

 struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;

 

-static const wchar_t *k_LZMA2_Name = L"LZMA2";

+static const char *k_LZMA2_Name = "LZMA2";

 

-struct CStatInfo

+void CStatInfo::Clear()

 {

-  UInt64 InSize;

-  UInt64 OutSize;

-  UInt64 PhySize;

-

-  UInt64 NumStreams;

-  UInt64 NumBlocks;

-

-  bool UnpackSize_Defined;

-

-  bool NumStreams_Defined;

-  bool NumBlocks_Defined;

-

-  bool IsArc;

-  bool UnexpectedEnd;

-  bool DataAfterEnd;

-  bool Unsupported;

-  bool HeadersError;

-  bool DataError;

-  bool CrcError;

-

-  CStatInfo() { Clear();   }

-

-  void Clear()

-  {

-    InSize = 0;

-    OutSize = 0;

-    PhySize = 0;

-

-    NumStreams = 0;

-    NumBlocks = 0;

-

-    UnpackSize_Defined = false;

+  InSize = 0;

+  OutSize = 0;

+  PhySize = 0;

   

-    NumStreams_Defined = false;

-    NumBlocks_Defined = false;

-    

-    UnexpectedEnd = false;

-    DataAfterEnd = false;

-    Unsupported = false;

-    HeadersError = false;

-    DataError = false;

-    CrcError = false;

-    IsArc = false;

-  }

-

-};

-

-struct IDecodeState: public CStatInfo

-{

-  SRes DecodeRes;

-

-  IDecodeState(): DecodeRes(SZ_OK) {}

-  virtual HRESULT Progress() = 0;

-

-  HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream);

-};

-

-struct CVirtProgress_To_LocalProgress: public IDecodeState

-{

-  CLocalProgress *lps;

-  CMyComPtr<ICompressProgressInfo> progress;

-

-  HRESULT Progress();

-};

-

-HRESULT CVirtProgress_To_LocalProgress::Progress()

-{

-  lps->InSize = InSize;

-  lps->OutSize = OutSize;

-  return lps->SetCur();

+  NumStreams = 0;

+  NumBlocks = 0;

+  

+  UnpackSize_Defined = false;

+  

+  NumStreams_Defined = false;

+  NumBlocks_Defined = false;

+  

+  IsArc = false;

+  UnexpectedEnd = false;

+  DataAfterEnd = false;

+  Unsupported = false;

+  HeadersError = false;

+  DataError = false;

+  CrcError = false;

 }

 

-

 class CHandler:

   public IInArchive,

   public IArchiveOpenSeq,

@@ -137,21 +87,27 @@
   CMyComPtr<IInStream> _stream;

   CMyComPtr<ISequentialInStream> _seqStream;

 

-  UInt32 _filterId;

   AString _methodsString;

 

+  #ifndef EXTRACT_ONLY

+

+  UInt32 _filterId;

+

   void Init()

   {

     _filterId = 0;

     CMultiMethodProps::Init();

   }

+  

+  #endif

 

   HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);

 

-  HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress)

+  HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,

+      CDecoder &decoder, ICompressProgressInfo *progress)

   {

-    RINOK(progress.Decode(seqInStream, outStream));

-    _stat = progress;

+    RINOK(decoder.Decode(seqInStream, outStream, progress));

+    _stat = decoder;

     _phySize_Defined = true;

     return S_OK;

   }

@@ -171,7 +127,7 @@
 

   #ifndef EXTRACT_ONLY

   INTERFACE_IOutArchive(;)

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);

+  STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);

   #endif

 

   CHandler();

@@ -179,9 +135,12 @@
 

 CHandler::CHandler()

 {

+  #ifndef EXTRACT_ONLY

   Init();

+  #endif

 }

 

+

 static const Byte kProps[] =

 {

   kpidSize,

@@ -295,12 +254,11 @@
 

 static void AddString(AString &dest, const AString &src)

 {

-  if (!dest.IsEmpty())

-    dest += ' ';

+  dest.Add_Space_if_NotEmpty();

   dest += src;

 }

 

-static const char *kChecks[] =

+static const char * const kChecks[] =

 {

     "NoCheck"

   , "CRC32"

@@ -405,7 +363,8 @@
 static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)

 {

   COpenCallbackWrap *p = (COpenCallbackWrap *)pp;

-  p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);

+  if (p->OpenCallback)

+    p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);

   return (SRes)p->Res;

 }

 

@@ -423,26 +382,6 @@
   ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }

 };

 

-

-struct CVirtProgress_To_OpenProgress: public IDecodeState

-{

-  IArchiveOpenCallback *Callback;

-  UInt64 Offset;

-

-  HRESULT Progress();

-};

-

-HRESULT CVirtProgress_To_OpenProgress::Progress()

-{

-  if (Callback)

-  {

-    UInt64 files = 0;

-    UInt64 value = Offset + InSize;

-    return Callback->SetCompleted(&files, &value);

-  }

-  return S_OK;

-}

-

 static HRESULT SRes_to_Open_HRESULT(SRes res)

 {

   switch (res)

@@ -488,7 +427,10 @@
   }

 

   RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize));

-  RINOK(callback->SetTotal(NULL, &_stat.PhySize));

+  if (callback)

+  {

+    RINOK(callback->SetTotal(NULL, &_stat.PhySize));

+  }

 

   CSeekInStreamWrap inStreamImp(inStream);

 

@@ -527,6 +469,7 @@
   {

     res = SZ_OK;

   }

+

   RINOK(SRes_to_Open_HRESULT(res));

   _stream = inStream;

   _seqStream = inStream;

@@ -539,7 +482,7 @@
   COM_TRY_BEGIN

   {

     Close();

-    return Open2(inStream, /* 0, */ callback);

+    return Open2(inStream, callback);

   }

   COM_TRY_END

 }

@@ -587,38 +530,32 @@
 

 STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }

 

-struct CXzUnpackerCPP

+CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)

 {

-  Byte *InBuf;

-  Byte *OutBuf;

-  CXzUnpacker p;

-  

-  CXzUnpackerCPP(): InBuf(0), OutBuf(0)

-  {

-    XzUnpacker_Construct(&p, &g_Alloc);

-  }

-  ~CXzUnpackerCPP()

-  {

-    XzUnpacker_Free(&p);

-    MyFree(InBuf);

-    MyFree(OutBuf);

-  }

-};

+  XzUnpacker_Construct(&p, &g_Alloc);

+}

 

-HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream)

+CXzUnpackerCPP::~CXzUnpackerCPP()

+{

+  XzUnpacker_Free(&p);

+  MyFree(InBuf);

+  MyFree(OutBuf);

+}

+

+HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)

 {

   const size_t kInBufSize = 1 << 15;

   const size_t kOutBufSize = 1 << 21;

 

+  Clear();

   DecodeRes = SZ_OK;

 

-  CXzUnpackerCPP xzu;

   XzUnpacker_Init(&xzu.p);

-  xzu.InBuf = (Byte *)MyAlloc(kInBufSize);

-  xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);

-  if (!xzu.InBuf || !xzu.OutBuf)

-    return E_OUTOFMEMORY;

-

+  if (!xzu.InBuf)

+    xzu.InBuf = (Byte *)MyAlloc(kInBufSize);

+  if (!xzu.OutBuf)

+    xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);

+  

   UInt32 inSize = 0;

   SizeT inPos = 0;

   SizeT outPos = 0;

@@ -664,7 +601,10 @@
     else

       outPos = 0;

     

-    RINOK(Progress());

+    if (progress)

+    {

+      RINOK(progress->SetRatioInfo(&InSize, &OutSize));

+    }

     

     if (finished)

     {

@@ -730,6 +670,30 @@
   return S_OK;

 }

 

+Int32 CDecoder::Get_Extract_OperationResult() const

+{

+  Int32 opRes;

+  if (!IsArc)

+    opRes = NExtract::NOperationResult::kIsNotArc;

+  else if (UnexpectedEnd)

+    opRes = NExtract::NOperationResult::kUnexpectedEnd;

+  else if (DataAfterEnd)

+    opRes = NExtract::NOperationResult::kDataAfterEnd;

+  else if (CrcError)

+    opRes = NExtract::NOperationResult::kCRCError;

+  else if (Unsupported)

+    opRes = NExtract::NOperationResult::kUnsupportedMethod;

+  else if (HeadersError)

+    opRes = NExtract::NOperationResult::kDataError;

+  else if (DataError)

+    opRes = NExtract::NOperationResult::kDataError;

+  else if (DecodeRes != SZ_OK)

+    opRes = NExtract::NOperationResult::kDataError;

+  else

+    opRes = NExtract::NOperationResult::kOK;

+  return opRes;

+}

+

 STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

     Int32 testMode, IArchiveExtractCallback *extractCallback)

 {

@@ -739,7 +703,9 @@
   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))

     return E_INVALIDARG;

 

-  extractCallback->SetTotal(_stat.PhySize);

+  if (_phySize_Defined)

+    extractCallback->SetTotal(_stat.PhySize);

+

   UInt64 currentTotalPacked = 0;

   RINOK(extractCallback->SetCompleted(&currentTotalPacked));

   CMyComPtr<ISequentialOutStream> realOutStream;

@@ -754,11 +720,9 @@
 

   extractCallback->PrepareOperation(askMode);

 

-  CVirtProgress_To_LocalProgress vp;

-  vp.lps = new CLocalProgress;

-  vp.progress = vp.lps;

-  vp.lps->Init(extractCallback, true);

-

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> lpsRef = lps;

+  lps->Init(extractCallback, true);

 

   if (_needSeekToStart)

   {

@@ -769,28 +733,9 @@
   else

     _needSeekToStart = true;

 

-  RINOK(Decode2(_seqStream, realOutStream, vp));

-

-  Int32 opRes;

-

-  if (!vp.IsArc)

-    opRes = NExtract::NOperationResult::kIsNotArc;

-  else if (vp.UnexpectedEnd)

-    opRes = NExtract::NOperationResult::kUnexpectedEnd;

-  else if (vp.DataAfterEnd)

-    opRes = NExtract::NOperationResult::kDataAfterEnd;

-  else if (vp.CrcError)

-    opRes = NExtract::NOperationResult::kCRCError;

-  else if (vp.Unsupported)

-    opRes = NExtract::NOperationResult::kUnsupportedMethod;

-  else if (vp.HeadersError)

-    opRes = NExtract::NOperationResult::kDataError;

-  else if (vp.DataError)

-    opRes = NExtract::NOperationResult::kDataError;

-  else if (vp.DecodeRes != SZ_OK)

-    opRes = NExtract::NOperationResult::kDataError;

-  else

-    opRes = NExtract::NOperationResult::kOK;

+  CDecoder decoder;

+  RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));

+  Int32 opRes = decoder.Get_Extract_OperationResult();

 

   realOutStream.Release();

   return extractCallback->SetOperationResult(opRes);

@@ -808,6 +753,8 @@
 STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,

     IArchiveUpdateCallback *updateCallback)

 {

+  COM_TRY_BEGIN

+

   CSeqOutStreamWrap seqOutStream(outStream);

   

   if (numItems == 0)

@@ -927,16 +874,37 @@
       return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);

     return SResToHRESULT(res);

   }

+

   if (indexInArchive != 0)

     return E_INVALIDARG;

+

+  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;

+  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);

+  if (opCallback)

+  {

+    RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate))

+  }

+

   if (_stream)

+  {

+    if (_phySize_Defined)

+      RINOK(updateCallback->SetTotal(_stat.PhySize));

     RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));

-  return NCompress::CopyStream(_stream, outStream, NULL);

+  }

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(updateCallback, true);

+

+  return NCompress::CopyStream(_stream, outStream, progress);

+

+  COM_TRY_END

 }

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

+

   Init();

   for (UInt32 i = 0; i < numProps; i++)

   {

@@ -964,28 +932,25 @@
     return E_INVALIDARG;

   if (_methods.Size() == 1)

   {

-    UString &methodName = _methods[0].MethodName;

+    AString &methodName = _methods[0].MethodName;

     if (methodName.IsEmpty())

       methodName = k_LZMA2_Name;

-    else if (!methodName.IsEqualToNoCase(k_LZMA2_Name))

+    else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name))

       return E_INVALIDARG;

   }

+  

   return S_OK;

+

   COM_TRY_END

 }

 

 #endif

 

-IMP_CreateArcIn

-IMP_CreateArcOut

-

-static CArcInfo g_ArcInfo =

-  { "xz", "xz txz", "* .tar", 0xC,

-  6, { 0xFD, '7' , 'z', 'X', 'Z', 0 },

+REGISTER_ARC_IO(

+  "xz", "xz txz", "* .tar", 0xC,

+  XZ_SIG,

   0,

   NArcInfoFlags::kKeepName,

-  REF_CreateArc_Pair };

-

-REGISTER_ARC(xz)

+  NULL)

 

 }}

diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h
new file mode 100644
index 0000000..a61d4f7
--- /dev/null
+++ b/CPP/7zip/Archive/XzHandler.h
@@ -0,0 +1,65 @@
+// XzHandler.h

+

+#ifndef __XZ_HANDLER_H

+#define __XZ_HANDLER_H

+

+#include "../../../C/Xz.h"

+

+#include "../ICoder.h"

+

+namespace NArchive {

+namespace NXz {

+ 

+struct CXzUnpackerCPP

+{

+  Byte *InBuf;

+  Byte *OutBuf;

+  CXzUnpacker p;

+  

+  CXzUnpackerCPP();

+  ~CXzUnpackerCPP();

+};

+

+struct CStatInfo

+{

+  UInt64 InSize;

+  UInt64 OutSize;

+  UInt64 PhySize;

+

+  UInt64 NumStreams;

+  UInt64 NumBlocks;

+

+  bool UnpackSize_Defined;

+

+  bool NumStreams_Defined;

+  bool NumBlocks_Defined;

+

+  bool IsArc;

+  bool UnexpectedEnd;

+  bool DataAfterEnd;

+  bool Unsupported;

+  bool HeadersError;

+  bool DataError;

+  bool CrcError;

+

+  CStatInfo() { Clear(); }

+

+  void Clear();

+};

+

+struct CDecoder: public CStatInfo

+{

+  CXzUnpackerCPP xzu;

+  SRes DecodeRes; // it's not HRESULT

+

+  CDecoder(): DecodeRes(SZ_OK) {}

+

+  /* Decode() can return ERROR code only if there is progress or stream error.

+     Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */

+  HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress);

+  Int32 Get_Extract_OperationResult() const;

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
index f96ad74..37c059d 100644
--- a/CPP/7zip/Bundles/Alone7z/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -44,7 +44,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

-# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /FAc /Yu"StdAfx.h" /FD /c

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -69,7 +69,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c

-# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c

+# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -94,7 +94,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c

-# ADD CPP /nologo /Gz /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -121,7 +121,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c

-# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c

+# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -546,14 +546,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Common\CWrappers.cpp

 # End Source File

 # Begin Source File

@@ -738,14 +730,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Compress\BranchCoder.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Compress\BranchCoder.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Compress\BranchMisc.cpp

 # End Source File

 # Begin Source File

@@ -820,14 +804,6 @@
 

 SOURCE=..\..\Compress\LzmaRegister.cpp

 # End Source File

-# Begin Source File

-

-SOURCE=..\..\Compress\RangeCoder.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Compress\RangeCoderBit.h

-# End Source File

 # End Group

 # Begin Group "Archive"

 

@@ -873,14 +849,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\7z\7zFolderOutStream.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\7z\7zHandler.cpp

 # End Source File

 # Begin Source File

@@ -961,14 +929,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CoderMixer2MT.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\Common\DummyOutStream.cpp

 # End Source File

 # Begin Source File

@@ -1026,6 +986,10 @@
 # End Group

 # Begin Source File

 

+SOURCE=..\..\Archive\IArchive.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Archive\LzmaHandler.cpp

 # End Source File

 # Begin Source File

@@ -1526,6 +1490,58 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Bcj2.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bcj2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bcj2Enc.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Bra.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
index c68a42e..814ccb7 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -48,7 +48,6 @@
   $O\InOutTempBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\MethodId.obj \

   $O\MethodProps.obj \

   $O\OffsetStream.obj \

@@ -68,8 +67,6 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\DummyOutStream.obj \

   $O\HandlerOut.obj \

   $O\InStreamWithCRC.obj \

@@ -85,7 +82,6 @@
   $O\7zEncode.obj \

   $O\7zExtract.obj \

   $O\7zFolderInStream.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zHandlerOut.obj \

   $O\7zHeader.obj \

@@ -101,7 +97,6 @@
   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

-  $O\BranchCoder.obj \

   $O\BranchMisc.obj \

   $O\BranchRegister.obj \

   $O\ByteSwap.obj \

@@ -125,6 +120,8 @@
 C_OBJS = \

   $O\7zStream.obj \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

+  $O\Bcj2Enc.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

   $O\BraIA64.obj \

diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
index 0b2f581..d34ab46 100644
--- a/CPP/7zip/Bundles/Format7zExtractR/makefile
+++ b/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -26,7 +26,6 @@
   $O\InBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\MethodId.obj \

   $O\MethodProps.obj \

   $O\OutBuffer.obj \

@@ -43,8 +42,6 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\HandlerOut.obj \

   $O\ItemNameUtils.obj \

   $O\OutStreamWithCRC.obj \

@@ -55,7 +52,6 @@
   $O\7zCompressionMode.obj \

   $O\7zDecode.obj \

   $O\7zExtract.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zHeader.obj \

   $O\7zIn.obj \

@@ -69,7 +65,6 @@
   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

-  $O\BranchCoder.obj \

   $O\BranchMisc.obj \

   $O\BranchRegister.obj \

   $O\ByteSwap.obj \

@@ -83,6 +78,7 @@
 

 C_OBJS = \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

   $O\BraIA64.obj \

diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
index 0e885c0..cd63c72 100644
--- a/CPP/7zip/Bundles/Format7zR/makefile
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -30,7 +30,6 @@
   $O\InOutTempBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\MethodId.obj \

   $O\MethodProps.obj \

   $O\OutBuffer.obj \

@@ -48,8 +47,6 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\HandlerOut.obj \

   $O\InStreamWithCRC.obj \

   $O\ItemNameUtils.obj \

@@ -63,7 +60,6 @@
   $O\7zEncode.obj \

   $O\7zExtract.obj \

   $O\7zFolderInStream.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zHandlerOut.obj \

   $O\7zHeader.obj \

@@ -81,7 +77,6 @@
   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

-  $O\BranchCoder.obj \

   $O\BranchMisc.obj \

   $O\BranchRegister.obj \

   $O\ByteSwap.obj \

@@ -97,6 +92,8 @@
 

 C_OBJS = \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

+  $O\Bcj2Enc.obj \

   $O\Bra.obj \

   $O\Bra86.obj \

   $O\BraIA64.obj \

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index 677fb8f..fdad478 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"

@@ -25,6 +25,7 @@
 #include "../../../Windows/System.h"

 #endif

 

+#include "../../../Common/IntToString.h"

 #include "../../../Common/CommandLineParser.h"

 #include "../../../Common/StringConvert.h"

 #include "../../../Common/StringToInt.h"

@@ -36,14 +37,41 @@
 #include "../../Compress/LzmaEncoder.h"

 

 #include "../../UI/Console/BenchCon.h"

-

+#include "../../UI/Console/ConsoleClose.h"

 

 using namespace NCommandLineParser;

 

+static const unsigned kDictSizeLog = 24;

+

+static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n";

+

+static const char *kHelpString =

+    "Usage:  LZMA <command> [inputFile] [outputFile] [<switches>...]\n"

+    "\n"

+    "<command>\n"

+    "  e : Encode file\n"

+    "  d : Decode file\n"

+    "  b : Benchmark\n"

+    "<switches>\n"

+    "  -a{N}  : set compression mode : [0, 1] : default = 1 (max)\n"

+    "  -d{N}  : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"

+    "  -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"

+    "  -mc{N} : set number of cycles for match finder\n"

+    "  -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"

+    "  -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"

+    "  -pb{N} : set number of pos bits : [0, 4] : default = 2\n"

+    "  -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"

+    "  -mt{N} : set number of CPU threads\n"

+    "  -eos   : write end of stream marker\n"

+    "  -si    : read data from stdin\n"

+    "  -so    : write data to stdout\n";

+

+

 static const char *kCantAllocate = "Can not allocate memory";

 static const char *kReadError = "Read error";

 static const char *kWriteError = "Write error";

 

+

 namespace NKey {

 enum Enum

 {

@@ -88,96 +116,220 @@
   { "F86",  NSwitchType::kChar, false, 0, "+" }

 };

 

-static void PrintMessage(const char *s)

+

+static void PrintErr(const char *s)

 {

   fputs(s, stderr);

 }

 

-static void PrintHelp()

+static void PrintErr_LF(const char *s)

 {

-  PrintMessage("\nUsage:  LZMA <e|d> inputFile outputFile [<switches>...]\n"

-             "  e: encode file\n"

-             "  d: decode file\n"

-             "  b: Benchmark\n"

-    "<Switches>\n"

-    "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n"

-    "  -d{N}:  set dictionary size - [12, 30], default: 23 (8MB)\n"

-    "  -fb{N}: set number of fast bytes - [5, 273], default: 128\n"

-    "  -mc{N}: set number of cycles for match finder\n"

-    "  -lc{N}: set number of literal context bits - [0, 8], default: 3\n"

-    "  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"

-    "  -pb{N}: set number of pos bits - [0, 4], default: 2\n"

-    "  -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"

-    "  -mt{N}: set number of CPU threads\n"

-    "  -eos:   write End Of Stream marker\n"

-    "  -si:    read data from stdin\n"

-    "  -so:    write data to stdout\n"

-    );

+  PrintErr(s);

+  fputc('\n', stderr);

 }

 

-static void PrintHelpAndExit(const char *s)

+

+static void PrintError(const char *s)

 {

-  fprintf(stderr, "\nError: %s\n\n", s);

-  PrintHelp();

-  throw -1;

+  PrintErr("\nERROR: ");

+  PrintErr_LF(s);

 }

 

+static void PrintError2(const char *s1, const wchar_t *s2)

+{

+  PrintError(s1);

+  PrintErr_LF(GetOemString(s2));

+}

+

+static void PrintError_int(const char *s, int code)

+{

+  PrintError(s);

+  char temp[32];

+  ConvertInt64ToString(code, temp);

+  PrintErr("Error code = ");

+  PrintErr_LF(temp);

+}

+

+

+

+static void Print(const char *s)

+{

+  fputs(s, stdout);

+}

+

+static void Print_UInt64(UInt64 v)

+{

+  char temp[32];

+  ConvertUInt64ToString(v, temp);

+  Print(temp);

+}

+

+static void Print_MB(UInt64 v)

+{

+  Print_UInt64(v);

+  Print(" MiB");

+}

+

+static void Print_Size(const char *s, UInt64 v)

+{

+  Print(s);

+  Print_UInt64(v);

+  Print(" (");

+  Print_MB(v >> 20);

+  Print(")\n");

+}

+

+static void PrintTitle()

+{

+  Print(kCopyrightString);

+}

+

+static void PrintHelp()

+{

+  PrintTitle();

+  Print(kHelpString);

+}

+

+class CProgressPrint:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+  UInt64 _size1;

+  UInt64 _size2;

+public:

+  CProgressPrint(): _size1(0), _size2(0) {}

+

+  void ClosePrint();

+

+  MY_UNKNOWN_IMP1(ICompressProgressInfo)

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

+#define BACK_STR \

+"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"

+static const char *kBackSpaces =

+BACK_STR

+"                                                                "

+BACK_STR;

+

+

+void CProgressPrint::ClosePrint()

+{

+  Print(kBackSpaces);

+}

+

+STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  if (inSize)

+  {

+    UInt64 v1 = *inSize >> 20;

+    UInt64 v2 = _size2;

+    if (outSize)

+      v2 = *outSize >> 20;

+    if (v1 != _size1 || v2 != _size2)

+    {

+      _size1 = v1;

+      _size2 = v2;

+      ClosePrint();

+      Print_MB(_size1);

+      Print(" -> ");

+      Print_MB(_size2);

+    }

+  }

+  return S_OK;

+}

+

+

 static void IncorrectCommand()

 {

-  PrintHelpAndExit("Incorrect command");

+  throw "Incorrect command";

 }

 

-static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings)

+static UInt32 GetNumber(const wchar_t *s)

 {

-  for (int i = 1; i < numArgs; i++)

-    strings.Add(MultiByteToUnicodeString(args[i]));

-}

-

-static bool GetNumber(const wchar_t *s, UInt32 &value)

-{

-  value = 0;

-  if (*s == 0)

-    return false;

   const wchar_t *end;

-  value = ConvertStringToUInt32(s, &end);

-  return *end == 0;

+  UInt32 v = ConvertStringToUInt32(s, &end);

+  if (*end != 0)

+    IncorrectCommand();

+  return v;

 }

 

 static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)

 {

   if (parser[index].ThereIs)

-    if (!GetNumber(parser[index].PostStrings[0], res))

-      IncorrectCommand();

+    res = GetNumber(parser[index].PostStrings[0]);

 }

 

-#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1;

 

-int main2(int numArgs, const char *args[])

+static int Error_HRESULT(const char *s, HRESULT res)

+{

+  if (res == E_ABORT)

+  {

+    Print("\n\nBreak signaled\n");

+    return 255;

+  }

+

+  PrintError(s);

+

+  if (res == E_OUTOFMEMORY)

+  {

+    PrintErr_LF(kCantAllocate);

+    return 8;

+  }

+  if (res == E_INVALIDARG)

+  {

+    PrintErr_LF("Ununsupported parameter");

+  }

+  else

+  {

+    char temp[32];

+    ConvertUInt32ToHex(res, temp);

+    PrintErr("Error code = 0x");

+    PrintErr_LF(temp);

+  }

+  return 1;

+}

+

+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;

+

+static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)

+{

+  CProperty &prop = props2.AddNew();

+  prop.Name.SetFromAscii(name);

+  prop.Value = val;

+}

+

+static int main2(int numArgs, const char *args[])

 {

   NT_CHECK

 

-  PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");

-

   if (numArgs == 1)

   {

     PrintHelp();

     return 0;

   }

 

-  bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);

+  /*

+  bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);

   if (unsupportedTypes)

-  {

-    PrintMessage("Unsupported base types. Edit Common/Types.h and recompile");

-    return 1;

-  }

+    throw "Unsupported base types. Edit Common/Types.h and recompile";

+  */

 

   UStringVector commandStrings;

-  WriteArgumentsToStringList(numArgs, args, commandStrings);

+  for (int i = 1; i < numArgs; i++)

+    commandStrings.Add(MultiByteToUnicodeString(args[i]));

   

   CParser parser(ARRAY_SIZE(kSwitchForms));

   try

   {

-    parser.ParseStrings(kSwitchForms, commandStrings);

+    if (!parser.ParseStrings(kSwitchForms, commandStrings))

+    {

+      PrintError2(parser.ErrorMessage, parser.ErrorLine);

+      return 1;

+    }

   }

   catch(...)

   {

@@ -189,40 +341,41 @@
     PrintHelp();

     return 0;

   }

-  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

+

+  bool stdInMode = parser[NKey::kStdIn].ThereIs;

+  bool stdOutMode = parser[NKey::kStdOut].ThereIs;

+

+  if (!stdOutMode)

+    PrintTitle();

+

+  const UStringVector &params = parser.NonSwitchStrings;

 

   unsigned paramIndex = 0;

-  if (paramIndex >= nonSwitchStrings.Size())

+  if (paramIndex >= params.Size())

     IncorrectCommand();

-  const UString &command = nonSwitchStrings[paramIndex++];

+  const UString &command = params[paramIndex++];

 

-  CObjectVector<CProperty> props;

+  CObjectVector<CProperty> props2;

   bool dictDefined = false;

   UInt32 dict = (UInt32)(Int32)-1;

+  

   if (parser[NKey::kDict].ThereIs)

   {

-    UInt32 dicLog;

+    UInt32 dictLog;

     const UString &s = parser[NKey::kDict].PostStrings[0];

-    if (!GetNumber(s, dicLog))

-      IncorrectCommand();

-    dict = 1 << dicLog;

+    dictLog = GetNumber(s);

+    dict = 1 << dictLog;

     dictDefined = true;

-    CProperty prop;

-    prop.Name = L"d";

-    prop.Value = s;

-    props.Add(prop);

+    AddProp(props2, "d", s);

   }

+  

   if (parser[NKey::kLevel].ThereIs)

   {

-    UInt32 level = 5;

     const UString &s = parser[NKey::kLevel].PostStrings[0];

-    if (!GetNumber(s, level))

-      IncorrectCommand();

-    CProperty prop;

-    prop.Name = L"x";

-    prop.Value = s;

-    props.Add(prop);

+    /* UInt32 level = */ GetNumber(s);

+    AddProp(props2, "x", s);

   }

+  

   UString mf = L"BT4";

   if (parser[NKey::kMatchFinder].ThereIs)

     mf = parser[NKey::kMatchFinder].PostStrings[0];

@@ -230,70 +383,64 @@
   UInt32 numThreads = (UInt32)(Int32)-1;

 

   #ifndef _7ZIP_ST

+  

   if (parser[NKey::kMultiThread].ThereIs)

   {

-    UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

     const UString &s = parser[NKey::kMultiThread].PostStrings[0];

     if (s.IsEmpty())

-      numThreads = numCPUs;

+      numThreads = NWindows::NSystem::GetNumberOfProcessors();

     else

-      if (!GetNumber(s, numThreads))

-        IncorrectCommand();

-    CProperty prop;

-    prop.Name = L"mt";

-    prop.Value = s;

-    props.Add(prop);

+      numThreads = GetNumber(s);

+    AddProp(props2, "mt", s);

   }

+  

   #endif

 

+  

   if (parser[NKey::kMethod].ThereIs)

   {

-    UString s = parser[NKey::kMethod].PostStrings[0];

+    const UString &s = parser[NKey::kMethod].PostStrings[0];

     if (s.IsEmpty() || s[0] != '=')

       IncorrectCommand();

-    CProperty prop;

-    prop.Name = L"m";

-    prop.Value = s.Ptr(1);

-    props.Add(prop);

+    AddProp(props2, "m", s.Ptr(1));

   }

 

-  if (MyStringCompareNoCase(command, L"b") == 0)

+  if (StringsAreEqualNoCase_Ascii(command, "b"))

   {

-    const UInt32 kNumDefaultItereations = 1;

-    UInt32 numIterations = kNumDefaultItereations;

-    {

-      if (paramIndex < nonSwitchStrings.Size())

-        if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))

-          numIterations = kNumDefaultItereations;

-    }

-    HRESULT res = BenchCon(props, numIterations, stderr);

-    if (res != S_OK)

-    {

-      if (res != E_ABORT)

-      {

-        PrintMessage("Benchmark Error");

-        return 1;

-      }

-    }

-    return 0;

+    UInt32 numIterations = 1;

+    if (paramIndex < params.Size())

+      numIterations = GetNumber(params[paramIndex++]);

+    if (params.Size() != paramIndex)

+      IncorrectCommand();

+  

+    HRESULT res = BenchCon(props2, numIterations, stdout);

+    

+    if (res == S_OK)

+      return 0;

+    return Error_HRESULT("Benchmark error", res);

+  }

+

+  {

+    UInt32 needParams = 3;

+    if (stdInMode) needParams--;

+    if (stdOutMode) needParams--;

+    if (needParams != params.Size())

+      IncorrectCommand();

   }

 

   if (numThreads == (UInt32)(Int32)-1)

     numThreads = 1;

 

   bool encodeMode = false;

-  if (MyStringCompareNoCase(command, L"e") == 0)

+  

+  if (StringsAreEqualNoCase_Ascii(command, "e"))

     encodeMode = true;

-  else if (MyStringCompareNoCase(command, L"d") == 0)

-    encodeMode = false;

-  else

+  else if (!StringsAreEqualNoCase_Ascii(command, "d"))

     IncorrectCommand();

 

-  bool stdInMode = parser[NKey::kStdIn].ThereIs;

-  bool stdOutMode = parser[NKey::kStdOut].ThereIs;

-

   CMyComPtr<ISequentialInStream> inStream;

-  CInFileStream *inStreamSpec = 0;

+  CInFileStream *inStreamSpec = NULL;

+  

   if (stdInMode)

   {

     inStream = new CStdInFileStream;

@@ -301,21 +448,19 @@
   }

   else

   {

-    if (paramIndex >= nonSwitchStrings.Size())

-      IncorrectCommand();

-    const UString &inputName = nonSwitchStrings[paramIndex++];

+    const UString &inputName = params[paramIndex++];

     inStreamSpec = new CInFileStream;

     inStream = inStreamSpec;

     if (!inStreamSpec->Open(us2fs(inputName)))

     {

-      fprintf(stderr, "\nError: can not open input file %s\n",

-          (const char *)GetOemString(inputName));

+      PrintError2("can not open input file", inputName);

       return 1;

     }

   }

 

   CMyComPtr<ISequentialOutStream> outStream;

   COutFileStream *outStreamSpec = NULL;

+  

   if (stdOutMode)

   {

     outStream = new CStdOutFileStream;

@@ -323,99 +468,148 @@
   }

   else

   {

-    if (paramIndex >= nonSwitchStrings.Size())

-      IncorrectCommand();

-    const UString &outputName = nonSwitchStrings[paramIndex++];

+    const UString &outputName = params[paramIndex++];

     outStreamSpec = new COutFileStream;

     outStream = outStreamSpec;

     if (!outStreamSpec->Create(us2fs(outputName), true))

     {

-      fprintf(stderr, "\nError: can not open output file %s\n",

-        (const char *)GetOemString(outputName));

+      PrintError2("can not open output file", outputName);

       return 1;

     }

   }

 

+  bool fileSizeDefined = false;

+  UInt64 fileSize = 0;

+  

+  if (inStreamSpec)

+  {

+    if (!inStreamSpec->File.GetLength(fileSize))

+      throw "Can not get file length";

+    fileSizeDefined = true;

+    if (!stdOutMode)

+      Print_Size("Input size:  ", fileSize);

+  }

+

+  if (encodeMode && !dictDefined)

+  {

+    dict = 1 << kDictSizeLog;

+    if (fileSizeDefined)

+    {

+      unsigned i;

+      for (i = 16; i < kDictSizeLog; i++)

+        if ((UInt32)((UInt32)1 << i) >= fileSize)

+          break;

+      dict = (UInt32)1 << i;

+    }

+  }

+

   if (parser[NKey::kFilter86].ThereIs)

   {

-    // -f86 switch is for x86 filtered mode: BCJ + LZMA.

+    /* -f86 switch is for x86 filtered mode: BCJ + LZMA.

+       It uses modified header format.

+       It's not recommended to use -f86 mode now.

+       You can use xz format instead, if you want to use filters */

+

     if (parser[NKey::kEOS].ThereIs || stdInMode)

       throw "Can not use stdin in this mode";

-    UInt64 fileSize;

-    inStreamSpec->File.GetLength(fileSize);

-    if (fileSize > 0xF0000000)

-      throw "File is too big";

+

     size_t inSize = (size_t)fileSize;

-    Byte *inBuffer = 0;

+

+    if (inSize != fileSize)

+      throw "File is too big";

+

+    Byte *inBuffer = NULL;

+    

     if (inSize != 0)

     {

       inBuffer = (Byte *)MyAlloc((size_t)inSize);

-      if (inBuffer == 0)

+      if (!inBuffer)

         throw kCantAllocate;

     }

     

     if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)

       throw "Can not read";

 

-    Byte *outBuffer = 0;

+    Byte *outBuffer = NULL;

     size_t outSize;

+    

     if (encodeMode)

     {

       // we allocate 105% of original size for output buffer

-      outSize = (size_t)fileSize / 20 * 21 + (1 << 16);

+      UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);

+

+      outSize = (size_t)outSize64;

+      

+      if (outSize != outSize64)

+        throw "File is too big";

+

       if (outSize != 0)

       {

         outBuffer = (Byte *)MyAlloc((size_t)outSize);

-        if (outBuffer == 0)

+        if (!outBuffer)

           throw kCantAllocate;

       }

-      if (!dictDefined)

-        dict = 1 << 23;

+      

       int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,

           5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);

+  

       if (res != 0)

       {

-        fprintf(stderr, "\nEncoder error = %d\n", (int)res);

+        PrintError_int("Encode error", (int)res);

         return 1;

       }

     }

     else

     {

       UInt64 outSize64;

+      

       if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)

         throw "data error";

+      

       outSize = (size_t)outSize64;

       if (outSize != outSize64)

-        throw "too big";

+        throw "Unpack size is too big";

       if (outSize != 0)

       {

         outBuffer = (Byte *)MyAlloc(outSize);

-        if (outBuffer == 0)

+        if (!outBuffer)

           throw kCantAllocate;

       }

+      

       int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);

+      

       if (inSize != (size_t)fileSize)

         throw "incorrect processed size";

       if (res != 0)

-        throw "LzmaDecoder error";

+      {

+        PrintError_int("Decode error", (int)res);

+        return 1;

+      }

     }

+    

     if (WriteStream(outStream, outBuffer, outSize) != S_OK)

       throw kWriteError;

+    

     MyFree(outBuffer);

     MyFree(inBuffer);

-    return 0;

+  }

+  else

+  {

+

+  CProgressPrint *progressSpec = NULL;

+  CMyComPtr<ICompressProgressInfo> progress;

+

+  if (!stdOutMode)

+  {

+    progressSpec = new CProgressPrint;

+    progress = progressSpec;

   }

 

-

-  UInt64 fileSize;

   if (encodeMode)

   {

     NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;

     CMyComPtr<ICompressCoder> encoder = encoderSpec;

 

-    if (!dictDefined)

-      dict = 1 << 23;

-

     UInt32 pb = 2;

     UInt32 lc = 3; // = 0; for 32-bit data

     UInt32 lp = 0; // = 2; for 32-bit data

@@ -434,8 +628,7 @@
 

     mcDefined = parser[NKey::kMc].ThereIs;

     if (mcDefined)

-      if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))

-        IncorrectCommand();

+      mc = GetNumber(parser[NKey::kMc].PostStrings[0]);

     

     const PROPID propIDs[] =

     {

@@ -450,6 +643,7 @@
       NCoderPropID::kNumThreads,

       NCoderPropID::kMatchFinderCycles,

     };

+

     const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);

 

     PROPVARIANT props[kNumPropsMax];

@@ -480,92 +674,105 @@
     if (!mcDefined)

       numProps--;

 

-    if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK)

-      IncorrectCommand();

-    encoderSpec->WriteCoderProperties(outStream);

+    HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);

+    if (res != S_OK)

+      return Error_HRESULT("incorrect encoder properties", res);

 

+    if (encoderSpec->WriteCoderProperties(outStream) != S_OK)

+      throw kWriteError;

+

+    bool fileSizeWasUsed = true;

     if (eos || stdInMode)

+    {

       fileSize = (UInt64)(Int64)-1;

-    else

-      inStreamSpec->File.GetLength(fileSize);

+      fileSizeWasUsed = false;

+    }

 

-    for (int i = 0; i < 8; i++)

     {

-      Byte b = Byte(fileSize >> (8 * i));

-      if (outStream->Write(&b, 1, 0) != S_OK)

-      {

-        PrintMessage(kWriteError);

-        return 1;

-      }

+      Byte temp[8];

+      for (int i = 0; i < 8; i++)

+        temp[i]= (Byte)(fileSize >> (8 * i));

+      if (WriteStream(outStream, temp, 8) != S_OK)

+        throw kWriteError;

     }

-    HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);

-    if (result == E_OUTOFMEMORY)

-    {

-      PrintMessage("\nError: Can not allocate memory\n");

-      return 1;

-    }

-    else if (result != S_OK)

-    {

-      fprintf(stderr, "\nEncoder error = %X\n", (unsigned)result);

-      return 1;

-    }

+  

+    res = encoder->Code(inStream, outStream, NULL, NULL, progress);

+    if (progressSpec)

+      progressSpec->ClosePrint();

+

+    if (res != S_OK)

+      return Error_HRESULT("Encoding error", res);

+

+    UInt64 processedSize = encoderSpec->GetInputProcessedSize();

+    

+    if (fileSizeWasUsed && processedSize != fileSize)

+      throw "Incorrect size of processed data";

   }

   else

   {

     NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;

     CMyComPtr<ICompressCoder> decoder = decoderSpec;

+    

     decoderSpec->FinishStream = true;

-    const UInt32 kPropertiesSize = 5;

+    

+    const unsigned kPropertiesSize = 5;

     Byte header[kPropertiesSize + 8];

-    if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)

-    {

-      PrintMessage(kReadError);

-      return 1;

-    }

-    if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)

-    {

-      PrintMessage("SetDecoderProperties error");

-      return 1;

-    }

-    fileSize = 0;

-    for (int i = 0; i < 8; i++)

-      fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);

 

-    bool isSizeDefined = (fileSize != (UInt64)(Int64)-1);

-    HRESULT res = decoder->Code(inStream, outStream, 0, isSizeDefined ? &fileSize : NULL, 0) != S_OK;

+    if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)

+      throw kReadError;

+    

+    if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)

+      throw "SetDecoderProperties error";

+    

+    UInt64 unpackSize = 0;

+    for (int i = 0; i < 8; i++)

+      unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);

+

+    bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1);

+

+    HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress);

+    if (progressSpec)

+      progressSpec->ClosePrint();

+

     if (res != S_OK)

     {

-      PrintMessage("Decoder error");

-      return 1;

+      if (res == S_FALSE)

+      {

+        PrintError("Decoding error");

+        return 1;

+      }

+      return Error_HRESULT("Decoding error", res);

     }

-    if (isSizeDefined && decoderSpec->GetOutputProcessedSize() != fileSize)

-    {

-      PrintMessage("Error: incorrect uncompressed size in header");

-      return 1;

-    }

+    

+    if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize())

+      throw "incorrect uncompressed size in header";

   }

-  if (outStreamSpec != NULL)

+  }

+

+  if (outStreamSpec)

   {

+    if (!stdOutMode)

+      Print_Size("Output size: ", outStreamSpec->ProcessedSize);

     if (outStreamSpec->Close() != S_OK)

-    {

-      PrintMessage("File closing error");

-      return 1;

-    }

+      throw "File closing error";

   }

+

   return 0;

 }

 

 int MY_CDECL main(int numArgs, const char *args[])

 {

+  NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;

+

   try { return main2(numArgs, args); }

   catch (const char *s)

   {

-    fprintf(stderr, "\nError: %s\n", s);

+    PrintError(s);

     return 1;

   }

   catch(...)

   {

-    PrintMessage("\nError\n");

+    PrintError("Unknown Error");

     return 1;

   }

 }

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
index 3e43804..bdc0c3e 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
@@ -366,6 +366,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\7zTypes.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Alloc.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

@@ -464,10 +468,6 @@
 

 SOURCE=..\..\..\..\C\Threads.h

 # End Source File

-# Begin Source File

-

-SOURCE=..\..\..\..\C\Types.h

-# End Source File

 # End Group

 # Begin Source File

 

diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
index ae9e27a..3fb5ec2 100644
--- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc
+++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
@@ -18,7 +18,6 @@
 FILE_IO_2 =Windows/$(FILE_IO)

 

 MT_FILES = \

-  System.o \

   LzFindMt.o \

   Threads.o \

 

@@ -60,6 +59,7 @@
   StringConvert.o \

   StringToInt.o \

   PropVariant.o \

+  System.o \

   7zCrc.o \

   7zCrcOpt.o \

   Alloc.o \

@@ -150,10 +150,8 @@
 PropVariant.o: ../../../Windows/PropVariant.cpp

 	$(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp

 

-ifdef MT_FILES

 System.o: ../../../Windows/System.cpp

 	$(CXX) $(CFLAGS) ../../../Windows/System.cpp

-endif

 

 7zCrc.o: ../../../../C/7zCrc.c

 	$(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c

@@ -195,4 +193,3 @@
 

 clean:

 	-$(RM) $(PROG) $(OBJS)

-

diff --git a/CPP/7zip/Bundles/LzmaCon/resource.rc b/CPP/7zip/Bundles/LzmaCon/resource.rc
index 6b5918d..9b54fa8 100644
--- a/CPP/7zip/Bundles/LzmaCon/resource.rc
+++ b/CPP/7zip/Bundles/LzmaCon/resource.rc
@@ -1,3 +1,3 @@
-#include "../../../../C/7zVersion.rc"

+#include "../../MyVersionInfo.rc"

 

 MY_VERSION_INFO_APP("LZMA", "lzma")

diff --git a/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp b/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
index bd79123..67e8dfc 100644
--- a/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
+++ b/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
@@ -1,5 +1,5 @@
-/* LzmaSpec.c -- LZMA Reference Decoder

-2013-07-28 : Igor Pavlov : Public domain */

+/* LzmaSpec.cpp -- LZMA Reference Decoder

+2015-06-14 : Igor Pavlov : Public domain */

 

 // This code implements LZMA file decoding according to LZMA specification.

 // This code is not optimized for speed.

@@ -141,27 +141,27 @@
   CInputStream *InStream;

   bool Corrupted;

 

-  void Init();

+  bool Init();

   bool IsFinishedOK() const { return Code == 0; }

 

   UInt32 DecodeDirectBits(unsigned numBits);

   unsigned DecodeBit(CProb *prob);

 };

 

-void CRangeDecoder::Init()

+bool CRangeDecoder::Init()

 {

   Corrupted = false;

-  

-  if (InStream->ReadByte() != 0)

-    Corrupted = true;

-  

   Range = 0xFFFFFFFF;

   Code = 0;

+

+  Byte b = InStream->ReadByte();

+  

   for (int i = 0; i < 4; i++)

     Code = (Code << 8) | InStream->ReadByte();

   

-  if (Code == Range)

+  if (b != 0 || Code == Range)

     Corrupted = true;

+  return b == 0;

 }

 

 #define kTopValue ((UInt32)1 << 24)

@@ -466,8 +466,10 @@
 

 int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)

 {

+  if (!RangeDec.Init())

+    return LZMA_RES_ERROR;

+

   Init();

-  RangeDec.Init();

 

   UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;

   unsigned state = 0;

@@ -605,7 +607,7 @@
 

 int main2(int numArgs, const char *args[])

 {

-  Print("\nLZMA Reference Decoder 9.31 : Igor Pavlov : Public domain : 2013-02-06\n");

+  Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n");

   if (numArgs == 1)

     Print("\nUse: lzmaSpec a.lzma outFile");

 

@@ -657,7 +659,7 @@
   Print("\n");

 

   lzmaDecoder.Create();

-  // we support the streams that have uncompressed size and marker.

+  

   int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);

 

   PrintUInt64("Read    ", inStream.Processed);

diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
index 6f380b1..f1e9a9e 100644
--- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -117,22 +117,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CoderMixer2MT.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\Common\ItemNameUtils.cpp

 # End Source File

 # Begin Source File

@@ -197,6 +181,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\UI\Console\PercentPrinter.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\PercentPrinter.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\UI\Console\UserInputUtils.cpp

 # End Source File

 # Begin Source File

@@ -221,14 +213,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\7z\7zFolderOutStream.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\7z\7zHandler.cpp

 # End Source File

 # Begin Source File

@@ -281,7 +265,15 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Compress\BranchCoder.cpp

+SOURCE=..\..\Compress\BranchMisc.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchMisc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchRegister.cpp

 # End Source File

 # Begin Source File

 

@@ -293,6 +285,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Compress\DeltaFilter.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Compress\Lzma2Decoder.cpp

 # End Source File

 # Begin Source File

@@ -605,6 +601,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Common\RegisterArc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\RegisterCodec.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Common\StreamBinder.cpp

 # End Source File

 # Begin Source File

@@ -758,6 +762,20 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Bcj2.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bcj2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Bra.h

 # End Source File

 # Begin Source File

@@ -767,11 +785,34 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\BraIA64.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\CpuArch.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Delta.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Delta.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Lzma2Dec.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index ae525fe..e67c671 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"

@@ -22,6 +24,8 @@
 

 #include "../../MyVersion.h"

 

+#include "../../../../C/DllSecur.h"

+

 using namespace NWindows;

 using namespace NFile;

 using namespace NDir;

@@ -101,10 +105,10 @@
 static const int kCommandIndex = 0;

 

 static const char *kHelpString =

-    "\nUsage: 7zSFX [<command>] [<switches>...]\n"

+    "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n"

     "\n"

     "<Commands>\n"

-    "  l: List contents of archive\n"

+    // "  l: List contents of archive\n"

     "  t: Test integrity of archive\n"

     "  x: eXtract files with full pathname (default)\n"

     "<Switches>\n"

@@ -220,13 +224,6 @@
     ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);

 }

 

-void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor,

-    const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type,

-    bool /* thereAreSwitchIncludeWildcards */)

-{

-  AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, type);

-}

-

 

 #ifndef _WIN32

 static void GetArguments(int numArgs, const char *args[], UStringVector &parts)

@@ -246,6 +243,11 @@
   #endif

 )

 {

+  #ifdef _WIN32

+  // do we need load Security DLLs for console program?

+  LoadSecurityDlls();

+  #endif

+

   #if defined(_WIN32) && !defined(UNDER_CE)

   SetFileApisToOEM();

   #endif

@@ -281,9 +283,16 @@
   commandStrings.Delete(0);

 

   NCommandLineParser::CParser parser(kNumSwitches);

+  

   try

   {

-    parser.ParseStrings(kSwitchForms, commandStrings);

+    if (!parser.ParseStrings(kSwitchForms, commandStrings))

+    {

+      g_StdOut << "Command line error:" << endl

+          << parser.ErrorMessage << endl

+          << parser.ErrorLine << endl;

+      return NExitCode::kUserError;

+    }

   }

   catch(...)

   {

@@ -295,19 +304,23 @@
     PrintHelp();

     return 0;

   }

+  

   const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

 

-  int numNonSwitchStrings = nonSwitchStrings.Size();

+  unsigned curCommandIndex = 0;

 

   CArchiveCommand command;

-  if (numNonSwitchStrings == 0)

+  if (nonSwitchStrings.IsEmpty())

     command.CommandType = NCommandType::kFullExtract;

   else

   {

-    if (numNonSwitchStrings > 1)

-      PrintHelpAndExit();

-    if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command))

-      PrintHelpAndExit();

+    const UString &cmd = nonSwitchStrings[curCommandIndex];

+    if (!ParseArchiveCommand(cmd, command))

+    {

+      g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl;

+      return NExitCode::kUserError;

+    }

+    curCommandIndex = 1;

   }

 

 

@@ -316,11 +329,17 @@
 

   NWildcard::CCensor wildcardCensor;

   

-  bool thereAreSwitchIncludeWildcards;

-  thereAreSwitchIncludeWildcards = false;

-

-  AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType,

-      thereAreSwitchIncludeWildcards);

+  {

+    if (nonSwitchStrings.Size() == curCommandIndex)

+      AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, recursedType);

+    for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++)

+    {

+      const UString &s = nonSwitchStrings[curCommandIndex];

+      if (s.IsEmpty())

+        throw "Empty file path";

+      AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType);

+    }

+  }

 

   bool yesToAll = parser[NKey::kYes].ThereIs;

 

@@ -361,30 +380,32 @@
       IUnknown

       #endif

       > compressCodecsInfo = codecs;

-    HRESULT result = codecs->Load();

-    if (result != S_OK)

-      throw CSystemException(result);

+    {

+      HRESULT result = codecs->Load();

+      if (result != S_OK)

+        throw CSystemException(result);

+    }

 

     if (command.CommandType != NCommandType::kList)

     {

       CExtractCallbackConsole *ecs = new CExtractCallbackConsole;

       CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

-      ecs->OutStream = g_StdStream;

+      ecs->Init(g_StdStream, &g_StdErr, g_StdStream);

 

       #ifndef _NO_CRYPTO

       ecs->PasswordIsDefined = passwordEnabled;

       ecs->Password = password;

       #endif

 

-      ecs->Init();

-

+      /*

       COpenCallbackConsole openCallback;

-      openCallback.OutStream = g_StdStream;

+      openCallback.Init(g_StdStream, g_StdStream);

 

       #ifndef _NO_CRYPTO

       openCallback.PasswordIsDefined = passwordEnabled;

       openCallback.Password = password;

       #endif

+      */

 

       CExtractOptions eo;

       eo.StdOutMode = false;

@@ -402,7 +423,7 @@
           codecs, CObjectVector<COpenType>(), CIntVector(),

           v1, v2,

           wildcardCensorHead,

-          eo, &openCallback, ecs,

+          eo, ecs, ecs,

           // NULL, // hash

           errorMessage, stat);

       if (!errorMessage.IsEmpty())

@@ -425,6 +446,9 @@
     }

     else

     {

+      throw CSystemException(E_NOTIMPL);

+

+      /*

       UInt64 numErrors = 0;

       UInt64 numWarnings = 0;

       HRESULT result = ListArchives(

@@ -447,6 +471,7 @@
       }

       if (result != S_OK)

         throw CSystemException(result);

+      */

     }

   }

   return 0;

diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
index 4d35d7e..d81e512 100644
--- a/CPP/7zip/Bundles/SFXCon/makefile
+++ b/CPP/7zip/Bundles/SFXCon/makefile
@@ -4,6 +4,7 @@
   -DEXTRACT_ONLY \

   -DNO_READ_FROM_CODER \

   -D_SFX \

+  -D_CONSOLE \

 

 CURRENT_OBJS = \

   $O\SfxCon.obj \

@@ -14,6 +15,7 @@
   $O\List.obj \

   $O\MainAr.obj \

   $O\OpenCallbackConsole.obj \

+  $O\PercentPrinter.obj \

   $O\UserInputUtils.obj \

 

 COMMON_OBJS = \

@@ -48,7 +50,6 @@
   $O\InBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

   $O\PropId.obj \

@@ -72,8 +73,6 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\ItemNameUtils.obj \

   $O\MultiStream.obj \

   $O\OutStreamWithCRC.obj \

@@ -82,19 +81,20 @@
 7Z_OBJS = \

   $O\7zDecode.obj \

   $O\7zExtract.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zIn.obj \

   $O\7zRegister.obj \

 

 COMPRESS_OBJS = \

-  $O\BranchCoder.obj \

   $O\Bcj2Coder.obj \

   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

   $O\CopyCoder.obj \

   $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

   $O\Lzma2Decoder.obj \

   $O\Lzma2Register.obj \

   $O\LzmaDecoder.obj \

@@ -109,8 +109,13 @@
 

 C_OBJS = \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

+  $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\DllSecur.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

   $O\Ppmd7.obj \

diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc
index 1c34357..97882cd 100644
--- a/CPP/7zip/Bundles/SFXCon/resource.rc
+++ b/CPP/7zip/Bundles/SFXCon/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"

+#include "../../MyVersionInfo.rc"

 

 MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")

 

diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
index 0811978..5708349 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -58,6 +58,11 @@
   #endif

 }

 

+HRESULT CExtractCallbackImp::Open_Finished()

+{

+  return S_OK;

+}

+

 STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)

 {

   #ifndef _NO_PROGRESS

@@ -83,7 +88,7 @@
   {

     fullPath += us2fs(dirPathParts[i]);

     CreateDir(fullPath);

-    fullPath += FCHAR_PATH_SEPARATOR;

+    fullPath.Add_PathSepar();

   }

 }

 

@@ -95,18 +100,21 @@
     return E_ABORT;

   #endif

   _outFileStream.Release();

-  NCOM::CPropVariant propVariantName;

-  RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName));

+

   UString fullPath;

-  if (propVariantName.vt == VT_EMPTY)

-    fullPath = _itemDefaultName;

-  else

   {

-    if (propVariantName.vt != VT_BSTR)

-      return E_FAIL;

-    fullPath = propVariantName.bstrVal;

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));

+    if (prop.vt == VT_EMPTY)

+      fullPath = _itemDefaultName;

+    else

+    {

+      if (prop.vt != VT_BSTR)

+        return E_FAIL;

+      fullPath.SetFromBstr(prop.bstrVal);

+    }

+    _filePath = fullPath;

   }

-  _filePath = fullPath;

 

   if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)

   {

@@ -133,7 +141,7 @@
     }

 

     RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));

-    switch(prop.vt)

+    switch (prop.vt)

     {

       case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;

       case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;

@@ -207,7 +215,7 @@
 

 STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)

 {

-  switch(resultEOperationResult)

+  switch (resultEOperationResult)

   {

     case NArchive::NExtract::NOperationResult::kOK:

       break;

@@ -215,7 +223,7 @@
     default:

     {

       _outFileStream.Release();

-      switch(resultEOperationResult)

+      switch (resultEOperationResult)

       {

         case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

           _message = kUnsupportedMethod;

diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
index ba0e960..6d5b55a 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
@@ -55,8 +55,7 @@
     Result = ArchiveLink.Open2(options, ExtractCallbackSpec);

     if (Result != S_OK)

     {

-      if (Result != S_OK)

-        ErrorMessage = kCantOpenArchive;

+      ErrorMessage = kCantOpenArchive;

       return;

     }

 

diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
index 1024311..4bf2fb8 100644
--- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -157,14 +157,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\7z\7zFolderOutStream.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\7z\7zHandler.cpp

 # End Source File

 # Begin Source File

@@ -205,22 +197,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CoderMixer2MT.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\Common\ItemNameUtils.cpp

 # End Source File

 # Begin Source File

@@ -257,7 +233,15 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Compress\BranchCoder.cpp

+SOURCE=..\..\Compress\BranchMisc.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchMisc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchRegister.cpp

 # End Source File

 # Begin Source File

 

@@ -269,6 +253,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Compress\DeltaFilter.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Compress\Lzma2Decoder.cpp

 # End Source File

 # Begin Source File

@@ -513,14 +501,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Common\LockedStream.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Common\LockedStream.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Common\OutBuffer.cpp

 # End Source File

 # Begin Source File

@@ -680,6 +660,20 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Bcj2.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bcj2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Bra.h

 # End Source File

 # Begin Source File

@@ -689,6 +683,11 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\BraIA64.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\CpuArch.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

@@ -698,6 +697,24 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Delta.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Delta.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Lzma2Dec.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 202c262..be44f39 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"

@@ -21,6 +23,8 @@
 

 #include "ExtractEngine.h"

 

+#include "../../../../C/DllSecur.h"

+

 #include "resource.h"

 

 using namespace NWindows;

@@ -94,12 +98,11 @@
   }

 }

 

-static char kStartID[] = ",!@Install@!UTF-8!";

-static char kEndID[] = ",!@InstallEnd@!";

+static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 };

+static char kEndID[]   = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 };

 

-class CInstallIDInit

+struct CInstallIDInit

 {

-public:

   CInstallIDInit()

   {

     kStartID[0] = ';';

@@ -134,6 +137,10 @@
 

   NT_CHECK

 

+  #ifdef _WIN32

+  LoadSecurityDlls();

+  #endif

+

   // InitCommonControls();

 

   UString archiveName, switches;

@@ -147,7 +154,7 @@
 

   switches.Trim();

   bool assumeYes = false;

-  if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0)

+  if (switches.IsPrefixedBy_Ascii_NoCase("-y"))

   {

     assumeYes = true;

     switches = switches.Ptr(2);

@@ -177,7 +184,7 @@
     UString friendlyName = GetTextConfigValue(pairs, L"Title");

     UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");

     UString progress = GetTextConfigValue(pairs, L"Progress");

-    if (progress.IsEqualToNoCase(L"no"))

+    if (progress.IsEqualTo_Ascii_NoCase("no"))

       showProgress = false;

     int index = FindTextConfigItem(pairs, L"Directory");

     if (index >= 0)

@@ -206,11 +213,13 @@
 

   CCodecs *codecs = new CCodecs;

   CMyComPtr<IUnknown> compressCodecsInfo = codecs;

-  HRESULT result = codecs->Load();

-  if (result != S_OK)

   {

-    ShowErrorMessage(L"Can not load codecs");

-    return 1;

+    HRESULT result = codecs->Load();

+    if (result != S_OK)

+    {

+      ShowErrorMessage(L"Can not load codecs");

+      return 1;

+    }

   }

 

   const FString tempDirPath = tempDir.GetPath();

@@ -265,8 +274,7 @@
 

     if (!switches.IsEmpty())

     {

-      if (!executeParameters.IsEmpty())

-        executeParameters += L' ';

+      executeParameters.Add_Space_if_NotEmpty();

       executeParameters += switches;

     }

 

@@ -281,7 +289,7 @@
     execInfo.hProcess = 0;

     /* BOOL success = */ ::ShellExecuteEx(&execInfo);

     UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;

-    if(result <= 32)

+    if (result <= 32)

     {

       if (!assumeYes)

         ShowErrorMessage(L"Can not open file");

@@ -315,7 +323,7 @@
 

     if (!switches.IsEmpty())

     {

-      appLaunched += L' ';

+      appLaunched.Add_Space();

       appLaunched += switches;

     }

     STARTUPINFO startupInfo;

diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
index 47c65f9..2cd3976 100644
--- a/CPP/7zip/Bundles/SFXSetup/makefile
+++ b/CPP/7zip/Bundles/SFXSetup/makefile
@@ -44,7 +44,6 @@
   $O\InBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

   $O\PropId.obj \

@@ -68,27 +67,26 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\ItemNameUtils.obj \

   $O\OutStreamWithCRC.obj \

 

 7Z_OBJS = \

   $O\7zDecode.obj \

   $O\7zExtract.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zIn.obj \

   $O\7zRegister.obj \

 

 COMPRESS_OBJS = \

-  $O\BranchCoder.obj \

   $O\Bcj2Coder.obj \

   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

   $O\CopyCoder.obj \

   $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

   $O\Lzma2Decoder.obj \

   $O\Lzma2Register.obj \

   $O\LzmaDecoder.obj \

@@ -96,8 +94,13 @@
 

 C_OBJS = \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

+  $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\DllSecur.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

   $O\Threads.obj \

diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc
index 7a16044..9e88fd4 100644
--- a/CPP/7zip/Bundles/SFXSetup/resource.rc
+++ b/CPP/7zip/Bundles/SFXSetup/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"

+#include "../../MyVersionInfo.rc"

 #include "resource.h"

 

 MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx")

diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index 711582f..9ee6c77 100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -149,14 +149,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\7z\7zFolderOutStream.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\7z\7zHandler.cpp

 # End Source File

 # Begin Source File

@@ -197,22 +189,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CoderMixer2MT.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Archive\Common\CrossThreadProgress.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\Archive\Common\ItemNameUtils.cpp

 # End Source File

 # Begin Source File

@@ -257,7 +233,15 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Compress\BranchCoder.cpp

+SOURCE=..\..\Compress\BranchMisc.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchMisc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchRegister.cpp

 # End Source File

 # Begin Source File

 

@@ -269,6 +253,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Compress\DeltaFilter.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Compress\Lzma2Decoder.cpp

 # End Source File

 # Begin Source File

@@ -337,14 +325,6 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\UI\FileManager\MessagesDialog.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\UI\FileManager\MessagesDialog.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp

 # End Source File

 # Begin Source File

@@ -509,6 +489,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\UI\FileManager\PropertyName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\PropertyName.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\UI\FileManager\SysIconUtils.cpp

 # End Source File

 # Begin Source File

@@ -858,6 +846,20 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Bcj2.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bcj2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Bra.h

 # End Source File

 # Begin Source File

@@ -867,11 +869,34 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\BraIA64.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\CpuArch.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Delta.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Delta.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\DllSecur.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\..\C\Lzma2Dec.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index 42e940f..3f05e10 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"

@@ -26,6 +28,8 @@
 #include "../../UI/GUI/ExtractGUI.h"

 #include "../../UI/GUI/ExtractRes.h"

 

+#include "../../../../C/DllSecur.h"

+

 using namespace NWindows;

 using namespace NFile;

 using namespace NDir;

@@ -218,6 +222,10 @@
 

   try

   {

+    #ifdef _WIN32

+    LoadSecurityDlls();

+    #endif

+

     return WinMain2();

   }

   catch(const CNewException &)

diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
index 36806c8..686eaff 100644
--- a/CPP/7zip/Bundles/SFXWin/makefile
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -56,7 +56,6 @@
   $O\InBuffer.obj \

   $O\FilterCoder.obj \

   $O\LimitedStreams.obj \

-  $O\LockedStream.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

   $O\PropId.obj \

@@ -85,6 +84,7 @@
   $O\OverwriteDialog.obj \

   $O\PasswordDialog.obj \

   $O\ProgressDialog2.obj \

+  $O\PropertyName.obj \

   $O\SysIconUtils.obj \

 

 AR_OBJS = \

@@ -92,8 +92,6 @@
 

 AR_COMMON_OBJS = \

   $O\CoderMixer2.obj \

-  $O\CoderMixer2MT.obj \

-  $O\CrossThreadProgress.obj \

   $O\ItemNameUtils.obj \

   $O\MultiStream.obj \

   $O\OutStreamWithCRC.obj \

@@ -101,19 +99,20 @@
 7Z_OBJS = \

   $O\7zDecode.obj \

   $O\7zExtract.obj \

-  $O\7zFolderOutStream.obj \

   $O\7zHandler.obj \

   $O\7zIn.obj \

   $O\7zRegister.obj \

 

 COMPRESS_OBJS = \

-  $O\BranchCoder.obj \

   $O\Bcj2Coder.obj \

   $O\Bcj2Register.obj \

   $O\BcjCoder.obj \

   $O\BcjRegister.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

   $O\CopyCoder.obj \

   $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

   $O\Lzma2Decoder.obj \

   $O\Lzma2Register.obj \

   $O\LzmaDecoder.obj \

@@ -128,8 +127,13 @@
   

 C_OBJS = \

   $O\Alloc.obj \

+  $O\Bcj2.obj \

+  $O\Bra.obj \

   $O\Bra86.obj \

+  $O\BraIA64.obj \

   $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\DllSecur.obj \

   $O\Lzma2Dec.obj \

   $O\LzmaDec.obj \

   $O\Ppmd7.obj \

diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc
index 3e24fa6..3b69b35 100644
--- a/CPP/7zip/Bundles/SFXWin/resource.rc
+++ b/CPP/7zip/Bundles/SFXWin/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"

+#include "../../MyVersionInfo.rc"

 #include "../../GuiCommon.rc"

 #include "../../UI/GUI/ExtractDialogRes.h"

 #include "../../UI/FileManager/PropertyNameRes.h"

diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
index 14424d5..8bf3718 100644
--- a/CPP/7zip/Common/CWrappers.cpp
+++ b/CPP/7zip/Common/CWrappers.cpp
@@ -86,7 +86,7 @@
 

 HRESULT SResToHRESULT(SRes res) throw()

 {

-  switch(res)

+  switch (res)

   {

     case SZ_OK: return S_OK;

     case SZ_ERROR_MEM: return E_OUTOFMEMORY;

@@ -111,7 +111,7 @@
 {

   CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;

   UInt32 moveMethod;

-  switch(origin)

+  switch (origin)

   {

     case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;

     case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;

diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
index 8be4e05..53e7631 100644
--- a/CPP/7zip/Common/CreateCoder.cpp
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -10,25 +10,40 @@
 #include "FilterCoder.h"

 #include "RegisterCodec.h"

 

-static const unsigned int kNumCodecsMax = 64;

-unsigned int g_NumCodecs = 0;

+static const unsigned kNumCodecsMax = 64;

+unsigned g_NumCodecs = 0;

 const CCodecInfo *g_Codecs[kNumCodecsMax];

+

+// We use g_ExternalCodecs in other stages.

+/*

+#ifdef EXTERNAL_CODECS

+extern CExternalCodecs g_ExternalCodecs;

+#define CHECK_GLOBAL_CODECS \

+    if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs;

+#endif

+*/

+

+#define CHECK_GLOBAL_CODECS

+

 void RegisterCodec(const CCodecInfo *codecInfo) throw()

 {

   if (g_NumCodecs < kNumCodecsMax)

     g_Codecs[g_NumCodecs++] = codecInfo;

 }

 

-static const unsigned int kNumHashersMax = 16;

-unsigned int g_NumHashers = 0;

+static const unsigned kNumHashersMax = 16;

+unsigned g_NumHashers = 0;

 const CHasherInfo *g_Hashers[kNumHashersMax];

+

 void RegisterHasher(const CHasherInfo *hashInfo) throw()

 {

   if (g_NumHashers < kNumHashersMax)

     g_Hashers[g_NumHashers++] = hashInfo;

 }

 

+

 #ifdef EXTERNAL_CODECS

+

 static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)

 {

   NWindows::NCOM::CPropVariant prop;

@@ -55,102 +70,130 @@
   return S_OK;

 }

 

-HRESULT CExternalCodecs::LoadCodecs()

+HRESULT CExternalCodecs::Load()

 {

+  Codecs.Clear();

+  Hashers.Clear();

+

   if (GetCodecs)

   {

+    CCodecInfoEx info;

+    

+    UString s;

     UInt32 num;

-    RINOK(GetCodecs->GetNumberOfMethods(&num));

+    RINOK(GetCodecs->GetNumMethods(&num));

+    

     for (UInt32 i = 0; i < num; i++)

     {

-      CCodecInfoEx info;

       NWindows::NCOM::CPropVariant prop;

+      

       RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop));

-      // if (prop.vt != VT_BSTR)

-      // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);

-      // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize);

       if (prop.vt != VT_UI8)

         continue; // old Interface

       info.Id = prop.uhVal.QuadPart;

+      

       prop.Clear();

       

+      info.Name.Empty();

       RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop));

       if (prop.vt == VT_BSTR)

-        info.Name = prop.bstrVal;

+        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);

       else if (prop.vt != VT_EMPTY)

-        return E_INVALIDARG;

+        continue;

       

-      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams));

-      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams));

+      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams));

+      {

+        UInt32 numUnpackStreams = 1;

+        RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams));

+        if (numUnpackStreams != 1)

+          continue;

+      }

       RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));

       RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));

       

       Codecs.Add(info);

     }

   }

+  

   if (GetHashers)

   {

     UInt32 num = GetHashers->GetNumHashers();

+    CHasherInfoEx info;

+    

     for (UInt32 i = 0; i < num; i++)

     {

-      CHasherInfoEx info;

       NWindows::NCOM::CPropVariant prop;

+

       RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop));

       if (prop.vt != VT_UI8)

         continue;

       info.Id = prop.uhVal.QuadPart;

+      

       prop.Clear();

       

+      info.Name.Empty();

       RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop));

       if (prop.vt == VT_BSTR)

-        info.Name = prop.bstrVal;

+        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);

       else if (prop.vt != VT_EMPTY)

-        return E_INVALIDARG;

+        continue;

       

       Hashers.Add(info);

     }

   }

+  

   return S_OK;

 }

 

 #endif

 

-bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS

-    const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)

+

+bool FindMethod(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const AString &name,

+    CMethodId &methodId, UInt32 &numStreams)

 {

-  UInt32 i;

+  unsigned i;

   for (i = 0; i < g_NumCodecs; i++)

   {

     const CCodecInfo &codec = *g_Codecs[i];

-    if (name.IsEqualToNoCase(codec.Name))

+    if (StringsAreEqualNoCase_Ascii(name, codec.Name))

     {

       methodId = codec.Id;

-      numInStreams = codec.NumInStreams;

-      numOutStreams = 1;

+      numStreams = codec.NumStreams;

       return true;

     }

   }

+  

   #ifdef EXTERNAL_CODECS

+  

+  CHECK_GLOBAL_CODECS

+

   if (__externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

+    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)

     {

       const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

-      if (codec.Name.IsEqualToNoCase(name))

+      if (StringsAreEqualNoCase_Ascii(name, codec.Name))

       {

         methodId = codec.Id;

-        numInStreams = codec.NumInStreams;

-        numOutStreams = codec.NumOutStreams;

+        numStreams = codec.NumStreams;

         return true;

       }

     }

+  

   #endif

+  

   return false;

 }

 

-bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS

-   CMethodId methodId, UString &name)

+bool FindMethod(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId,

+    AString &name)

 {

-  UInt32 i;

+  name.Empty();

+ 

+  unsigned i;

   for (i = 0; i < g_NumCodecs; i++)

   {

     const CCodecInfo &codec = *g_Codecs[i];

@@ -160,9 +203,13 @@
       return true;

     }

   }

+  

   #ifdef EXTERNAL_CODECS

+

+  CHECK_GLOBAL_CODECS

+

   if (__externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

+    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)

     {

       const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

       if (methodId == codec.Id)

@@ -171,62 +218,79 @@
         return true;

       }

     }

+  

   #endif

+  

   return false;

 }

 

-bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS

-  const UString &name,

-  CMethodId &methodId)

+bool FindHashMethod(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const AString &name,

+    CMethodId &methodId)

 {

-  UInt32 i;

+  unsigned i;

   for (i = 0; i < g_NumHashers; i++)

   {

     const CHasherInfo &codec = *g_Hashers[i];

-    if (name.IsEqualToNoCase(codec.Name))

+    if (StringsAreEqualNoCase_Ascii(name, codec.Name))

     {

       methodId = codec.Id;

       return true;

     }

   }

+  

   #ifdef EXTERNAL_CODECS

+

+  CHECK_GLOBAL_CODECS

+

   if (__externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)

     {

       const CHasherInfoEx &codec = __externalCodecs->Hashers[i];

-      if (codec.Name.IsEqualToNoCase(name))

+      if (StringsAreEqualNoCase_Ascii(name, codec.Name))

       {

         methodId = codec.Id;

         return true;

       }

     }

+  

   #endif

+  

   return false;

 }

 

-void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS

+void GetHashMethods(

+    DECL_EXTERNAL_CODECS_LOC_VARS

     CRecordVector<CMethodId> &methods)

 {

   methods.ClearAndSetSize(g_NumHashers);

-  UInt32 i;

+  unsigned i;

   for (i = 0; i < g_NumHashers; i++)

     methods[i] = (*g_Hashers[i]).Id;

+  

   #ifdef EXTERNAL_CODECS

+  

+  CHECK_GLOBAL_CODECS

+

   if (__externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)

       methods.Add(__externalCodecs->Hashers[i].Id);

+  

   #endif

 }

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressFilter> &filter,

-  CMyComPtr<ICompressCoder> &coder,

-  CMyComPtr<ICompressCoder2> &coder2,

-  bool encode, bool onlyCoder)

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressFilter> &filter,

+    CCreatedCoder &cod)

 {

-  UInt32 i;

+  cod.IsExternal = false;

+  cod.IsFilter = false;

+  cod.NumStreams = 1;

+

+  unsigned i;

   for (i = 0; i < g_NumCodecs; i++)

   {

     const CCodecInfo &codec = *g_Codecs[i];

@@ -238,9 +302,9 @@
         {

           void *p = codec.CreateEncoder();

           if (codec.IsFilter) filter = (ICompressFilter *)p;

-          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

-          else coder2 = (ICompressCoder2 *)p;

-          break;

+          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;

+          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }

+          return S_OK;

         }

       }

       else

@@ -248,16 +312,21 @@
         {

           void *p = codec.CreateDecoder();

           if (codec.IsFilter) filter = (ICompressFilter *)p;

-          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

-          else coder2 = (ICompressCoder2 *)p;

-          break;

+          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;

+          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }

+          return S_OK;

         }

     }

   }

 

   #ifdef EXTERNAL_CODECS

-  if (!filter && !coder && !coder2 && __externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

+

+  CHECK_GLOBAL_CODECS

+  

+  if (__externalCodecs)

+  {

+    cod.IsExternal = true;

+    for (i = 0; i < __externalCodecs->Codecs.Size(); i++)

     {

       const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

       if (codec.Id == methodId)

@@ -266,125 +335,126 @@
         {

           if (codec.EncoderIsAssigned)

           {

-            if (codec.IsSimpleCodec())

+            if (codec.NumStreams == 1)

             {

-              HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);

-              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)

-                return result;

-              if (!coder)

-              {

-                RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));

-              }

+              HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);

+              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)

+                return res;

+              if (cod.Coder)

+                return res;

+              return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);

             }

-            else

-            {

-              RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));

-            }

-            break;

+            cod.NumStreams = codec.NumStreams;

+            return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);

           }

         }

         else

           if (codec.DecoderIsAssigned)

           {

-            if (codec.IsSimpleCodec())

+            if (codec.NumStreams == 1)

             {

-              HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);

-              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)

-                return result;

-              if (!coder)

-              {

-                RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));

-              }

+              HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);

+              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)

+                return res;

+              if (cod.Coder)

+                return res;

+              return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);

             }

-            else

-            {

-              RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));

-            }

-            break;

+            cod.NumStreams = codec.NumStreams;

+            return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);

           }

       }

     }

+  }

   #endif

 

-  if (onlyCoder && filter)

-  {

-    CFilterCoder *coderSpec = new CFilterCoder;

-    coder = coderSpec;

-    coderSpec->Filter = filter;

-  }

   return S_OK;

 }

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressCoder> &coder,

-  CMyComPtr<ICompressCoder2> &coder2,

-  bool encode)

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CCreatedCoder &cod)

 {

   CMyComPtr<ICompressFilter> filter;

-  return CreateCoder(

-    EXTERNAL_CODECS_LOC_VARS

-    methodId,

-    filter, coder, coder2, encode, true);

+  HRESULT res = CreateCoder(

+      EXTERNAL_CODECS_LOC_VARS

+      methodId, encode,

+      filter, cod);

+  

+  if (filter)

+  {

+    cod.IsFilter = true;

+    CFilterCoder *coderSpec = new CFilterCoder(encode);

+    cod.Coder = coderSpec;

+    coderSpec->Filter = filter;

+  }

+  

+  return res;

 }

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressCoder> &coder, bool encode)

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressCoder> &coder)

 {

-  CMyComPtr<ICompressFilter> filter;

-  CMyComPtr<ICompressCoder2> coder2;

-  return CreateCoder(

-    EXTERNAL_CODECS_LOC_VARS

-    methodId,

-    coder, coder2, encode);

+  CCreatedCoder cod;

+  HRESULT res = CreateCoder(

+      EXTERNAL_CODECS_LOC_VARS

+      methodId, encode,

+      cod);

+  coder = cod.Coder;

+  return res;

 }

 

 HRESULT CreateFilter(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressFilter> &filter,

-  bool encode)

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressFilter> &filter)

 {

-  CMyComPtr<ICompressCoder> coder;

-  CMyComPtr<ICompressCoder2> coder2;

+  CCreatedCoder cod;

   return CreateCoder(

-    EXTERNAL_CODECS_LOC_VARS

-    methodId,

-    filter, coder, coder2, encode, false);

+      EXTERNAL_CODECS_LOC_VARS

+      methodId, encode,

+      filter, cod);

 }

 

+

 HRESULT CreateHasher(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  UString &name,

-  CMyComPtr<IHasher> &hasher)

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId,

+    AString &name,

+    CMyComPtr<IHasher> &hasher)

 {

-  UInt32 i;

+  name.Empty();

+

+  unsigned i;

   for (i = 0; i < g_NumHashers; i++)

   {

     const CHasherInfo &codec = *g_Hashers[i];

     if (codec.Id == methodId)

     {

-      hasher = (IHasher *)codec.CreateHasher();

+      hasher = codec.CreateHasher();

       name = codec.Name;

       break;

     }

   }

 

   #ifdef EXTERNAL_CODECS

+

+  CHECK_GLOBAL_CODECS

+

   if (!hasher && __externalCodecs)

-    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+    for (i = 0; i < __externalCodecs->Hashers.Size(); i++)

     {

       const CHasherInfoEx &codec = __externalCodecs->Hashers[i];

       if (codec.Id == methodId)

       {

         name = codec.Name;

-        return __externalCodecs->GetHashers->CreateHasher(i, &hasher);

+        return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);

       }

     }

+

   #endif

 

   return S_OK;

diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
index 50dc148..e0956e1 100644
--- a/CPP/7zip/Common/CreateCoder.h
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -5,29 +5,44 @@
 

 #include "../../Common/MyCom.h"

 #include "../../Common/MyString.h"

+

 #include "../ICoder.h"

 

 #include "MethodId.h"

 

+/*

+  if EXTERNAL_CODECS is not defined, the code supports only codecs that

+      are statically linked at compile-time and link-time.

+

+  if EXTERNAL_CODECS is defined, the code supports also codecs from another

+      executable modules, that can be linked dynamically at run-time:

+        - EXE module can use codecs from external DLL files.

+        - DLL module can use codecs from external EXE and DLL files.

+     

+      CExternalCodecs contains information about codecs and interfaces to create them.

+  

+  The order of codecs:

+    1) Internal codecs

+    2) External codecs

+*/

+

 #ifdef EXTERNAL_CODECS

 

 struct CCodecInfoEx

 {

-  UString Name;

   CMethodId Id;

-  UInt32 NumInStreams;

-  UInt32 NumOutStreams;

+  AString Name;

+  UInt32 NumStreams;

   bool EncoderIsAssigned;

   bool DecoderIsAssigned;

   

-  bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }

   CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}

 };

 

 struct CHasherInfoEx

 {

-  UString Name;

   CMethodId Id;

+  AString Name;

 };

 

 #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,

@@ -35,7 +50,7 @@
 #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);

 #define IMPL_ISetCompressCodecsInfo2(x) \

 STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \

-  COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo;  return __externalCodecs.LoadCodecs(); COM_TRY_END }

+  COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo;  return __externalCodecs.Load(); COM_TRY_END }

 #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)

 

 struct CExternalCodecs

@@ -46,13 +61,36 @@
   CObjectVector<CCodecInfoEx> Codecs;

   CObjectVector<CHasherInfoEx> Hashers;

 

-  HRESULT LoadCodecs();

+  bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; }

+

+  HRESULT Load();

+

+  void ClearAndRelease()

+  {

+    Hashers.Clear();

+    Codecs.Clear();

+    GetHashers.Release();

+    GetCodecs.Release();

+  }

+

+  ~CExternalCodecs()

+  {

+    GetHashers.Release();

+    GetCodecs.Release();

+  }

 };

 

-#define EXTERNAL_CODECS_VARS2 &__externalCodecs

+extern CExternalCodecs g_ExternalCodecs;

+

+#define EXTERNAL_CODECS_VARS2   (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs)

+#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs)

+#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)

 

 #define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;

-#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,

+

+#define EXTERNAL_CODECS_VARS   EXTERNAL_CODECS_VARS2,

+#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,

+#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,

 

 #define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs

 #define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs

@@ -68,7 +106,9 @@
 #define IMPL_ISetCompressCodecsInfo

 #define EXTERNAL_CODECS_VARS2

 #define DECL_EXTERNAL_CODECS_VARS

-#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2

+#define EXTERNAL_CODECS_VARS

+#define EXTERNAL_CODECS_VARS_L

+#define EXTERNAL_CODECS_VARS_G

 #define DECL_EXTERNAL_CODECS_LOC_VARS2

 #define EXTERNAL_CODECS_LOC_VARS2

 #define DECL_EXTERNAL_CODECS_LOC_VARS

@@ -76,52 +116,67 @@
 

 #endif

 

-bool FindMethod(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);

+

+

 

 bool FindMethod(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId, UString &name);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const AString &name,

+    CMethodId &methodId, UInt32 &numStreams);

+

+bool FindMethod(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId,

+    AString &name);

 

 bool FindHashMethod(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  const UString &name, CMethodId &methodId);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const AString &name,

+    CMethodId &methodId);

 

 void GetHashMethods(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CRecordVector<CMethodId> &methods);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CRecordVector<CMethodId> &methods);

+

+

+struct CCreatedCoder

+{

+  CMyComPtr<ICompressCoder> Coder;

+  CMyComPtr<ICompressCoder2> Coder2;

+  

+  bool IsExternal;

+  bool IsFilter; // = true, if Coder was created from filter

+  UInt32 NumStreams;

+

+  // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {}

+};

+

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressFilter> &filter,

-  CMyComPtr<ICompressCoder> &coder,

-  CMyComPtr<ICompressCoder2> &coder2,

-  bool encode, bool onlyCoder);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressFilter> &filter,

+    CCreatedCoder &cod);

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressCoder> &coder,

-  CMyComPtr<ICompressCoder2> &coder2,

-  bool encode);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CCreatedCoder &cod);

 

 HRESULT CreateCoder(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressCoder> &coder, bool encode);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressCoder> &coder);

 

 HRESULT CreateFilter(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  CMyComPtr<ICompressFilter> &filter,

-  bool encode);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId, bool encode,

+    CMyComPtr<ICompressFilter> &filter);

 

 HRESULT CreateHasher(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  CMethodId methodId,

-  UString &name,

-  CMyComPtr<IHasher> &hacher);

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CMethodId methodId,

+    AString &name,

+    CMyComPtr<IHasher> &hasher);

 

 #endif

diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
index db151c0..6cbadf5 100644
--- a/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -12,44 +12,40 @@
 using namespace NWindows;

 

 static bool MakeAutoName(const FString &name,

-    const FString &extension, unsigned value, FString &path)

+    const FString &extension, UInt32 value, FString &path)

 {

-  FChar number[16];

-  ConvertUInt32ToString(value, number);

+  char temp[16];

+  ConvertUInt32ToString(value, temp);

   path = name;

-  path += number;

+  path.AddAscii(temp);

   path += extension;

   return NFile::NFind::DoesFileOrDirExist(path);

 }

 

-bool AutoRenamePath(FString &fullProcessedPath)

+bool AutoRenamePath(FString &path)

 {

-  FString path;

-  int dotPos = fullProcessedPath.ReverseFind(FTEXT('.'));

+  int dotPos = path.ReverseFind_Dot();

+  int slashPos = path.ReverseFind_PathSepar();

 

-  int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));

-  #ifdef _WIN32

-  int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));

-  slashPos = MyMax(slashPos, slash1Pos);

-  #endif

-

-  FString name, extension;

-  if (dotPos > slashPos && dotPos > 0)

+  FString name = path;

+  FString extension;

+  if (dotPos > slashPos + 1)

   {

-    name.SetFrom(fullProcessedPath, dotPos);

-    extension = fullProcessedPath.Ptr(dotPos);

+    name.DeleteFrom(dotPos);

+    extension = path.Ptr(dotPos);

   }

-  else

-    name = fullProcessedPath;

-  name += L'_';

-  unsigned left = 1, right = (1 << 30);

+  name += FTEXT('_');

+  

+  FString temp;

+

+  UInt32 left = 1, right = ((UInt32)1 << 30);

   while (left != right)

   {

-    unsigned mid = (left + right) / 2;

-    if (MakeAutoName(name, extension, mid, path))

+    UInt32 mid = (left + right) / 2;

+    if (MakeAutoName(name, extension, mid, temp))

       left = mid + 1;

     else

       right = mid;

   }

-  return !MakeAutoName(name, extension, right, fullProcessedPath);

+  return !MakeAutoName(name, extension, right, path);

 }

diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
index 96f79a0..11c14d2 100644
--- a/CPP/7zip/Common/FileStreams.cpp
+++ b/CPP/7zip/Common/FileStreams.cpp
@@ -29,25 +29,29 @@
   #endif

 }

 

-#ifdef SUPPORT_DEVICE_FILE

 

 static const UInt32 kClusterSize = 1 << 18;

 CInFileStream::CInFileStream():

+  #ifdef SUPPORT_DEVICE_FILE

   VirtPos(0),

   PhyPos(0),

   Buf(0),

   BufSize(0),

-  SupportHardLinks(false)

+  #endif

+  SupportHardLinks(false),

+  Callback(NULL),

+  CallbackRef(0)

 {

 }

 

-#endif

-

 CInFileStream::~CInFileStream()

 {

   #ifdef SUPPORT_DEVICE_FILE

   MidFree(Buf);

   #endif

+

+  if (Callback)

+    Callback->InFileStream_On_Destroy(CallbackRef);

 }

 

 STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

@@ -148,19 +152,37 @@
   bool result = File.ReadPart(data, size, realProcessedSize);

   if (processedSize)

     *processedSize = realProcessedSize;

+

   #ifdef SUPPORT_DEVICE_FILE

   VirtPos += realProcessedSize;

   PhyPos += realProcessedSize;

   #endif

-  return ConvertBoolToHRESULT(result);

-  

+

+  if (result)

+    return S_OK;

+

+  {

+    DWORD error = ::GetLastError();

+

+    if (Callback)

+      return Callback->InFileStream_On_Error(CallbackRef, error);

+    if (error == 0)

+      return E_FAIL;

+

+    return HRESULT_FROM_WIN32(error);

+  }

+

   #else

   

   if (processedSize)

     *processedSize = 0;

   ssize_t res = File.Read(data, (size_t)size);

   if (res == -1)

+  {

+    if (Callback)

+      return Callback->InFileStream_On_Error(CallbackRef, E_FAIL);

     return E_FAIL;

+  }

   if (processedSize)

     *processedSize = (UInt32)res;

   return S_OK;

@@ -321,7 +343,7 @@
   #ifdef USE_WIN_FILE

 

   UInt32 realProcessedSize;

-  bool result = File.WritePart(data, size, realProcessedSize);

+  bool result = File.Write(data, size, realProcessedSize);

   ProcessedSize += realProcessedSize;

   if (processedSize)

     *processedSize = realProcessedSize;

@@ -346,6 +368,7 @@
 {

   if (seekOrigin >= 3)

     return STG_E_INVALIDFUNCTION;

+  

   #ifdef USE_WIN_FILE

 

   UInt64 realNewPosition;

@@ -369,6 +392,7 @@
 STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)

 {

   #ifdef USE_WIN_FILE

+  

   UInt64 currentPos;

   if (!File.Seek(0, FILE_CURRENT, currentPos))

     return E_FAIL;

@@ -376,12 +400,21 @@
   UInt64 currentPos2;

   result = result && File.Seek(currentPos, currentPos2);

   return result ? S_OK : E_FAIL;

+  

   #else

+  

   return E_FAIL;

+  

   #endif

 }

 

+HRESULT COutFileStream::GetSize(UInt64 *size)

+{

+  return ConvertBoolToHRESULT(File.GetLength(*size));

+}

+

 #ifdef UNDER_CE

+

 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

   size_t s2 = fwrite(data, 1, size, stdout);

@@ -389,13 +422,16 @@
     *processedSize = s2;

   return (s2 == size) ? S_OK : E_FAIL;

 }

+

 #else

+

 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

   if (processedSize)

     *processedSize = 0;

 

   #ifdef _WIN32

+

   UInt32 realProcessedSize;

   BOOL res = TRUE;

   if (size > 0)

@@ -407,6 +443,7 @@
       sizeTemp = size;

     res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),

         data, sizeTemp, (DWORD *)&realProcessedSize, NULL);

+    _size += realProcessedSize;

     size -= realProcessedSize;

     data = (const void *)((const Byte *)data + realProcessedSize);

     if (processedSize)

@@ -417,18 +454,21 @@
   #else

   

   ssize_t res;

+

   do

   {

     res = write(1, data, (size_t)size);

   }

   while (res < 0 && (errno == EINTR));

+  

   if (res == -1)

     return E_FAIL;

+

+  _size += (size_t)res;

   if (processedSize)

     *processedSize = (UInt32)res;

   return S_OK;

   

-  return S_OK;

   #endif

 }

 

diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
index 1cd2d1a..a0996f8 100644
--- a/CPP/7zip/Common/FileStreams.h
+++ b/CPP/7zip/Common/FileStreams.h
@@ -19,6 +19,18 @@
 

 #include "../IStream.h"

 

+#ifdef _WIN32

+typedef UINT_PTR My_UINT_PTR;

+#else

+typedef UINT My_UINT_PTR;

+#endif

+

+struct IInFileStream_Callback

+{

+  virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0;

+  virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0;

+};

+

 class CInFileStream:

   public IInStream,

   public IStreamGetSize,

@@ -45,12 +57,13 @@
   #endif

 

   bool SupportHardLinks;

-  

+

+  IInFileStream_Callback *Callback;

+  My_UINT_PTR CallbackRef;

+

   virtual ~CInFileStream();

 

-  #ifdef SUPPORT_DEVICE_FILE

   CInFileStream();

-  #endif

   

   bool Open(CFSTR fileName)

   {

@@ -132,15 +145,20 @@
   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

   STDMETHOD(SetSize)(UInt64 newSize);

+

+  HRESULT GetSize(UInt64 *size);

 };

 

 class CStdOutFileStream:

   public ISequentialOutStream,

   public CMyUnknownImp

 {

+  UInt64 _size;

 public:

   MY_UNKNOWN_IMP

 

+  UInt64 GetSize() const { return _size; }

+  CStdOutFileStream(): _size(0) {}

   virtual ~CStdOutFileStream() {}

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
index bed8298..275c60d 100644
--- a/CPP/7zip/Common/FilterCoder.cpp
+++ b/CPP/7zip/Common/FilterCoder.cpp
@@ -2,90 +2,144 @@
 

 #include "StdAfx.h"

 

-#include "../../../C/Alloc.h"

-

 #include "../../Common/Defs.h"

 

 #include "FilterCoder.h"

 #include "StreamUtils.h"

 

-static const UInt32 kBufferSize = 1 << 17;

+/*

+  AES filters need 16-bytes alignment for HARDWARE-AES instructions.

+  So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block.

 

-CFilterCoder::CFilterCoder()

+  AES-CBC filters need data size aligned for 16-bytes.

+  So the encoder can add zeros to the end of original stream.

+

+  Some filters (BCJ and others) don't process data at the end of stream in some cases.

+  So the encoder and decoder write such last bytes without change.

+*/

+

+

+static const UInt32 kBufSize = 1 << 20;

+

+STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }

+STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }

+

+HRESULT CFilterCoder::Alloc()

 {

-  _buffer = (Byte *)::MidAlloc(kBufferSize);

-  if (_buffer == 0)

-    throw 1;

+  UInt32 size = MyMin(_inBufSize, _outBufSize);

+  /* minimal bufSize is 16 bytes for AES and IA64 filter.

+     bufSize for AES must be aligned for 16 bytes.

+     We use (1 << 12) min size to support future aligned filters. */

+  const UInt32 kMinSize = 1 << 12;

+  size &= ~(UInt32)(kMinSize - 1);

+  if (size < kMinSize)

+    size = kMinSize;

+  if (!_buf || _bufSize != size)

+  {

+    AllocAlignedMask(size, 16 - 1);

+    if (!_buf)

+      return E_OUTOFMEMORY;

+    _bufSize = size;

+  }

+  return S_OK;

 }

 

+HRESULT CFilterCoder::Init_and_Alloc()

+{

+  RINOK(Filter->Init());

+  return Alloc();

+}

+

+CFilterCoder::CFilterCoder(bool encodeMode):

+    _bufSize(0),

+    _inBufSize(kBufSize),

+    _outBufSize(kBufSize),

+    _encodeMode(encodeMode),

+    _outSizeIsDefined(false),

+    _outSize(0),

+    _nowPos64(0)

+  {}

+

 CFilterCoder::~CFilterCoder()

 {

-  ::MidFree(_buffer);

-}

-

-HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)

-{

-  if (_outSizeIsDefined)

-  {

-    UInt64 remSize = _outSize - _nowPos64;

-    if (size > remSize)

-      size = (UInt32)remSize;

-  }

-  RINOK(WriteStream(outStream, _buffer, size));

-  _nowPos64 += size;

-  return S_OK;

 }

 

 STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

     const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)

 {

-  RINOK(Init());

-  UInt32 bufferPos = 0;

-  _outSizeIsDefined = (outSize != 0);

-  if (_outSizeIsDefined)

-    _outSize = *outSize;

+  RINOK(Init_and_Alloc());

+  

+  UInt64 nowPos64 = 0;

+  bool inputFinished = false;

+  UInt32 pos = 0;

 

-  while (!_outSizeIsDefined || _nowPos64 < _outSize)

+  while (!outSize || nowPos64 < *outSize)

   {

-    size_t processedSize = kBufferSize - bufferPos;

+    UInt32 endPos = pos;

     

-    // Change it: It can be optimized using ReadPart

-    RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));

-    

-    UInt32 endPos = bufferPos + (UInt32)processedSize;

-

-    bufferPos = Filter->Filter(_buffer, endPos);

-    if (bufferPos > endPos)

+    if (!inputFinished)

     {

-      for (; endPos < bufferPos; endPos++)

-        _buffer[endPos] = 0;

-      bufferPos = Filter->Filter(_buffer, endPos);

+      size_t processedSize = _bufSize - pos;

+      RINOK(ReadStream(inStream, _buf + pos, &processedSize));

+      endPos = pos + (UInt32)processedSize;

+      inputFinished = (endPos != _bufSize);

     }

 

-    if (bufferPos == 0)

+    pos = Filter->Filter(_buf, endPos);

+    

+    if (pos > endPos)

     {

-      if (endPos == 0)

-        return S_OK;

-      return WriteWithLimit(outStream, endPos);

+      // AES

+      if (!inputFinished || pos > _bufSize)

+        return E_FAIL;

+      if (!_encodeMode)

+        return S_FALSE;

+      

+      do

+        _buf[endPos] = 0;

+      while (++endPos != pos);

+      

+      if (pos != Filter->Filter(_buf, pos))

+        return E_FAIL;

     }

-    RINOK(WriteWithLimit(outStream, bufferPos));

-    if (progress != NULL)

+

+    if (endPos == 0)

+      return S_OK;

+

+    UInt32 size = (pos != 0 ? pos : endPos);

+    if (outSize)

     {

-      RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));

+      UInt64 remSize = *outSize - nowPos64;

+      if (size > remSize)

+        size = (UInt32)remSize;

     }

+    

+    RINOK(WriteStream(outStream, _buf, size));

+    nowPos64 += size;

+

+    if (pos == 0)

+      return S_OK;

+

+    if (progress)

+      RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));

+

     UInt32 i = 0;

-    while (bufferPos < endPos)

-      _buffer[i++] = _buffer[bufferPos++];

-    bufferPos = i;

+    while (pos < endPos)

+      _buf[i++] = _buf[pos++];

+    pos = i;

   }

+

   return S_OK;

 }

 

+

+

+// ---------- Write to Filter ----------

+

 STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)

 {

-  _bufferPos = 0;

   _outStream = outStream;

-  return Init();

+  return S_OK;

 }

 

 STDMETHODIMP CFilterCoder::ReleaseOutStream()

@@ -94,76 +148,154 @@
   return S_OK;

 }

 

+HRESULT CFilterCoder::Flush2()

+{

+  while (_convSize != 0)

+  {

+    UInt32 num = _convSize;

+    if (_outSizeIsDefined)

+    {

+      UInt64 rem = _outSize - _nowPos64;

+      if (num > rem)

+        num = (UInt32)rem;

+      if (num == 0)

+        return k_My_HRESULT_WritingWasCut;

+    }

+    

+    UInt32 processed = 0;

+    HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);

+    if (processed == 0)

+      return res != S_OK ? res : E_FAIL;

+    

+    _convPos += processed;

+    _convSize -= processed;

+    _nowPos64 += processed;

+    RINOK(res);

+  }

+    

+  if (_convPos != 0)

+  {

+    UInt32 num = _bufPos - _convPos;

+    for (UInt32 i = 0; i < num; i++)

+      _buf[i] = _buf[_convPos + i];

+    _bufPos = num;

+    _convPos = 0;

+  }

+    

+  return S_OK;

+}

 

 STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

-  while (size > 0)

+  

+  while (size != 0)

   {

-    UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos);

-    memcpy(_buffer + _bufferPos, data, sizeTemp);

-    size -= sizeTemp;

-    if (processedSize != NULL)

-      *processedSize += sizeTemp;

-    data = (const Byte *)data + sizeTemp;

-    UInt32 endPos = _bufferPos + sizeTemp;

-    _bufferPos = Filter->Filter(_buffer, endPos);

-    if (_bufferPos == 0)

+    RINOK(Flush2());

+

+    // _convSize is 0

+    // _convPos is 0

+    // _bufPos is small

+

+    if (_bufPos != _bufSize)

     {

-      _bufferPos = endPos;

-      break;

+      UInt32 num = MyMin(size, _bufSize - _bufPos);

+      memcpy(_buf + _bufPos, data, num);

+      size -= num;

+      data = (const Byte *)data + num;

+      if (processedSize)

+        *processedSize += num;

+      _bufPos += num;

+      if (_bufPos != _bufSize)

+        continue;

     }

-    if (_bufferPos > endPos)

+

+    // _bufPos == _bufSize

+    _convSize = Filter->Filter(_buf, _bufPos);

+    

+    if (_convSize == 0)

+      break;

+    if (_convSize > _bufPos)

     {

-      if (size != 0)

-        return E_FAIL;

-      break;

+      // that case is not possible.

+      _convSize = 0;

+      return E_FAIL;

     }

-    RINOK(WriteWithLimit(_outStream, _bufferPos));

-    UInt32 i = 0;

-    while (_bufferPos < endPos)

-      _buffer[i++] = _buffer[_bufferPos++];

-    _bufferPos = i;

   }

+

   return S_OK;

 }

 

-STDMETHODIMP CFilterCoder::Flush()

+STDMETHODIMP CFilterCoder::OutStreamFinish()

 {

-  if (_bufferPos != 0)

+  for (;;)

   {

-    // _buffer contains only data refused by previous Filter->Filter call.

-    UInt32 endPos = Filter->Filter(_buffer, _bufferPos);

-    if (endPos > _bufferPos)

+    RINOK(Flush2());

+    if (_bufPos == 0)

+      break;

+    _convSize = Filter->Filter(_buf, _bufPos);

+    if (_convSize == 0)

+      _convSize = _bufPos;

+    else if (_convSize > _bufPos)

     {

-      for (; _bufferPos < endPos; _bufferPos++)

-        _buffer[_bufferPos] = 0;

-      if (Filter->Filter(_buffer, endPos) != endPos)

+      // AES

+      if (_convSize > _bufSize)

+      {

+        _convSize = 0;

+        return E_FAIL;

+      }

+      if (!_encodeMode)

+      {

+        _convSize = 0;

+        return S_FALSE;

+      }

+      for (; _bufPos < _convSize; _bufPos++)

+        _buf[_bufPos] = 0;

+      _convSize = Filter->Filter(_buf, _bufPos);

+      if (_convSize != _bufPos)

         return E_FAIL;

     }

-    RINOK(WriteWithLimit(_outStream, _bufferPos));

-    _bufferPos = 0;

   }

-  CMyComPtr<IOutStreamFlush> flush;

-  _outStream.QueryInterface(IID_IOutStreamFlush, &flush);

-  if (flush)

-    return flush->Flush();

+  

+  CMyComPtr<IOutStreamFinish> finish;

+  _outStream.QueryInterface(IID_IOutStreamFinish, &finish);

+  if (finish)

+    return finish->OutStreamFinish();

   return S_OK;

 }

 

+// ---------- Init functions ----------

 

-void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream)

+STDMETHODIMP CFilterCoder::InitEncoder()

 {

-  _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;

-  _inStream = inStream;

-  Init2();

+  InitSpecVars();

+  return Init_and_Alloc();

 }

 

+HRESULT CFilterCoder::Init_NoSubFilterInit()

+{

+  InitSpecVars();

+  return Alloc();

+}

+

+STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize)

+{

+  InitSpecVars();

+  if (outSize)

+  {

+    _outSize = *outSize;

+    _outSizeIsDefined = true;

+  }

+  return Init_and_Alloc();

+}

+

+// ---------- Read from Filter ----------

+

 STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)

 {

-  SetInStream_NoSubFilterInit(inStream);

-  return Init();

+  _inStream = inStream;

+  return S_OK;

 }

 

 STDMETHODIMP CFilterCoder::ReleaseInStream()

@@ -172,94 +304,115 @@
   return S_OK;

 }

 

+

 STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

-  while (size > 0)

+  

+  while (size != 0)

   {

-    if (_convertedPosBegin != _convertedPosEnd)

+    if (_convSize != 0)

     {

-      UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);

-      memcpy(data, _buffer + _convertedPosBegin, sizeTemp);

-      _convertedPosBegin += sizeTemp;

-      data = (void *)((Byte *)data + sizeTemp);

-      size -= sizeTemp;

-      if (processedSize != NULL)

-        *processedSize += sizeTemp;

+      if (size > _convSize)

+        size = _convSize;

+      if (_outSizeIsDefined)

+      {

+        UInt64 rem = _outSize - _nowPos64;

+        if (size > rem)

+          size = (UInt32)rem;

+      }

+      memcpy(data, _buf + _convPos, size);

+      _convPos += size;

+      _convSize -= size;

+      _nowPos64 += size;

+      if (processedSize)

+        *processedSize = size;

       break;

     }

-    UInt32 i;

-    for (i = 0; _convertedPosEnd + i < _bufferPos; i++)

-      _buffer[i] = _buffer[_convertedPosEnd + i];

-    _bufferPos = i;

-    _convertedPosBegin = _convertedPosEnd = 0;

-    size_t processedSizeTemp = kBufferSize - _bufferPos;

-    RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));

-    _bufferPos += (UInt32)processedSizeTemp;

-    _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);

-    if (_convertedPosEnd == 0)

+  

+    if (_convPos != 0)

     {

-      if (_bufferPos == 0)

+      UInt32 num = _bufPos - _convPos;

+      for (UInt32 i = 0; i < num; i++)

+        _buf[i] = _buf[_convPos + i];

+      _bufPos = num;

+      _convPos = 0;

+    }

+    

+    {

+      size_t readSize = _bufSize - _bufPos;

+      HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);

+      _bufPos += (UInt32)readSize;

+      RINOK(res);

+    }

+    

+    _convSize = Filter->Filter(_buf, _bufPos);

+    

+    if (_convSize == 0)

+    {

+      if (_bufPos == 0)

         break;

-      _convertedPosEnd = _bufferPos; // check it

+      // BCJ

+      _convSize = _bufPos;

       continue;

     }

-    if (_convertedPosEnd > _bufferPos)

+    

+    if (_convSize > _bufPos)

     {

-      for (; _bufferPos < _convertedPosEnd; _bufferPos++)

-        _buffer[_bufferPos] = 0;

-      _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);

+      // AES

+      if (_convSize > _bufSize)

+        return E_FAIL;

+      if (!_encodeMode)

+        return S_FALSE;

+      

+      do

+        _buf[_bufPos] = 0;

+      while (++_bufPos != _convSize);

+      

+      _convSize = Filter->Filter(_buf, _convSize);

+      if (_convSize != _bufPos)

+        return E_FAIL;

     }

   }

+ 

   return S_OK;

 }

 

+

 #ifndef _NO_CRYPTO

 

 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)

-{

-  return _setPassword->CryptoSetPassword(data, size);

-}

+  { return _SetPassword->CryptoSetPassword(data, size); }

 

 STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)

-{

-  return _cryptoProperties->SetKey(data, size);

-}

+  { return _CryptoProperties->SetKey(data, size); }

 

 STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)

-{

-  return _cryptoProperties->SetInitVector(data, size);

-}

+  { return _CryptoProperties->SetInitVector(data, size); }

 

 #endif

 

+

 #ifndef EXTRACT_ONLY

+

 STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,

-      const PROPVARIANT *properties, UInt32 numProperties)

-{

-  return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);

-}

+    const PROPVARIANT *properties, UInt32 numProperties)

+  { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }

 

 STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)

-{

-  return _writeCoderProperties->WriteCoderProperties(outStream);

-}

+  { return _WriteCoderProperties->WriteCoderProperties(outStream); }

 

 /*

 STDMETHODIMP CFilterCoder::ResetSalt()

-{

-  return _CryptoResetSalt->ResetSalt();

-}

+  { return _CryptoResetSalt->ResetSalt(); }

 */

 

 STDMETHODIMP CFilterCoder::ResetInitVector()

-{

-  return _CryptoResetInitVector->ResetInitVector();

-}

+  { return _CryptoResetInitVector->ResetInitVector(); }

+

 #endif

 

+

 STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)

-{

-  return _setDecoderProperties->SetDecoderProperties2(data, size);

-}

+  { return _SetDecoderProperties2->SetDecoderProperties2(data, size); }

diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index 35e877f..7890e56 100644
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -3,106 +3,204 @@
 #ifndef __FILTER_CODER_H

 #define __FILTER_CODER_H

 

+#include "../../../C/Alloc.h"

+

 #include "../../Common/MyCom.h"

 #include "../ICoder.h"

+

+#ifndef _NO_CRYPTO

 #include "../IPassword.h"

+#endif

 

 #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \

   { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \

     *outObject = (void *)(i *)this; }

 

+

+struct CAlignedMidBuffer

+{

+  #ifdef _WIN32

+

+  Byte *_buf;

+

+  CAlignedMidBuffer(): _buf(NULL) {}

+  ~CAlignedMidBuffer() { ::MidFree(_buf); }

+  

+  void AllocAlignedMask(size_t size, size_t)

+  {

+    ::MidFree(_buf);

+    _buf = (Byte *)::MidAlloc(size);

+  }

+  

+  #else

+  

+  Byte *_bufBase;

+  Byte *_buf;

+

+  CAlignedMidBuffer(): _bufBase(NULL), _buf(NULL) {}

+  ~CAlignedMidBuffer() { ::MidFree(_bufBase); }

+  

+  void AllocAlignedMask(size_t size, size_t alignMask)

+  {

+    ::MidFree(_bufBase);

+    _buf = NULL;

+    _bufBase = (Byte *)::MidAlloc(size + alignMask);

+    

+    if (_bufBase)

+    {

+      // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);

+         _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);

+    }

+  }

+  

+  #endif

+};

+

 class CFilterCoder:

   public ICompressCoder,

+  

+  public ICompressSetOutStreamSize,

+  public ICompressInitEncoder,

+ 

   public ICompressSetInStream,

   public ISequentialInStream,

+  

   public ICompressSetOutStream,

   public ISequentialOutStream,

-  public IOutStreamFlush,

+  public IOutStreamFinish,

+  

+  public ICompressSetBufSize,

 

   #ifndef _NO_CRYPTO

   public ICryptoSetPassword,

   public ICryptoProperties,

   #endif

+  

   #ifndef EXTRACT_ONLY

   public ICompressSetCoderProperties,

   public ICompressWriteCoderProperties,

   // public ICryptoResetSalt,

   public ICryptoResetInitVector,

   #endif

+  

   public ICompressSetDecoderProperties2,

-  public CMyUnknownImp

+  public CMyUnknownImp,

+  public CAlignedMidBuffer

 {

-protected:

-  Byte *_buffer;

-  CMyComPtr<ISequentialInStream> _inStream;

-  CMyComPtr<ISequentialOutStream> _outStream;

-  UInt32 _bufferPos;

-  UInt32 _convertedPosBegin;

-  UInt32 _convertedPosEnd;

+  UInt32 _bufSize;

+  UInt32 _inBufSize;

+  UInt32 _outBufSize;

+

+  bool _encodeMode;

   bool _outSizeIsDefined;

   UInt64 _outSize;

   UInt64 _nowPos64;

 

-  void Init2()

+  CMyComPtr<ISequentialInStream> _inStream;

+  CMyComPtr<ISequentialOutStream> _outStream;

+  UInt32 _bufPos;

+  UInt32 _convPos;    // current pos in buffer for converted data

+  UInt32 _convSize;   // size of converted data starting from _convPos

+  

+  void InitSpecVars()

   {

-    _nowPos64 = 0;

+    _bufPos = 0;

+    _convPos = 0;

+    _convSize = 0;

+

     _outSizeIsDefined = false;

+    _outSize = 0;

+    _nowPos64 = 0;

   }

 

-  HRESULT Init()

-  {

-    Init2();

-    return Filter->Init();

-  }

+  HRESULT Alloc();

+  HRESULT Init_and_Alloc();

+  HRESULT Flush2();

 

-  CMyComPtr<ICryptoSetPassword> _setPassword;

-  CMyComPtr<ICryptoProperties> _cryptoProperties;

+  #ifndef _NO_CRYPTO

+  CMyComPtr<ICryptoSetPassword> _SetPassword;

+  CMyComPtr<ICryptoProperties> _CryptoProperties;

+  #endif

+

   #ifndef EXTRACT_ONLY

   CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;

-  CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;

+  CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;

   // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;

   CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;

   #endif

-  CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;

+

+  CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;

+

 public:

   CMyComPtr<ICompressFilter> Filter;

 

-  CFilterCoder();

+  CFilterCoder(bool encodeMode);

   ~CFilterCoder();

-  HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);

 

-public:

+  class C_InStream_Releaser

+  {

+  public:

+    CFilterCoder *FilterCoder;

+    C_InStream_Releaser(): FilterCoder(NULL) {}

+    ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }

+  };

+  

+  class C_OutStream_Releaser

+  {

+  public:

+    CFilterCoder *FilterCoder;

+    C_OutStream_Releaser(): FilterCoder(NULL) {}

+    ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }

+  };

+

   MY_QUERYINTERFACE_BEGIN2(ICompressCoder)

+

+    MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)

+    MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder)

+    

     MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)

     MY_QUERYINTERFACE_ENTRY(ISequentialInStream)

+    

     MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)

     MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)

-    MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)

+    MY_QUERYINTERFACE_ENTRY(IOutStreamFinish)

+    

+    MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)

 

     #ifndef _NO_CRYPTO

-    MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)

-    MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties)

+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword)

+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties)

     #endif

 

     #ifndef EXTRACT_ONLY

     MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)

-    MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)

+    MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties)

     // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)

     MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)

     #endif

 

-    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)

+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2)

   MY_QUERYINTERFACE_END

   MY_ADDREF_RELEASE

+  

+  

   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

-  STDMETHOD(ReleaseInStream)();

+  

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

+  STDMETHOD(InitEncoder)();

+

   STDMETHOD(SetInStream)(ISequentialInStream *inStream);

-  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+

   STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);

   STDMETHOD(ReleaseOutStream)();

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

-  STDMETHOD(Flush)();

+  STDMETHOD(OutStreamFinish)();

+  

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

 

   #ifndef _NO_CRYPTO

   STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);

@@ -110,6 +208,7 @@
   STDMETHOD(SetKey)(const Byte *data, UInt32 size);

   STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);

   #endif

+  

   #ifndef EXTRACT_ONLY

   STDMETHOD(SetCoderProperties)(const PROPID *propIDs,

       const PROPVARIANT *properties, UInt32 numProperties);

@@ -117,26 +216,11 @@
   // STDMETHOD(ResetSalt)();

   STDMETHOD(ResetInitVector)();

   #endif

+  

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

 

-  void SetInStream_NoSubFilterInit(ISequentialInStream *inStream);

-

-};

-

-class CInStreamReleaser

-{

-public:

-  CFilterCoder *FilterCoder;

-  CInStreamReleaser(): FilterCoder(0) {}

-  ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }

-};

-

-class COutStreamReleaser

-{

-public:

-  CFilterCoder *FilterCoder;

-  COutStreamReleaser(): FilterCoder(0) {}

-  ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }

+  

+  HRESULT Init_NoSubFilterInit();

 };

 

 #endif

diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
index 591d01e..cf4bffe 100644
--- a/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -13,7 +13,7 @@
 using namespace NFile;

 using namespace NDir;

 

-static const UInt32 kTempBufSize = (1 << 20);

+static const size_t kTempBufSize = (1 << 20);

 

 static CFSTR kTempFilePrefixString = FTEXT("7zt");

 

@@ -58,15 +58,19 @@
 

 bool CInOutTempBuffer::Write(const void *data, UInt32 size)

 {

-  if (_bufPos < kTempBufSize)

+  if (size == 0)

+    return true;

+  size_t cur = kTempBufSize - _bufPos;

+  if (cur != 0)

   {

-    UInt32 cur = MyMin(kTempBufSize - _bufPos, size);

+    if (cur > size)

+      cur = size;

     memcpy(_buf + _bufPos, data, cur);

     _crc = CrcUpdate(_crc, data, cur);

     _bufPos += cur;

-    size -= cur;

-    data = ((const Byte *)data) + cur;

     _size += cur;

+    size -= (UInt32)cur;

+    data = ((const Byte *)data) + cur;

   }

   return WriteToFile(data, size);

 }

@@ -79,12 +83,13 @@
   UInt64 size = 0;

   UInt32 crc = CRC_INIT_VAL;

 

-  if (_bufPos > 0)

+  if (_bufPos != 0)

   {

     RINOK(WriteStream(stream, _buf, _bufPos));

     crc = CrcUpdate(crc, _buf, _bufPos);

     size += _bufPos;

   }

+  

   if (_tempFileCreated)

   {

     NIO::CInFile inFile;

@@ -102,18 +107,21 @@
       size += processed;

     }

   }

+  

   return (_crc == crc && size == _size) ? S_OK : E_FAIL;

 }

 

+/*

 STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)

 {

   if (!_buf->Write(data, size))

   {

-    if (processed != NULL)

+    if (processed)

       *processed = 0;

     return E_FAIL;

   }

-  if (processed != NULL)

+  if (processed)

     *processed = size;

   return S_OK;

 }

+*/

diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h
index 710e474..4140d28 100644
--- a/CPP/7zip/Common/InOutTempBuffer.h
+++ b/CPP/7zip/Common/InOutTempBuffer.h
@@ -13,10 +13,10 @@
   NWindows::NFile::NDir::CTempFile _tempFile;

   NWindows::NFile::NIO::COutFile _outFile;

   Byte *_buf;

-  UInt32 _bufPos;

-  bool _tempFileCreated;

+  size_t _bufPos;

   UInt64 _size;

   UInt32 _crc;

+  bool _tempFileCreated;

 

   bool WriteToFile(const void *data, UInt32 size);

 public:

@@ -31,6 +31,7 @@
   UInt64 GetDataSize() const { return _size; }

 };

 

+/*

 class CSequentialOutTempBufferImp:

   public ISequentialOutStream,

   public CMyUnknownImp

@@ -42,5 +43,6 @@
 

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

+*/

 

 #endif

diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index 174cac1..fc7e794 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -2,17 +2,22 @@
 

 #include "StdAfx.h"

 

+#include <string.h>

+

 #include "LimitedStreams.h"

-#include "../../Common/Defs.h"

 

 STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

   UInt32 realProcessedSize = 0;

-  UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);

-  HRESULT result = S_OK;

-  if (sizeToRead > 0)

   {

-    result = _stream->Read(data, sizeToRead, &realProcessedSize);

+    const UInt64 rem = _size - _pos;

+    if (size > rem)

+      size = (UInt32)rem;

+  }

+  HRESULT result = S_OK;

+  if (size != 0)

+  {

+    result = _stream->Read(data, size, &realProcessedSize);

     _pos += realProcessedSize;

     if (realProcessedSize == 0)

       _wasFinished = true;

@@ -32,9 +37,11 @@
     return S_OK;

     // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF

   }

-  UInt64 rem = _size - _virtPos;

-  if (rem < size)

-    size = (UInt32)rem;

+  {

+    const UInt64 rem = _size - _virtPos;

+    if (size > rem)

+      size = (UInt32)rem;

+  }

   UInt64 newPos = _startOffset + _virtPos;

   if (newPos != _physPos)

   {

@@ -84,26 +91,34 @@
     *processedSize = 0;

   if (_virtPos >= Size)

     return S_OK;

+  {

+    UInt64 rem = Size - _virtPos;

+    if (size > rem)

+      size = (UInt32)rem;

+  }

+  if (size == 0)

+    return S_OK;

 

   if (_curRem == 0)

   {

-    UInt32 blockSize = (UInt32)1 << BlockSizeLog;

-    UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);

-    UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);

-    UInt32 phyBlock = Vector[virtBlock];

+    const UInt32 blockSize = (UInt32)1 << BlockSizeLog;

+    const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);

+    const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);

+    const UInt32 phyBlock = Vector[virtBlock];

+    

     UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;

     if (newPos != _physPos)

     {

       _physPos = newPos;

       RINOK(SeekToPhys());

     }

+

     _curRem = blockSize - offsetInBlock;

+    

     for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)

       _curRem += (UInt32)1 << BlockSizeLog;

-    UInt64 rem = Size - _virtPos;

-    if (_curRem > rem)

-      _curRem = (UInt32)rem;

   }

+  

   if (size > _curRem)

     size = _curRem;

   HRESULT res = Stream->Read(data, size, &size);

@@ -279,7 +294,10 @@
   if (newPos >= _cachePhyPos &&

       offsetInCache <= _cacheSize &&

       size <= _cacheSize - (size_t)offsetInCache)

-    memcpy(data, _cache + (size_t)offsetInCache, size);

+  {

+    if (size != 0)

+      memcpy(data, _cache + (size_t)offsetInCache, size);

+  }

   else

   {

     if (newPos != _physPos)

diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
index 8c89502..2e55aa0 100644
--- a/CPP/7zip/Common/LimitedStreams.h
+++ b/CPP/7zip/Common/LimitedStreams.h
@@ -30,6 +30,7 @@
 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   UInt64 GetSize() const { return _pos; }

+  UInt64 GetRem() const { return _size - _pos; }

   bool WasFinished() const { return _wasFinished; }

 };

 

@@ -73,11 +74,11 @@
   UInt64 _physPos;

   UInt32 _curRem;

 public:

-  CMyComPtr<IInStream> Stream;

-  UInt64 StartOffset;

-  UInt64 Size;

   unsigned BlockSizeLog;

+  UInt64 Size;

+  CMyComPtr<IInStream> Stream;

   CRecordVector<UInt32> Vector;

+  UInt64 StartOffset;

 

   HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

 

diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
index d1bbf6d..1223efe 100644
--- a/CPP/7zip/Common/LockedStream.cpp
+++ b/CPP/7zip/Common/LockedStream.cpp
@@ -1,23 +1,3 @@
 // LockedStream.cpp

 

 #include "StdAfx.h"

-

-#include "LockedStream.h"

-

-HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size,

-  UInt32 *processedSize)

-{

-  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);

-  RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));

-  return _stream->Read(data, size, processedSize);

-}

-

-STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)

-{

-  UInt32 realProcessedSize = 0;

-  HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);

-  _pos += realProcessedSize;

-  if (processedSize != NULL)

-    *processedSize = realProcessedSize;

-  return result;

-}

diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
index e12e22a..5bf5c85 100644
--- a/CPP/7zip/Common/LockedStream.h
+++ b/CPP/7zip/Common/LockedStream.h
@@ -1,38 +1,6 @@
 // LockedStream.h

 

-#ifndef __LOCKEDSTREAM_H

-#define __LOCKEDSTREAM_H

-

-#include "../../Windows/Synchronization.h"

-#include "../../Common/MyCom.h"

-#include "../IStream.h"

-

-class CLockedInStream

-{

-  CMyComPtr<IInStream> _stream;

-  NWindows::NSynchronization::CCriticalSection _criticalSection;

-public:

-  void Init(IInStream *stream)

-    { _stream = stream; }

-  HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);

-};

-

-class CLockedSequentialInStreamImp:

-  public ISequentialInStream,

-  public CMyUnknownImp

-{

-  CLockedInStream *_lockedInStream;

-  UInt64 _pos;

-public:

-  void Init(CLockedInStream *lockedInStream, UInt64 startPos)

-  {

-    _lockedInStream = lockedInStream;

-    _pos = startPos;

-  }

-

-  MY_UNKNOWN_IMP

-

-  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

-};

+#ifndef __LOCKED_STREAM_H

+#define __LOCKED_STREAM_H

 

 #endif

diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index 0773511..7036572 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -10,12 +10,12 @@
 

 bool StringToBool(const UString &s, bool &res)

 {

-  if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON"))

+  if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))

   {

     res = true;

     return true;

   }

-  if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF"))

+  if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))

   {

     res = false;

     return true;

@@ -90,58 +90,71 @@
   return ParsePropToUInt32(name, prop, numThreads);

 }

 

-static HRESULT StringToDictSize(const UString &s, UInt32 &dicSize)

+

+static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)

 {

   const wchar_t *end;

   UInt32 number = ConvertStringToUInt32(s, &end);

   unsigned numDigits = (unsigned)(end - s);

   if (numDigits == 0 || s.Len() > numDigits + 1)

     return E_INVALIDARG;

-  const unsigned kLogDictSizeLimit = 32;

+  

   if (s.Len() == numDigits)

   {

-    if (number >= kLogDictSizeLimit)

+    if (number >= 64)

       return E_INVALIDARG;

-    dicSize = (UInt32)1 << (unsigned)number;

+    if (number < 32)

+      destProp = (UInt32)((UInt32)1 << (unsigned)number);

+    else

+      destProp = (UInt64)((UInt64)1 << (unsigned)number);

     return S_OK;

   }

+  

   unsigned numBits;

+  

   switch (MyCharLower_Ascii(s[numDigits]))

   {

-    case 'b': dicSize = number; return S_OK;

+    case 'b': destProp = number; return S_OK;

     case 'k': numBits = 10; break;

     case 'm': numBits = 20; break;

     case 'g': numBits = 30; break;

     default: return E_INVALIDARG;

   }

-  if (number >= ((UInt32)1 << (kLogDictSizeLimit - numBits)))

-    return E_INVALIDARG;

-  dicSize = number << numBits;

+  

+  if (number < ((UInt32)1 << (32 - numBits)))

+    destProp = (UInt32)(number << numBits);

+  else

+    destProp = (UInt64)((UInt64)number << numBits);

+  

   return S_OK;

 }

 

-static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue)

+

+static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)

 {

   if (prop.vt == VT_UI4)

   {

     UInt32 v = prop.ulVal;

-    if (v >= 32)

+    if (v >= 64)

       return E_INVALIDARG;

-    resValue = (UInt32)1 << v;

+    if (v < 32)

+      destProp = (UInt32)((UInt32)1 << (unsigned)v);

+    else

+      destProp = (UInt64)((UInt64)1 << (unsigned)v);

     return S_OK;

   }

   if (prop.vt == VT_BSTR)

-    return StringToDictSize(prop.bstrVal, resValue);

+    return StringToDictSize(prop.bstrVal, destProp);

   return E_INVALIDARG;

 }

 

+

 void CProps::AddProp32(PROPID propid, UInt32 level)

 {

-  CProp prop;

+  CProp &prop = Props.AddNew();

   prop.IsOptional = true;

   prop.Id = propid;

   prop.Value = (UInt32)level;

-  Props.Add(prop);

 }

 

 class CCoderProps

@@ -276,10 +289,10 @@
 {

   subStrings.Clear();

   UString s;

-  int len = srcString.Len();

+  unsigned len = srcString.Len();

   if (len == 0)

     return;

-  for (int i = 0; i < len; i++)

+  for (unsigned i = 0; i < len; i++)

   {

     wchar_t c = srcString[i];

     if (c == L':')

@@ -331,15 +344,13 @@
   int index = FindPropIdExact(name);

   if (index < 0)

     return E_INVALIDARG;

-  const CNameToPropID &nameToPropID = g_NameToPropID[index];

+  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];

   CProp prop;

   prop.Id = index;

 

   if (IsLogSizeProp(prop.Id))

   {

-    UInt32 dicSize;

-    RINOK(StringToDictSize(value, dicSize));

-    prop.Value = dicSize;

+    RINOK(StringToDictSize(value, prop.Value));

   }

   else

   {

@@ -392,24 +403,22 @@
   if (value.vt == VT_EMPTY)

   {

     // {realName}=[empty]

-    UString name, value;

-    SplitParam(realName, name, value);

-    return SetParam(name, value);

+    UString name, valueStr;

+    SplitParam(realName, name, valueStr);

+    return SetParam(name, valueStr);

   }

   

   // {realName}=value

   int index = FindPropIdExact(realName);

   if (index < 0)

     return E_INVALIDARG;

-  const CNameToPropID &nameToPropID = g_NameToPropID[index];

+  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];

   CProp prop;

   prop.Id = index;

   

   if (IsLogSizeProp(prop.Id))

   {

-    UInt32 dicSize;

-    RINOK(PROPVARIANT_to_DictSize(value, dicSize));

-    prop.Value = dicSize;

+    RINOK(PROPVARIANT_to_DictSize(value, prop.Value));

   }

   else

   {

@@ -422,12 +431,20 @@
 

 HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)

 {

-  int splitPos = s.Find(':');

-  MethodName = s;

+  MethodName.Empty();

+  int splitPos = s.Find(L':');

+  {

+    UString temp = s;

+    if (splitPos >= 0)

+      temp.DeleteFrom(splitPos);

+    if (!temp.IsAscii())

+      return E_INVALIDARG;

+    MethodName.SetFromWStr_if_Ascii(temp);

+  }

   if (splitPos < 0)

     return S_OK;

-  MethodName.DeleteFrom(splitPos);

-  return ParseParamsFromString(s.Ptr(splitPos + 1));

+  PropsString = s.Ptr(splitPos + 1);

+  return ParseParamsFromString(PropsString);

 }

 

 HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)

diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
index cc2b276..3f31c77 100644
--- a/CPP/7zip/Common/MethodProps.h
+++ b/CPP/7zip/Common/MethodProps.h
@@ -40,13 +40,12 @@
 

   void AddProp32(PROPID propid, UInt32 level);

 

-  void AddPropString(PROPID propid, const wchar_t *s)

+  void AddProp_Ascii(PROPID propid, const char *s)

   {

-    CProp prop;

+    CProp &prop = Props.AddNew();

     prop.IsOptional = true;

     prop.Id = propid;

     prop.Value = s;

-    Props.Add(prop);

   }

 

   HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;

@@ -100,6 +99,14 @@
     return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));

   }

 

+  bool Are_Lzma_Model_Props_Defined() const

+  {

+    if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;

+    if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;

+    if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;

+    return false;

+  }

+

   UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const

   {

     fixedNumber = false;

@@ -153,12 +160,12 @@
     return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));

   }

 

-  void AddLevelProp(UInt32 level)

+  void AddProp_Level(UInt32 level)

   {

     AddProp32(NCoderPropID::kLevel, level);

   }

 

-  void AddNumThreadsProp(UInt32 numThreads)

+  void AddProp_NumThreads(UInt32 numThreads)

   {

     AddProp32(NCoderPropID::kNumThreads, numThreads);

   }

@@ -170,12 +177,14 @@
 class COneMethodInfo: public CMethodProps

 {

 public:

-  UString MethodName;

+  AString MethodName;

+  UString PropsString;

   

   void Clear()

   {

     CMethodProps::Clear();

     MethodName.Empty();

+    PropsString.Empty();

   }

   bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }

   HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);

diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
index cfe504a..86f1e78 100644
--- a/CPP/7zip/Common/ProgressUtils.cpp
+++ b/CPP/7zip/Common/ProgressUtils.cpp
@@ -4,11 +4,13 @@
 

 #include "ProgressUtils.h"

 

-CLocalProgress::CLocalProgress()

-{

-  ProgressOffset = InSize = OutSize = 0;

-  SendRatio = SendProgress = true;

-}

+CLocalProgress::CLocalProgress():

+    ProgressOffset(0),

+    InSize(0),

+    OutSize(0),

+    SendRatio(true),

+    SendProgress(true)

+  {}

 

 void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)

 {

@@ -20,19 +22,26 @@
 

 STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

 {

-  UInt64 inSizeNew = InSize, outSizeNew = OutSize;

+  UInt64 inSize2 = InSize;

+  UInt64 outSize2 = OutSize;

+  

   if (inSize)

-    inSizeNew += (*inSize);

+    inSize2 += (*inSize);

   if (outSize)

-    outSizeNew += (*outSize);

+    outSize2 += (*outSize);

+  

   if (SendRatio && _ratioProgress)

   {

-    RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));

+    RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));

   }

-  inSizeNew += ProgressOffset;

-  outSizeNew += ProgressOffset;

+  

   if (SendProgress)

-    return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);

+  {

+    inSize2 += ProgressOffset;

+    outSize2 += ProgressOffset;

+    return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);

+  }

+  

   return S_OK;

 }

 

diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h
index c620484..176e8bb 100644
--- a/CPP/7zip/Common/ProgressUtils.h
+++ b/CPP/7zip/Common/ProgressUtils.h
@@ -1,7 +1,7 @@
 // ProgressUtils.h

 

-#ifndef __PROGRESSUTILS_H

-#define __PROGRESSUTILS_H

+#ifndef __PROGRESS_UTILS_H

+#define __PROGRESS_UTILS_H

 

 #include "../../Common/MyCom.h"

 

@@ -23,10 +23,11 @@
   bool SendProgress;

 

   CLocalProgress();

+

   void Init(IProgress *progress, bool inSizeIsMain);

   HRESULT SetCur();

 

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ICompressProgressInfo)

 

   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

 };

diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp
index b82b944..96f8f05 100644
--- a/CPP/7zip/Common/PropId.cpp
+++ b/CPP/7zip/Common/PropId.cpp
@@ -2,10 +2,12 @@
 

 #include "StdAfx.h"

 

+#include "../../Common/MyWindows.h"

+

 #include "../PropID.h"

 

 // VARTYPE

-Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =

+const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =

 {

   VT_EMPTY,

   VT_UI4,

@@ -95,5 +97,12 @@
   VT_BOOL,

   VT_BOOL,

   VT_UI8,

-  VT_UI8

+  VT_UI8,

+  VT_BSTR, // kpidNtReparse

+  VT_BSTR,

+  VT_UI8,

+  VT_UI8,

+  VT_BOOL,

+  VT_BSTR,

+  VT_BSTR

 };

diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h
index b4cf1bf..08aa2d4 100644
--- a/CPP/7zip/Common/RegisterArc.h
+++ b/CPP/7zip/Common/RegisterArc.h
@@ -7,18 +7,16 @@
 

 struct CArcInfo

 {

+  UInt16 Flags;

+  Byte Id;

+  Byte SignatureSize;

+  UInt16 SignatureOffset;

+  

+  const Byte *Signature;

   const char *Name;

   const char *Ext;

   const char *AddExt;

   

-  Byte ClassId;

-  

-  Byte SignatureSize;

-  Byte Signature[20];

-  UInt16 SignatureOffset;

-  

-  UInt16 Flags;

-

   Func_CreateInArchive CreateInArchive;

   Func_CreateOutArchive CreateOutArchive;

   Func_IsArc IsArc;

@@ -28,28 +26,53 @@
 

 void RegisterArc(const CArcInfo *arcInfo) throw();

 

-#define REGISTER_ARC_NAME(x) CRegister ## x

-

-#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \

-    REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \

-    static REGISTER_ARC_NAME(x) g_RegisterArc;

-

-#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \

-    REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \

-    static REGISTER_ARC_NAME(x) g_RegisterArc;

-

 

 #define IMP_CreateArcIn_2(c) \

   static IInArchive *CreateArc() { return new c; }

 

-#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler)

+#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())

 

 #ifdef EXTRACT_ONLY

   #define IMP_CreateArcOut

-  #define REF_CreateArc_Pair CreateArc, NULL

+  #define CreateArcOut NULL

 #else

-  #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; }

-  #define REF_CreateArc_Pair CreateArc, CreateArcOut

+  #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); }

 #endif

 

+#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \

+  static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \

+

+#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \

+  REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \

+  struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \

+  static CRegisterArc g_RegisterArc;

+

+

+#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \

+  IMP_CreateArcIn_2(cls) \

+  REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc)

+

+#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \

+  IMP_CreateArcIn_2(cls) \

+  REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc)

+

+#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \

+  REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc)

+

+#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \

+  REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc)

+

+

+#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \

+  IMP_CreateArcIn \

+  IMP_CreateArcOut \

+  REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc)

+

+#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \

+  IMP_CreateArcIn \

+  IMP_CreateArcOut \

+  REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \

+  struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \

+  static CRegisterArcDecSig g_RegisterArc;

+

 #endif

diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h
index d51dccb..b566065 100644
--- a/CPP/7zip/Common/RegisterCodec.h
+++ b/CPP/7zip/Common/RegisterCodec.h
@@ -4,48 +4,103 @@
 #define __REGISTER_CODEC_H

 

 #include "../Common/MethodId.h"

+

 #include "../ICoder.h"

 

 typedef void * (*CreateCodecP)();

+

 struct CCodecInfo

 {

   CreateCodecP CreateDecoder;

   CreateCodecP CreateEncoder;

   CMethodId Id;

-  const wchar_t *Name;

-  UInt32 NumInStreams;

+  const char *Name;

+  UInt32 NumStreams;

   bool IsFilter;

 };

 

 void RegisterCodec(const CCodecInfo *codecInfo) throw();

 

+

+#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); }

+#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder)

+

 #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x

+#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo =

 

 #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \

     REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \

     static REGISTER_CODEC_NAME(x) g_RegisterCodec;

 

+

 #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x

+#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =

+

 #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \

     REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \

     RegisterCodec(&g_CodecsInfo[i]); }}; \

     static REGISTER_CODECS_NAME(x) g_RegisterCodecs;

 

 

+#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \

+    REGISTER_CODEC_VAR \

+    { crDec, crEnc, id, name, 1, false }; \

+    REGISTER_CODEC(x)

+

+

+#ifdef EXTRACT_ONLY

+  #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \

+    REGISTER_CODEC_CREATE(CreateDec, clsDec) \

+    REGISTER_CODEC_2(x, CreateDec, NULL, id, name)

+#else

+  #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \

+    REGISTER_CODEC_CREATE(CreateDec, clsDec) \

+    REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \

+    REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name)

+#endif

+

+

+

+#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter)

+

+#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \

+    { crDec, crEnc, id, name, 1, true }

+

+#define REGISTER_FILTER(x, crDec, crEnc, id, name) \

+    REGISTER_CODEC_VAR \

+    REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \

+    REGISTER_CODEC(x)

+

+#ifdef EXTRACT_ONLY

+  #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \

+    REGISTER_FILTER_CREATE(CreateDec, clsDec) \

+    REGISTER_FILTER(x, CreateDec, NULL, id, name)

+#else

+  #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \

+    REGISTER_FILTER_CREATE(CreateDec, clsDec) \

+    REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \

+    REGISTER_FILTER(x, CreateDec, CreateEnc, id, name)

+#endif

+

+

+

 struct CHasherInfo

 {

   IHasher * (*CreateHasher)();

   CMethodId Id;

-  const wchar_t *Name;

+  const char *Name;

   UInt32 DigestSize;

 };

 

 void RegisterHasher(const CHasherInfo *hasher) throw();

 

-#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x

+#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x

 

-#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \

-    REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \

-    static REGISTER_HASHER_NAME(x) g_RegisterHasher;

+#define REGISTER_HASHER(cls, id, name, size) \

+    STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \

+    static IHasher *CreateHasherSpec() { return new cls(); } \

+    static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \

+    struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \

+    static REGISTER_HASHER_NAME(cls) g_RegisterHasher;

 

 #endif

diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp
index b3d056d..a6627db 100644
--- a/CPP/7zip/Common/StreamBinder.cpp
+++ b/CPP/7zip/Common/StreamBinder.cpp
@@ -12,7 +12,7 @@
 {

   CStreamBinder *_binder;

 public:

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialInStream)

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   ~CBinderInStream() { _binder->CloseRead(); }

   CBinderInStream(CStreamBinder *binder): _binder(binder) {}

@@ -27,7 +27,7 @@
 {

   CStreamBinder *_binder;

 public:

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

   ~CBinderOutStream() { _binder->CloseWrite(); }

   CBinderOutStream(CStreamBinder *binder): _binder(binder) {}

@@ -40,26 +40,38 @@
 

 WRes CStreamBinder::CreateEvents()

 {

-  RINOK(_canWrite_Event.Create(true));

+  RINOK(_canWrite_Event.Create());

   RINOK(_canRead_Event.Create());

   return _readingWasClosed_Event.Create();

 }

 

 void CStreamBinder::ReInit()

 {

-  _waitWrite = true;

+  _canWrite_Event.Reset();

   _canRead_Event.Reset();

   _readingWasClosed_Event.Reset();

+

+  // _readingWasClosed = false;

+  _readingWasClosed2 = false;

+

+  _waitWrite = true;

+  _bufSize = 0;

+  _buf = NULL;

   ProcessedSize = 0;

+  // WritingWasCut = false;

 }

 

 

 void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)

 {

+  // _readingWasClosed = false;

+  _readingWasClosed2 = false;

+

   _waitWrite = true;

   _bufSize = 0;

   _buf = NULL;

   ProcessedSize = 0;

+  // WritingWasCut = false;

 

   CBinderInStream *inStreamSpec = new CBinderInStream(this);

   CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

@@ -108,19 +120,37 @@
 {

   if (processedSize)

     *processedSize = 0;

-  if (size != 0)

+  if (size == 0)

+    return S_OK;

+

+  if (!_readingWasClosed2)

   {

     _buf = data;

     _bufSize = size;

-    _canWrite_Event.Reset();

     _canRead_Event.Set();

+    

+    /*

+    _canWrite_Event.Lock();

+    if (_readingWasClosed)

+      _readingWasClosed2 = true;

+    */

 

     HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };

     DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);

-    if (waitResult != WAIT_OBJECT_0 + 0)

-      return S_FALSE;

-    if (processedSize)

-      *processedSize = size;

+    if (waitResult >= WAIT_OBJECT_0 + 2)

+      return E_FAIL;

+

+    size -= _bufSize;

+    if (size != 0)

+    {

+      if (processedSize)

+        *processedSize = size;

+      return S_OK;

+    }

+    // if (waitResult == WAIT_OBJECT_0 + 1)

+      _readingWasClosed2 = true;

   }

-  return S_OK;

+

+  // WritingWasCut = true;

+  return k_My_HRESULT_WritingWasCut;

 }

diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
index 52733f9..f4d4f3b 100644
--- a/CPP/7zip/Common/StreamBinder.h
+++ b/CPP/7zip/Common/StreamBinder.h
@@ -7,11 +7,27 @@
 

 #include "../IStream.h"

 

+/*

+We don't use probably UNSAFE version:

+reader thread:

+     _canWrite_Event.Set();

+     _readingWasClosed = true

+     _canWrite_Event.Set();

+writer thread:

+     _canWrite_Event.Wait()

+      if (_readingWasClosed)

+Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set?

+*/

+

 class CStreamBinder

 {

-  NWindows::NSynchronization::CManualResetEvent _canWrite_Event;

+  NWindows::NSynchronization::CAutoResetEvent _canWrite_Event;

   NWindows::NSynchronization::CManualResetEvent _canRead_Event;

   NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;

+

+  // bool _readingWasClosed;

+  bool _readingWasClosed2;

+  // bool WritingWasCut;

   bool _waitWrite;

   UInt32 _bufSize;

   const void *_buf;

@@ -20,13 +36,23 @@
 

   WRes CreateEvents();

   void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream);

+  

   void ReInit();

+  

   HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);

   HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);

-  void CloseRead() { _readingWasClosed_Event.Set(); }

+

+  void CloseRead()

+  {

+    _readingWasClosed_Event.Set();

+    // _readingWasClosed = true;

+    // _canWrite_Event.Set();

+  }

+  

   void CloseWrite()

   {

-    // _bufSize must be = 0

+    _buf = NULL;

+    _bufSize = 0;

     _canRead_Event.Set();

   }

 };

diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
index 6709842..4cd9cc6 100644
--- a/CPP/7zip/Common/StreamObjects.cpp
+++ b/CPP/7zip/Common/StreamObjects.cpp
@@ -8,6 +8,41 @@
 

 #include "StreamObjects.h"

 

+STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (_pos >= Buf.Size())

+    return S_OK;

+  size_t rem = Buf.Size() - (size_t)_pos;

+  if (rem > size)

+    rem = (size_t)size;

+  memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);

+  _pos += rem;

+  if (processedSize)

+    *processedSize = (UInt32)rem;

+  return S_OK;

+}

+

+STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch (seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _pos; break;

+    case STREAM_SEEK_END: offset += Buf.Size(); break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _pos = offset;

+  if (newPosition)

+    *newPosition = offset;

+  return S_OK;

+}

+

 STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

   if (processedSize)

@@ -43,25 +78,22 @@
   return S_OK;

 }

 

-/*

-void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream)

+void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)

 {

+  *stream = NULL;

   CBufInStream *inStreamSpec = new CBufInStream;

   CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;

-  inStreamSpec->Init((const Byte *)data, size);

+  inStreamSpec->Init((const Byte *)data, size, ref);

   *stream = streamTemp.Detach();

 }

-*/

 

-void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream)

+void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)

 {

-  CReferenceBuf *referenceBuf = new CReferenceBuf;

-  CMyComPtr<IUnknown> ref = referenceBuf;

-  referenceBuf->Buf.CopyFrom((const Byte *)data, size);

-

-  CBufInStream *inStreamSpec = new CBufInStream;

+  *stream = NULL;

+  CBufferInStream *inStreamSpec = new CBufferInStream;

   CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;

-  inStreamSpec->Init(referenceBuf);

+  inStreamSpec->Buf.CopyFrom((const Byte *)data, size);

+  inStreamSpec->Init();

   *stream = streamTemp.Detach();

 }

 

@@ -128,8 +160,11 @@
   size_t rem = _size - _pos;

   if (rem > size)

     rem = (size_t)size;

-  memcpy(_buffer + _pos, data, rem);

-  _pos += rem;

+  if (rem != 0)

+  {

+    memcpy(_buffer + _pos, data, rem);

+    _pos += rem;

+  }

   if (processedSize)

     *processedSize = (UInt32)rem;

   return (rem != 0 || size == 0) ? S_OK : E_FAIL;

diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h
index 16c35b8..c3e0837 100644
--- a/CPP/7zip/Common/StreamObjects.h
+++ b/CPP/7zip/Common/StreamObjects.h
@@ -9,6 +9,21 @@
 

 #include "../IStream.h"

 

+class CBufferInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 _pos;

+public:

+  CByteBuffer Buf;

+  void Init() { _pos = 0; }

+ 

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

 struct CReferenceBuf:

   public IUnknown,

   public CMyUnknownImp

@@ -40,8 +55,10 @@
   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

 };

 

-// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream);

-void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream);

+void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream);

+void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream);

+inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream)

+  { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }

 

 class CByteDynBuffer

 {

@@ -53,8 +70,8 @@
   ~CByteDynBuffer() { Free(); }

   void Free() throw();

   size_t GetCapacity() const { return _capacity; }

-  operator Byte*() const { return _buf; };

-  operator const Byte*() const { return _buf; };

+  operator Byte*() const { return _buf; }

+  operator const Byte*() const { return _buf; }

   bool EnsureCapacity(size_t capacity) throw();

 };

 

diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp
index 8808f96..5baf1a4 100644
--- a/CPP/7zip/Common/UniqBlocks.cpp
+++ b/CPP/7zip/Common/UniqBlocks.cpp
@@ -2,15 +2,17 @@
 

 #include "StdAfx.h"

 

+#include <string.h>

+

 #include "UniqBlocks.h"

 

-int CUniqBlocks::AddUniq(const Byte *data, size_t size)

+unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)

 {

   unsigned left = 0, right = Sorted.Size();

   while (left != right)

   {

     unsigned mid = (left + right) / 2;

-    int index = Sorted[mid];

+    unsigned index = Sorted[mid];

     const CByteBuffer &buf = Bufs[index];

     size_t sizeMid = buf.Size();

     if (size < sizeMid)

@@ -19,6 +21,8 @@
       left = mid + 1;

     else

     {

+      if (size == 0)

+        return index;

       int cmp = memcmp(data, buf, size);

       if (cmp == 0)

         return index;

@@ -28,10 +32,9 @@
         left = mid + 1;

     }

   }

-  int index = Bufs.Size();

+  unsigned index = Bufs.Size();

   Sorted.Insert(left, index);

-  CByteBuffer &buf = Bufs.AddNew();

-  buf.CopyFrom(data, size);

+  Bufs.AddNew().CopyFrom(data, size);

   return index;

 }

 

@@ -47,10 +50,8 @@
 {

   unsigned num = Sorted.Size();

   BufIndexToSortedIndex.ClearAndSetSize(num);

-  int *p = &BufIndexToSortedIndex[0];

-  unsigned i;

-  for (i = 0; i < num; i++)

-    p[i] = 0;

-  for (i = 0; i < num; i++)

-    p[Sorted[i]] = i;

+  unsigned *p = &BufIndexToSortedIndex[0];

+  const unsigned *sorted = &Sorted[0];

+  for (unsigned i = 0; i < num; i++)

+    p[sorted[i]] = i;

 }

diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h
index 5b0dfb8..d9ec17d 100644
--- a/CPP/7zip/Common/UniqBlocks.h
+++ b/CPP/7zip/Common/UniqBlocks.h
@@ -10,20 +10,16 @@
 struct CUniqBlocks

 {

   CObjectVector<CByteBuffer> Bufs;

-  CIntVector Sorted;

-  CIntVector BufIndexToSortedIndex;

+  CUIntVector Sorted;

+  CUIntVector BufIndexToSortedIndex;

 

-  int AddUniq(const Byte *data, size_t size);

+  unsigned AddUniq(const Byte *data, size_t size);

   UInt64 GetTotalSizeInBytes() const;

   void GetReverseMap();

 

   bool IsOnlyEmpty() const

   {

-    if (Bufs.Size() == 0)

-      return true;

-    if (Bufs.Size() > 1)

-      return false;

-    return Bufs[0].Size() == 0;

+    return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0);

   }

 };

 

diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
index 636994c..261a626 100644
--- a/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -4,363 +4,655 @@
 

 #include "../../../C/Alloc.h"

 

+#include "../Common/StreamUtils.h"

+

 #include "Bcj2Coder.h"

 

 namespace NCompress {

 namespace NBcj2 {

 

-inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }

-inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }

-inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }

+CBaseCoder::CBaseCoder()

+{

+  for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)

+  {

+    _bufs[i] = NULL;

+    _bufsCurSizes[i] = 0;

+    _bufsNewSizes[i] = (1 << 18);

+  }

+}

+

+CBaseCoder::~CBaseCoder()

+{

+  for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)

+    ::MidFree(_bufs[i]);

+}

+

+HRESULT CBaseCoder::Alloc(bool allocForOrig)

+{

+  unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS;

+  for (unsigned i = 0; i < num; i++)

+  {

+    UInt32 newSize = _bufsNewSizes[i];

+    const UInt32 kMinBufSize = 1;

+    if (newSize < kMinBufSize)

+      newSize = kMinBufSize;

+    if (!_bufs[i] || newSize != _bufsCurSizes[i])

+    {

+      if (_bufs[i])

+      {

+        ::MidFree(_bufs[i]);

+        _bufs[i] = 0;

+      }

+      _bufsCurSizes[i] = 0;

+      Byte *buf = (Byte *)::MidAlloc(newSize);

+      _bufs[i] = buf;

+      if (!buf)

+        return E_OUTOFMEMORY;

+      _bufsCurSizes[i] = newSize;

+    }

+  }

+  return S_OK;

+}

+

+

 

 #ifndef EXTRACT_ONLY

 

-static const unsigned kBufSize = 1 << 17;

+CEncoder::CEncoder(): _relatLim(BCJ2_RELAT_LIMIT) {}

+CEncoder::~CEncoder() {}

 

-#define NUM_BITS 2

-#define SIGN_BIT (1 << NUM_BITS)

-#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1)))

+STDMETHODIMP CEncoder::SetInBufSize(UInt32, UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; }

+STDMETHODIMP CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; }

 

-static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS));

-

-static bool inline Test86MSByte(Byte b)

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

 {

-  return (((b) + SIGN_BIT) & MASK_HIGH) == 0;

+  UInt32 relatLim = BCJ2_RELAT_LIMIT;

+  

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = props[i];

+    PROPID propID = propIDs[i];

+    if (propID >= NCoderPropID::kReduceSize)

+      continue;

+    switch (propID)

+    {

+      /*

+      case NCoderPropID::kDefaultProp:

+      {

+        if (prop.vt != VT_UI4)

+          return E_INVALIDARG;

+        UInt32 v = prop.ulVal;

+        if (v > 31)

+          return E_INVALIDARG;

+        relatLim = (UInt32)1 << v;

+        break;

+      }

+      */

+      case NCoderPropID::kDictionarySize:

+      {

+        if (prop.vt != VT_UI4)

+          return E_INVALIDARG;

+        relatLim = prop.ulVal;

+        if (relatLim > ((UInt32)1 << 31))

+          return E_INVALIDARG;

+        break;

+      }

+

+      case NCoderPropID::kNumThreads:

+        continue;

+      case NCoderPropID::kLevel:

+        continue;

+     

+      default: return E_INVALIDARG;

+    }

+  }

+  

+  _relatLim = relatLim;

+  

+  return S_OK;

 }

 

-CEncoder::~CEncoder()

-{

-  ::MidFree(_buf);

-}

 

-HRESULT CEncoder::Flush()

-{

-  RINOK(_mainStream.Flush());

-  RINOK(_callStream.Flush());

-  RINOK(_jumpStream.Flush());

-  _rc.FlushData();

-  return _rc.FlushStream();

-}

-

-HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,

+HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+    ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams,

     ICompressProgressInfo *progress)

 {

-  if (numInStreams != 1 || numOutStreams != 4)

+  if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS)

     return E_INVALIDARG;

 

-  if (!_mainStream.Create(1 << 18)) return E_OUTOFMEMORY;

-  if (!_callStream.Create(1 << 18)) return E_OUTOFMEMORY;

-  if (!_jumpStream.Create(1 << 18)) return E_OUTOFMEMORY;

-  if (!_rc.Create(1 << 20)) return E_OUTOFMEMORY;

-  if (_buf == 0)

+  RINOK(Alloc());

+

+  UInt32 fileSize_for_Conv = 0;

+  if (inSizes && inSizes[0])

   {

-    _buf = (Byte *)MidAlloc(kBufSize);

-    if (_buf == 0)

-      return E_OUTOFMEMORY;

+    UInt64 inSize = *inSizes[0];

+    if (inSize <= BCJ2_FileSize_MAX)

+      fileSize_for_Conv = (UInt32)inSize;

   }

 

-  bool sizeIsDefined = false;

-  UInt64 inSize = 0;

-  if (inSizes)

-    if (inSizes[0])

-    {

-      inSize = *inSizes[0];

-      if (inSize <= kDefaultLimit)

-        sizeIsDefined = true;

-    }

-

-  ISequentialInStream *inStream = inStreams[0];

-

-  _mainStream.SetStream(outStreams[0]); _mainStream.Init();

-  _callStream.SetStream(outStreams[1]); _callStream.Init();

-  _jumpStream.SetStream(outStreams[2]); _jumpStream.Init();

-  _rc.SetStream(outStreams[3]); _rc.Init();

-  for (unsigned i = 0; i < 256 + 2; i++)

-    _statusEncoder[i].Init();

-

   CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;

+  inStreams[0]->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);

+

+  CBcj2Enc enc;

+    

+  enc.src = _bufs[BCJ2_NUM_STREAMS];

+  enc.srcLim = enc.src;

+    

   {

-    inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);

+    for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+    {

+      enc.bufs[i] = _bufs[i];

+      enc.lims[i] = _bufs[i] + _bufsCurSizes[i];

+    }

   }

 

-  UInt32 nowPos = 0;

-  UInt64 nowPos64 = 0;

-  UInt32 bufPos = 0;

+  size_t numBytes_in_ReadBuf = 0;

+  UInt64 prevProgress = 0;

+  UInt64 totalStreamRead = 0; // size read from InputStream

+  UInt64 currentInPos = 0; // data that was processed, it doesn't include data in input buffer and data in enc.temp

+  UInt64 outSizeRc = 0;

 

-  Byte prevByte = 0;

+  Bcj2Enc_Init(&enc);

 

+  enc.fileIp = 0;

+  enc.fileSize = fileSize_for_Conv;

+

+  enc.relatLimit = _relatLim;

+

+  enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;

+

+  bool needSubSize = false;

   UInt64 subStreamIndex = 0;

   UInt64 subStreamStartPos = 0;

-  UInt64 subStreamEndPos = 0;

+  bool readWasFinished = false;

 

   for (;;)

   {

-    UInt32 processedSize = 0;

-    for (;;)

+    if (needSubSize && getSubStreamSize)

     {

-      UInt32 size = kBufSize - (bufPos + processedSize);

-      UInt32 processedSizeLoc;

-      if (size == 0)

-        break;

-      RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc));

-      if (processedSizeLoc == 0)

-        break;

-      processedSize += processedSizeLoc;

-    }

-    UInt32 endPos = bufPos + processedSize;

-    

-    if (endPos < 5)

-    {

-      // change it

-      for (bufPos = 0; bufPos < endPos; bufPos++)

+      enc.fileIp = 0;

+      enc.fileSize = fileSize_for_Conv;

+      enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;

+      

+      for (;;)

       {

-        Byte b = _buf[bufPos];

-        _mainStream.WriteByte(b);

-        UInt32 index;

-        if (b == 0xE8)

-          index = prevByte;

-        else if (b == 0xE9)

-          index = 256;

-        else if (IsJcc(prevByte, b))

-          index = 257;

-        else

+        UInt64 subStreamSize = 0;

+        HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);

+        needSubSize = false;

+        

+        if (result == S_OK)

         {

-          prevByte = b;

-          continue;

+          UInt64 newEndPos = subStreamStartPos + subStreamSize;

+          

+          bool isAccurateEnd = (newEndPos < totalStreamRead ||

+            (newEndPos <= totalStreamRead && readWasFinished));

+          

+          if (newEndPos <= currentInPos && isAccurateEnd)

+          {

+            subStreamStartPos = newEndPos;

+            subStreamIndex++;

+            continue;

+          }

+          

+          enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;

+          

+          if (isAccurateEnd)

+          {

+            // data in enc.temp is possible here

+            size_t rem = (size_t)(totalStreamRead - newEndPos);

+            

+            /* Pos_of(enc.src) <= old newEndPos <= newEndPos

+               in another case, it's fail in some code */

+            if ((size_t)(enc.srcLim - enc.src) < rem)

+              return E_FAIL;

+            

+            enc.srcLim -= rem;

+            enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK;

+          }

+          

+          if (subStreamSize <= BCJ2_FileSize_MAX)

+          {

+            enc.fileIp = enc.ip + (UInt32)(subStreamStartPos - currentInPos);

+            enc.fileSize = (UInt32)subStreamSize;

+          }

+          break;

         }

-        _statusEncoder[index].Encode(&_rc, 0);

-        prevByte = b;

+        

+        if (result == S_FALSE)

+          break;

+        if (result == E_NOTIMPL)

+        {

+          getSubStreamSize.Release();

+          break;

+        }

+        return result;

       }

-      return Flush();

     }

 

-    bufPos = 0;

+    if (readWasFinished && totalStreamRead - currentInPos == Bcj2Enc_Get_InputData_Size(&enc))

+      enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM;

 

-    UInt32 limit = endPos - 5;

-    while (bufPos <= limit)

+    Bcj2Enc_Encode(&enc);

+

+    currentInPos = totalStreamRead - numBytes_in_ReadBuf + (enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos;

+    

+    if (Bcj2Enc_IsFinished(&enc))

+      break;

+

+    if (enc.state < BCJ2_NUM_STREAMS)

     {

-      Byte b = _buf[bufPos];

-      _mainStream.WriteByte(b);

-      if (!IsJ(prevByte, b))

+      size_t curSize = enc.bufs[enc.state] - _bufs[enc.state];

+      // printf("Write stream = %2d %6d\n", enc.state, curSize);

+      RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize));

+      if (enc.state == BCJ2_STREAM_RC)

+        outSizeRc += curSize;

+

+      enc.bufs[enc.state] = _bufs[enc.state];

+      enc.lims[enc.state] = _bufs[enc.state] + _bufsCurSizes[enc.state];

+    }

+    else if (enc.state != BCJ2_ENC_STATE_ORIG)

+      return E_FAIL;

+    else

+    {

+      needSubSize = true;

+

+      if (numBytes_in_ReadBuf != (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS]))

       {

-        bufPos++;

-        prevByte = b;

+        enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;

         continue;

       }

-      Byte nextByte = _buf[bufPos + 4];

-      UInt32 src =

-        (UInt32(nextByte) << 24) |

-        (UInt32(_buf[bufPos + 3]) << 16) |

-        (UInt32(_buf[bufPos + 2]) << 8) |

-        (_buf[bufPos + 1]);

-      UInt32 dest = (nowPos + bufPos + 5) + src;

-      // if (Test86MSByte(nextByte))

-      bool convert;

-      if (getSubStreamSize)

-      {

-        UInt64 currentPos = (nowPos64 + bufPos);

-        while (subStreamEndPos < currentPos)

-        {

-          UInt64 subStreamSize;

-          HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);

-          if (result == S_OK)

-          {

-            subStreamStartPos = subStreamEndPos;

-            subStreamEndPos += subStreamSize;

-            subStreamIndex++;

-          }

-          else if (result == S_FALSE || result == E_NOTIMPL)

-          {

-            getSubStreamSize.Release();

-            subStreamStartPos = 0;

-            subStreamEndPos = subStreamStartPos - 1;

-          }

-          else

-            return result;

-        }

-        if (getSubStreamSize == NULL)

-        {

-          if (sizeIsDefined)

-            convert = (dest < inSize);

-          else

-            convert = Test86MSByte(nextByte);

-        }

-        else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)

-          convert = Test86MSByte(nextByte);

-        else

-        {

-          UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));

-          convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);

-        }

-      }

-      else if (sizeIsDefined)

-        convert = (dest < inSize);

-      else

-        convert = Test86MSByte(nextByte);

-      unsigned index = GetIndex(prevByte, b);

-      if (convert)

-      {

-        _statusEncoder[index].Encode(&_rc, 1);

-        bufPos += 5;

-        COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;

-        for (int i = 24; i >= 0; i -= 8)

-          s.WriteByte((Byte)(dest >> i));

-        prevByte = nextByte;

-      }

-      else

-      {

-        _statusEncoder[index].Encode(&_rc, 0);

-        bufPos++;

-        prevByte = b;

-      }

-    }

-    nowPos += bufPos;

-    nowPos64 += bufPos;

 

-    if (progress)

-    {

-      /*

-      const UInt64 compressedSize =

-        _mainStream.GetProcessedSize() +

-        _callStream.GetProcessedSize() +

-        _jumpStream.GetProcessedSize() +

-        _rc.GetProcessedSize();

-      */

-      RINOK(progress->SetRatioInfo(&nowPos64, NULL));

-    }

+      if (readWasFinished)

+        continue;

+      

+      numBytes_in_ReadBuf = 0;

+      enc.src    = _bufs[BCJ2_NUM_STREAMS];

+      enc.srcLim = _bufs[BCJ2_NUM_STREAMS];

  

-    UInt32 i = 0;

-    while (bufPos < endPos)

-      _buf[i++] = _buf[bufPos++];

-    bufPos = i;

+      UInt32 curSize = _bufsCurSizes[BCJ2_NUM_STREAMS];

+      RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize));

+

+      // printf("Read %6d bytes\n", curSize);

+      if (curSize == 0)

+      {

+        readWasFinished = true;

+        continue;

+      }

+

+      numBytes_in_ReadBuf = curSize;

+      totalStreamRead += numBytes_in_ReadBuf;

+      enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;

+    }

+

+    if (progress && currentInPos - prevProgress >= (1 << 20))

+    {

+      UInt64 outSize2 = currentInPos + outSizeRc + enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC];

+      prevProgress = currentInPos;

+      // printf("progress %8d, %8d\n", (int)inSize2, (int)outSize2);

+      RINOK(progress->SetRatioInfo(&currentInPos, &outSize2));

+    }

   }

+

+  for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+  {

+    RINOK(WriteStream(outStreams[i], _bufs[i], enc.bufs[i] - _bufs[i]));

+  }

+

+  // if (currentInPos != subStreamStartPos + subStreamSize) return E_FAIL;

+

+  return S_OK;

 }

 

-STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+STDMETHODIMP CEncoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+    ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

     ICompressProgressInfo *progress)

 {

   try

   {

     return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);

   }

-  catch(const COutBufferException &e) { return e.ErrorCode; }

-  catch(...) { return S_FALSE; }

+  catch(...) { return E_FAIL; }

 }

 

 #endif

 

 

-STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; }

-STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }

 

-CDecoder::CDecoder():

-  _outBufSize(1 << 16)

+

+

+

+STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; }

+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; }

+

+CDecoder::CDecoder(): _finishMode(false), _outSizeDefined(false), _outSize(0)

+{}

+

+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)

 {

-  _inBufSizes[0] = 1 << 20;

-  _inBufSizes[1] = 1 << 20;

-  _inBufSizes[2] = 1 << 20;

-  _inBufSizes[3] = 1 << 20;

+  _finishMode = (finishMode != 0);

+  return S_OK;

 }

 

-HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams,

-    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,

+void CDecoder::InitCommon()

+{

+  {

+    for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+      dec.lims[i] = dec.bufs[i] = _bufs[i];

+  }

+

+  {

+    for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+    {

+      _extraReadSizes[i] = 0;

+      _inStreamsProcessed[i] = 0;

+      _readRes[i] = S_OK;

+    }

+  }

+    

+  Bcj2Dec_Init(&dec);

+}

+

+HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+    ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

     ICompressProgressInfo *progress)

 {

-  if (numInStreams != 4 || numOutStreams != 1)

+  if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1)

     return E_INVALIDARG;

 

-  if (!_mainStream.Create(_inBufSizes[0])) return E_OUTOFMEMORY;

-  if (!_callStream.Create(_inBufSizes[1])) return E_OUTOFMEMORY;

-  if (!_jumpStream.Create(_inBufSizes[2])) return E_OUTOFMEMORY;

-  if (!_rc.Create(_inBufSizes[3])) return E_OUTOFMEMORY;

-  if (!_outStream.Create(_outBufSize)) return E_OUTOFMEMORY;

+  RINOK(Alloc());

+    

+  InitCommon();

 

-  _mainStream.SetStream(inStreams[0]);

-  _callStream.SetStream(inStreams[1]);

-  _jumpStream.SetStream(inStreams[2]);

-  _rc.SetStream(inStreams[3]);

-  _outStream.SetStream(outStreams[0]);

+  dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS];

+  

+  UInt64 outSizeProcessed = 0;

+  UInt64 prevProgress = 0;

 

-  _mainStream.Init();

-  _callStream.Init();

-  _jumpStream.Init();

-  _rc.Init();

-  _outStream.Init();

+  HRESULT res = S_OK;

 

-  for (unsigned i = 0; i < 256 + 2; i++)

-    _statusDecoder[i].Init();

-

-  Byte prevByte = 0;

-  UInt32 processedBytes = 0;

   for (;;)

   {

-    if (processedBytes >= (1 << 20) && progress)

+    if (Bcj2Dec_Decode(&dec) != SZ_OK)

+      return S_FALSE;

+    

+    if (dec.state < BCJ2_NUM_STREAMS)

     {

-      /*

-      const UInt64 compressedSize =

-        _mainStream.GetProcessedSize() +

-        _callStream.GetProcessedSize() +

-        _jumpStream.GetProcessedSize() +

-        _rc.GetProcessedSize();

-      */

-      const UInt64 nowPos64 = _outStream.GetProcessedSize();

-      RINOK(progress->SetRatioInfo(NULL, &nowPos64));

-      processedBytes = 0;

-    }

-    UInt32 i;

-    Byte b = 0;

-    const UInt32 kBurstSize = (1 << 18);

-    for (i = 0; i < kBurstSize; i++)

-    {

-      if (!_mainStream.ReadByte(b))

-        return _outStream.Flush();

-      _outStream.WriteByte(b);

-      if (IsJ(prevByte, b))

-        break;

-      prevByte = b;

-    }

-    processedBytes += i;

-    if (i == kBurstSize)

-      continue;

-    unsigned index = GetIndex(prevByte, b);

-    if (_statusDecoder[index].Decode(&_rc) == 1)

-    {

-      UInt32 src = 0;

-      CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;

-      for (unsigned i = 0; i < 4; i++)

+      size_t totalRead = _extraReadSizes[dec.state];

       {

-        Byte b0;

-        if (!s.ReadByte(b0))

-          return S_FALSE;

-        src <<= 8;

-        src |= ((UInt32)b0);

+        Byte *buf = _bufs[dec.state];

+        for (size_t i = 0; i < totalRead; i++)

+          buf[i] = dec.bufs[dec.state][i];

+        dec.lims[dec.state] =

+        dec.bufs[dec.state] = buf;

       }

-      UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;

-      _outStream.WriteByte((Byte)(dest));

-      _outStream.WriteByte((Byte)(dest >> 8));

-      _outStream.WriteByte((Byte)(dest >> 16));

-      _outStream.WriteByte((Byte)(dest >> 24));

-      prevByte = (Byte)(dest >> 24);

-      processedBytes += 4;

+

+      if (_readRes[dec.state] != S_OK)

+      {

+        res = _readRes[dec.state];

+        break;

+      }

+

+      do

+      {

+        UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead;

+        /*

+        we want to call Read even even if size is 0

+        if (inSizes && inSizes[dec.state])

+        {

+          UInt64 rem = *inSizes[dec.state] - _inStreamsProcessed[dec.state];

+          if (curSize > rem)

+            curSize = (UInt32)rem;

+        }

+        */

+

+        HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize);

+        _readRes[dec.state] = res2;

+        if (curSize == 0)

+          break;

+        _inStreamsProcessed[dec.state] += curSize;

+        totalRead += curSize;

+        if (res2 != S_OK)

+          break;

+      }

+      while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state));

+

+      if (_readRes[dec.state] != S_OK)

+        res = _readRes[dec.state];

+

+      if (totalRead == 0)

+        break;

+

+      // res == S_OK;

+

+      if (BCJ2_IS_32BIT_STREAM(dec.state))

+      {

+        unsigned extraSize = ((unsigned)totalRead & 3);

+        _extraReadSizes[dec.state] = extraSize;

+        if (totalRead < 4)

+        {

+          res = (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE;

+          break;

+        }

+        totalRead -= extraSize;

+      }

+

+      dec.lims[dec.state] = _bufs[dec.state] + totalRead;

     }

-    else

-      prevByte = b;

+    else // if (dec.state <= BCJ2_STATE_ORIG)

+    {

+      size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS];

+      if (curSize != 0)

+      {

+        outSizeProcessed += curSize;

+        RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize));

+      }

+      dec.dest = _bufs[BCJ2_NUM_STREAMS];

+      {

+        size_t rem = _bufsCurSizes[BCJ2_NUM_STREAMS];

+        if (outSizes && outSizes[0])

+        {

+          UInt64 outSize = *outSizes[0] - outSizeProcessed;

+          if (rem > outSize)

+            rem = (size_t)outSize;

+        }

+        dec.destLim = dec.dest + rem;

+        if (rem == 0)

+          break;

+      }

+    }

+

+    if (progress)

+    {

+      UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);

+      if (outSize2 - prevProgress >= (1 << 22))

+      {

+        UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);

+        RINOK(progress->SetRatioInfo(&inSize2, &outSize2));

+        prevProgress = outSize2;

+      }

+    }

   }

+

+  size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS];

+  if (curSize != 0)

+  {

+    outSizeProcessed += curSize;

+    RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize));

+  }

+

+  if (res != S_OK)

+    return res;

+

+  if (_finishMode)

+  {

+    if (!Bcj2Dec_IsFinished(&dec))

+      return S_FALSE;

+

+    // we still allow the cases when input streams are larger than required for decoding.

+    // so the case (dec.state == BCJ2_STATE_ORIG) is also allowed, if MAIN stream is larger than required.

+    if (dec.state != BCJ2_STREAM_MAIN &&

+        dec.state != BCJ2_DEC_STATE_ORIG)

+      return S_FALSE;

+

+    if (inSizes)

+    {

+      for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+      {

+        size_t rem = dec.lims[i] - dec.bufs[i] + _extraReadSizes[i];

+        /*

+        if (rem != 0)

+          return S_FALSE;

+        */

+        if (inSizes[i] && *inSizes[i] != _inStreamsProcessed[i] - rem)

+          return S_FALSE;

+      }

+    }

+  }

+

+  return S_OK;

 }

 

-STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

-    ICompressProgressInfo *progress)

+STDMETHODIMP CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)

 {

-  try

+  _inStreams[streamIndex] = inStream;

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::ReleaseInStream2(UInt32 streamIndex)

+{

+  _inStreams[streamIndex].Release();

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)

+{

+  _outSizeDefined = (outSize != NULL);

+  _outSize = 0;

+  if (_outSizeDefined)

+    _outSize = *outSize;

+

+  _outSize_Processed = 0;

+

+  HRESULT res = Alloc(false);

+  

+  InitCommon();

+  dec.destLim = dec.dest = NULL;

+

+  return res;

+}

+

+

+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+

+  if (size == 0)

+    return S_OK;

+

+  UInt32 totalProcessed = 0;

+ 

+  if (_outSizeDefined)

   {

-    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);

+    UInt64 rem = _outSize - _outSize_Processed;

+    if (size > rem)

+      size = (UInt32)rem;

   }

-  catch(const CInBufferException &e) { return e.ErrorCode; }

-  catch(const COutBufferException &e) { return e.ErrorCode; }

-  catch(...) { return S_FALSE; }

+  dec.dest = (Byte *)data;

+  dec.destLim = (const Byte *)data + size;

+

+  HRESULT res = S_OK;

+

+  for (;;)

+  {

+    SRes sres = Bcj2Dec_Decode(&dec);

+    if (sres != SZ_OK)

+      return S_FALSE;

+    

+    {

+      UInt32 curSize = (UInt32)(dec.dest - (Byte *)data);

+      if (curSize != 0)

+      {

+        totalProcessed += curSize;

+        if (processedSize)

+          *processedSize = totalProcessed;

+        data = (void *)((Byte *)data + curSize);

+        size -= curSize;

+        _outSize_Processed += curSize;

+      }

+    }

+

+    if (dec.state >= BCJ2_NUM_STREAMS)

+      break;

+

+    {

+      size_t totalRead = _extraReadSizes[dec.state];

+      {

+        Byte *buf = _bufs[dec.state];

+        for (size_t i = 0; i < totalRead; i++)

+          buf[i] = dec.bufs[dec.state][i];

+        dec.lims[dec.state] =

+        dec.bufs[dec.state] = buf;

+      }

+

+      if (_readRes[dec.state] != S_OK)

+        return _readRes[dec.state];

+

+      do

+      {

+        UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead;

+        HRESULT res2 = _inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize);

+        _readRes[dec.state] = res2;

+        if (curSize == 0)

+          break;

+        _inStreamsProcessed[dec.state] += curSize;

+        totalRead += curSize;

+        if (res2 != S_OK)

+          break;

+      }

+      while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state));

+

+      if (totalRead == 0)

+      {

+        if (totalProcessed == 0)

+          res = _readRes[dec.state];

+        break;

+      }

+

+      if (BCJ2_IS_32BIT_STREAM(dec.state))

+      {

+        unsigned extraSize = ((unsigned)totalRead & 3);

+        _extraReadSizes[dec.state] = extraSize;

+        if (totalRead < 4)

+        {

+          if (totalProcessed != 0)

+            return S_OK;

+          return (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE;

+        }

+        totalRead -= extraSize;

+      }

+

+      dec.lims[dec.state] = _bufs[dec.state] + totalRead;

+    }

+  }

+

+  if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed)

+  {

+    if (!Bcj2Dec_IsFinished(&dec))

+      return S_FALSE;

+

+    if (dec.state != BCJ2_STREAM_MAIN &&

+        dec.state != BCJ2_DEC_STATE_ORIG)

+      return S_FALSE;

+  

+    /*

+    for (int i = 0; i < BCJ2_NUM_STREAMS; i++)

+      if (dec.bufs[i] != dec.lims[i] || _extraReadSizes[i] != 0)

+        return S_FALSE;

+    */

+  }

+

+  return res;

 }

 

 }}

diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
index 4d6994f..ec58dab 100644
--- a/CPP/7zip/Compress/Bcj2Coder.h
+++ b/CPP/7zip/Compress/Bcj2Coder.h
@@ -3,44 +3,57 @@
 #ifndef __COMPRESS_BCJ2_CODER_H

 #define __COMPRESS_BCJ2_CODER_H

 

+#include "../../../C/Bcj2.h"

+

 #include "../../Common/MyCom.h"

 

 #include "../ICoder.h"

 

-#include "RangeCoderBit.h"

-

 namespace NCompress {

 namespace NBcj2 {

 

-const unsigned kNumMoveBits = 5;

+class CBaseCoder

+{

+protected:

+  Byte *_bufs[BCJ2_NUM_STREAMS + 1];

+  UInt32 _bufsCurSizes[BCJ2_NUM_STREAMS + 1];

+  UInt32 _bufsNewSizes[BCJ2_NUM_STREAMS + 1];

+

+  HRESULT Alloc(bool allocForOrig = true);

+public:

+  CBaseCoder();

+  ~CBaseCoder();

+};

+

 

 #ifndef EXTRACT_ONLY

 

 class CEncoder:

   public ICompressCoder2,

-  public CMyUnknownImp

+  public ICompressSetCoderProperties,

+  public ICompressSetBufSize,

+  public CMyUnknownImp,

+  public CBaseCoder

 {

-  Byte *_buf;

+  UInt32 _relatLim;

 

-  COutBuffer _mainStream;

-  COutBuffer _callStream;

-  COutBuffer _jumpStream;

-  NRangeCoder::CEncoder _rc;

-  NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];

-

-  HRESULT Flush();

+  HRESULT CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+      ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

 

 public:

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP3(ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize)

 

-  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+  STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+      ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

       ICompressProgressInfo *progress);

-  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

-      ICompressProgressInfo *progress);

+

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

   

-  CEncoder(): _buf(0) {};

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

+  

+  CEncoder();

   ~CEncoder();

 };

 

@@ -48,28 +61,50 @@
 

 class CDecoder:

   public ICompressCoder2,

+  public ICompressSetFinishMode,

+  public ICompressSetInStream2,

+  public ISequentialInStream,

+  public ICompressSetOutStreamSize,

   public ICompressSetBufSize,

-  public CMyUnknownImp

+  public CMyUnknownImp,

+  public CBaseCoder

 {

-  CInBuffer _mainStream;

-  CInBuffer _callStream;

-  CInBuffer _jumpStream;

-  NRangeCoder::CDecoder _rc;

-  NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];

+  unsigned _extraReadSizes[BCJ2_NUM_STREAMS];

+  UInt64 _inStreamsProcessed[BCJ2_NUM_STREAMS];

+  HRESULT _readRes[BCJ2_NUM_STREAMS];

+  CMyComPtr<ISequentialInStream> _inStreams[BCJ2_NUM_STREAMS];

 

-  COutBuffer _outStream;

-  UInt32 _inBufSizes[4];

-  UInt32 _outBufSize;

+  bool _finishMode;

+  bool _outSizeDefined;

+  UInt64 _outSize;

+  UInt64 _outSize_Processed;

+  CBcj2Dec dec;

 

-public:

-  MY_UNKNOWN_IMP1(ICompressSetBufSize);

+  void InitCommon();

+  // HRESULT ReadSpec();

   

-  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+public:

+  MY_UNKNOWN_IMP6(

+    ICompressCoder2,

+    ICompressSetFinishMode,

+    ICompressSetInStream2,

+    ISequentialInStream,

+    ICompressSetOutStreamSize,

+    ICompressSetBufSize

+    );

+  

+  STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+      ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

       ICompressProgressInfo *progress);

-  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

-      ICompressProgressInfo *progress);

+

+  STDMETHOD(SetFinishMode)(UInt32 finishMode);

+

+  STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream);

+  STDMETHOD(ReleaseInStream2)(UInt32 streamIndex);

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

 

   STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

   STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
index b063f3f..bce6178 100644
--- a/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/CPP/7zip/Compress/Bcj2Register.cpp
@@ -6,14 +6,19 @@
 

 #include "Bcj2Coder.h"

 

-static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); }

+namespace NCompress {

+namespace NBcj2 {

+

+REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2)

 #ifndef EXTRACT_ONLY

-static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder());  }

+REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2)

 #else

-#define CreateCodecOut 0

+#define CreateCodecOut NULL

 #endif

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false };

+REGISTER_CODEC_VAR

+  { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false };

 

 REGISTER_CODEC(BCJ2)

+

+}}

diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
index 108c573..a50360c 100644
--- a/CPP/7zip/Compress/BcjCoder.cpp
+++ b/CPP/7zip/Compress/BcjCoder.cpp
@@ -4,12 +4,21 @@
 

 #include "BcjCoder.h"

 

-UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)

+namespace NCompress {

+namespace NBcj {

+

+STDMETHODIMP CCoder::Init()

 {

-  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1);

+  _bufferPos = 0;

+  x86_Convert_Init(_prevMask);

+  return S_OK;

 }

 

-UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)

+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)

 {

-  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0);

+  UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode);

+  _bufferPos += processed;

+  return processed;

 }

+

+}}

diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
index c86d5fc..475dfe5 100644
--- a/CPP/7zip/Compress/BcjCoder.h
+++ b/CPP/7zip/Compress/BcjCoder.h
@@ -5,15 +5,27 @@
 

 #include "../../../C/Bra.h"

 

-#include "BranchCoder.h"

+#include "../../Common/MyCom.h"

 

-struct CBranch86

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NBcj {

+

+class CCoder:

+  public ICompressFilter,

+  public CMyUnknownImp

 {

+  UInt32 _bufferPos;

   UInt32 _prevMask;

-  void x86Init() { x86_Convert_Init(_prevMask); }

+  int _encode;

+public:

+  MY_UNKNOWN_IMP1(ICompressFilter);

+  INTERFACE_ICompressFilter(;)

+

+  CCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); }

 };

 

-MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,

-    virtual void SubInit() { x86Init(); })

+}}

 

 #endif

diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
index 09e53c6..48cc057 100644
--- a/CPP/7zip/Compress/BcjRegister.cpp
+++ b/CPP/7zip/Compress/BcjRegister.cpp
@@ -6,14 +6,12 @@
 

 #include "BcjCoder.h"

 

-static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); }

-#ifndef EXTRACT_ONLY

-static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder());  }

-#else

-#define CreateCodecOut 0

-#endif

+namespace NCompress {

+namespace NBcj {

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true };

+REGISTER_FILTER_E(BCJ,

+    CCoder(false),

+    CCoder(true),

+    0x3030103, "BCJ")

 

-REGISTER_CODEC(BCJ)

+}}

diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp
deleted file mode 100644
index 6cacc66..0000000
--- a/CPP/7zip/Compress/BranchCoder.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// BranchCoder.cpp

-

-#include "StdAfx.h"

-

-#include "BranchCoder.h"

-

-STDMETHODIMP CBranchConverter::Init()

-{

-  _bufferPos = 0;

-  SubInit();

-  return S_OK;

-}

-

-STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)

-{

-  UInt32 processedSize = SubFilter(data, size);

-  _bufferPos += processedSize;

-  return processedSize;

-}

diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
deleted file mode 100644
index 473286a..0000000
--- a/CPP/7zip/Compress/BranchCoder.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// BranchCoder.h

-

-#ifndef __COMPRESS_BRANCH_CODER_H

-#define __COMPRESS_BRANCH_CODER_H

-

-#include "../../Common/MyCom.h"

-

-#include "../ICoder.h"

-

-class CBranchConverter:

-  public ICompressFilter,

-  public CMyUnknownImp

-{

-protected:

-  UInt32 _bufferPos;

-  virtual void SubInit() {}

-  virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;

-public:

-  MY_UNKNOWN_IMP;

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

-};

-

-#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \

-  { public: UInt32 SubFilter(Byte *data, UInt32 size); };

-

-#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \

-  { public: UInt32 SubFilter(Byte *data, UInt32 size); };

-

-#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \

-  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};

-

-#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \

-  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};

-

-#define MyClassA(Name, id, subId)  \

-MyClassEncoderA(Name ## _Encoder) \

-MyClassDecoderA(Name ## _Decoder)

-

-#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT)  \

-MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \

-MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)

-

-#endif

diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
index 1ac7949..d5a90f1 100644
--- a/CPP/7zip/Compress/BranchMisc.cpp
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -2,20 +2,22 @@
 

 #include "StdAfx.h"

 

-#include "../../../C/Bra.h"

-

 #include "BranchMisc.h"

 

-#define SUB_FILTER_IMP2(name, coderStr, coderNum) \

-  UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \

-  { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); }

+namespace NCompress {

+namespace NBranch {

 

-#define SUB_FILTER_IMP(name) \

-  SUB_FILTER_IMP2(name, Encoder, 1) \

-  SUB_FILTER_IMP2(name, Decoder, 0) \

+STDMETHODIMP CCoder::Init()

+{

+  _bufferPos = 0;

+  return S_OK;

+}

 

-SUB_FILTER_IMP(ARM_)

-SUB_FILTER_IMP(ARMT_)

-SUB_FILTER_IMP(PPC_)

-SUB_FILTER_IMP(SPARC_)

-SUB_FILTER_IMP(IA64_)

+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)

+{

+  UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode);

+  _bufferPos += processed;

+  return processed;

+}

+

+}}

diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
index 053e923..02a56c3 100644
--- a/CPP/7zip/Compress/BranchMisc.h
+++ b/CPP/7zip/Compress/BranchMisc.h
@@ -3,12 +3,33 @@
 #ifndef __COMPRESS_BRANCH_MISC_H

 #define __COMPRESS_BRANCH_MISC_H

 

-#include "BranchCoder.h"

+#include "../../Common/MyCom.h"

 

-MyClassA(BC_ARM,   0x05, 1)

-MyClassA(BC_ARMT,  0x07, 1)

-MyClassA(BC_PPC,   0x02, 5)

-MyClassA(BC_SPARC, 0x08, 5)

-MyClassA(BC_IA64,  0x04, 1)

+#include "../ICoder.h"

+

+EXTERN_C_BEGIN

+

+typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding);

+

+EXTERN_C_END

+

+namespace NCompress {

+namespace NBranch {

+

+class CCoder:

+  public ICompressFilter,

+  public CMyUnknownImp

+{

+  UInt32 _bufferPos;

+  int _encode;

+  Func_Bra BraFunc;

+public:

+  MY_UNKNOWN_IMP1(ICompressFilter);

+  INTERFACE_ICompressFilter(;)

+

+  CCoder(Func_Bra bra, int encode):  _bufferPos(0), _encode(encode), BraFunc(bra) {}

+};

+

+}}

 

 #endif

diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
index bc55dd6..b83c6bc 100644
--- a/CPP/7zip/Compress/BranchRegister.cpp
+++ b/CPP/7zip/Compress/BranchRegister.cpp
@@ -2,29 +2,40 @@
 

 #include "StdAfx.h"

 

+#include "../../../C/Bra.h"

+

 #include "../Common/RegisterCodec.h"

 

 #include "BranchMisc.h"

 

-#define CREATE_CODEC(x) \

-  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \

-  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); }

+namespace NCompress {

+namespace NBranch {

 

-CREATE_CODEC(BC_PPC)

-CREATE_CODEC(BC_IA64)

-CREATE_CODEC(BC_ARM)

-CREATE_CODEC(BC_ARMT)

-CREATE_CODEC(BC_SPARC)

+#define CREATE_BRA(n) \

+    REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(n ## _Convert, false)) \

+    REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(n ## _Convert, true)) \

 

-#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true  }

+CREATE_BRA(PPC)

+CREATE_BRA(IA64)

+CREATE_BRA(ARM)

+CREATE_BRA(ARMT)

+CREATE_BRA(SPARC)

 

-static CCodecInfo g_CodecsInfo[] =

+#define METHOD_ITEM(n, id, name) \

+    REGISTER_FILTER_ITEM( \

+      CreateBra_Decoder_ ## n, \

+      CreateBra_Encoder_ ## n, \

+      0x3030000 + id, name)

+

+REGISTER_CODECS_VAR

 {

-  METHOD_ITEM(BC_PPC,   0x02, 0x05, L"PPC"),

-  METHOD_ITEM(BC_IA64,  0x04, 1, L"IA64"),

-  METHOD_ITEM(BC_ARM,   0x05, 1, L"ARM"),

-  METHOD_ITEM(BC_ARMT,  0x07, 1, L"ARMT"),

-  METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC")

+  METHOD_ITEM(PPC,   0x205, "PPC"),

+  METHOD_ITEM(IA64,  0x401, "IA64"),

+  METHOD_ITEM(ARM,   0x501, "ARM"),

+  METHOD_ITEM(ARMT,  0x701, "ARMT"),

+  METHOD_ITEM(SPARC, 0x805, "SPARC")

 };

 

 REGISTER_CODECS(Branch)

+

+}}

diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
index 7f028fb..ee103af 100644
--- a/CPP/7zip/Compress/ByteSwap.cpp
+++ b/CPP/7zip/Compress/ByteSwap.cpp
@@ -8,14 +8,16 @@
 

 #include "../Common/RegisterCodec.h"

 

+namespace NCompress {

+namespace NByteSwap {

+

 class CByteSwap2:

   public ICompressFilter,

   public CMyUnknownImp

 {

 public:

-  MY_UNKNOWN_IMP

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  MY_UNKNOWN_IMP1(ICompressFilter);

+  INTERFACE_ICompressFilter(;)

 };

 

 class CByteSwap4:

@@ -23,9 +25,8 @@
   public CMyUnknownImp

 {

 public:

-  MY_UNKNOWN_IMP

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  MY_UNKNOWN_IMP1(ICompressFilter);

+  INTERFACE_ICompressFilter(;)

 };

 

 STDMETHODIMP CByteSwap2::Init() { return S_OK; }

@@ -33,14 +34,22 @@
 STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)

 {

   const UInt32 kStep = 2;

-  UInt32 i;

-  for (i = 0; i + kStep <= size; i += kStep)

+  if (size < kStep)

+    return 0;

+  size &= ~(kStep - 1);

+  

+  const Byte *end = data + (size_t)size;

+  

+  do

   {

-    Byte b = data[i];

-    data[i] = data[i + 1];

-    data[i + 1] = b;

+    Byte b0 = data[0];

+    data[0] = data[1];

+    data[1] = b0;

+    data += kStep;

   }

-  return i;

+  while (data != end);

+

+  return size;

 }

 

 STDMETHODIMP CByteSwap4::Init() { return S_OK; }

@@ -48,26 +57,36 @@
 STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)

 {

   const UInt32 kStep = 4;

-  UInt32 i;

-  for (i = 0; i + kStep <= size; i += kStep)

+  if (size < kStep)

+    return 0;

+  size &= ~(kStep - 1);

+  

+  const Byte *end = data + (size_t)size;

+  

+  do

   {

-    Byte b0 = data[i];

-    Byte b1 = data[i + 1];

-    data[i] = data[i + 3];

-    data[i + 1] = data[i + 2];

-    data[i + 2] = b1;

-    data[i + 3] = b0;

+    Byte b0 = data[0];

+    Byte b1 = data[1];

+    data[0] = data[3];

+    data[1] = data[2];

+    data[2] = b1;

+    data[3] = b0;

+    data += kStep;

   }

-  return i;

+  while (data != end);

+

+  return size;

 }

 

-static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); }

-static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); }

+REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2())

+REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4())

 

-static CCodecInfo g_CodecsInfo[] =

+REGISTER_CODECS_VAR

 {

-  { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true },

-  { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true }

+  REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"),

+  REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4")

 };

 

 REGISTER_CODECS(ByteSwap)

+

+}}

diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
index 8691d5d..7be496c 100644
--- a/CPP/7zip/Compress/CodecExports.cpp
+++ b/CPP/7zip/Compress/CodecExports.cpp
@@ -7,118 +7,163 @@
 #include "../../Common/ComTry.h"

 #include "../../Common/MyCom.h"

 

-#include "../../Windows/PropVariant.h"

+#include "../../Windows/Defs.h"

 

 #include "../ICoder.h"

 

 #include "../Common/RegisterCodec.h"

 

-extern unsigned int g_NumCodecs;

+extern unsigned g_NumCodecs;

 extern const CCodecInfo *g_Codecs[];

 

-extern unsigned int g_NumHashers;

+extern unsigned g_NumHashers;

 extern const CHasherInfo *g_Hashers[];

 

-static const UInt16 kDecodeId = 0x2790;

-static const UInt16 kEncodeId = 0x2791;

-static const UInt16 kHasherId = 0x2792;

-

-DEFINE_GUID(CLSID_CCodec,

-0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);

-

-static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)

+static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()

 {

-  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)

+  UINT len = (UINT)strlen(s);

+  BSTR dest = ::SysAllocStringLen(NULL, len);

+  if (dest)

+  {

+    for (UINT i = 0; i <= len; i++)

+      dest[i] = (Byte)s[i];

+    prop->bstrVal = dest;

+    prop->vt = VT_BSTR;

+  }

+}

+

+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw()

+{

+  if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)

     value->vt = VT_BSTR;

   return S_OK;

 }

 

-static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)

-{

-  return SetPropString((const char *)&guid, sizeof(GUID), value);

-}

-

-static HRESULT SetClassID(CMethodId id, UInt16 typeId, PROPVARIANT *value)

+static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()

 {

   GUID clsId;

-  clsId.Data1 = CLSID_CCodec.Data1;

-  clsId.Data2 = CLSID_CCodec.Data2;

+  clsId.Data1 = k_7zip_GUID_Data1;

+  clsId.Data2 = k_7zip_GUID_Data2;

   clsId.Data3 = typeId;

   SetUi64(clsId.Data4, id);

   return SetPropGUID(clsId, value);

 }

 

-static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)

+static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw()

 {

   index = -1;

-  if (clsID->Data1 != CLSID_CCodec.Data1 ||

-      clsID->Data2 != CLSID_CCodec.Data2)

+  if (clsid->Data1 != k_7zip_GUID_Data1 ||

+      clsid->Data2 != k_7zip_GUID_Data2)

     return S_OK;

+  

   encode = true;

-  if (clsID->Data3 == kDecodeId)

-    encode = false;

-  else if (clsID->Data3 != kEncodeId)

-    return S_OK;

-  UInt64 id = GetUi64(clsID->Data4);

+  

+       if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false;

+  else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK;

+  

+  UInt64 id = GetUi64(clsid->Data4);

+  

   for (unsigned i = 0; i < g_NumCodecs; i++)

   {

     const CCodecInfo &codec = *g_Codecs[i];

-    if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)

+    

+    if (id != codec.Id

+        || (encode ? !codec.CreateEncoder : !codec.CreateDecoder)

+        || (isFilter ? !codec.IsFilter : codec.IsFilter))

       continue;

-    if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||

-        codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)

+

+    if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)

       return E_NOINTERFACE;

+    

     index = i;

     return S_OK;

   }

+  

   return S_OK;

 }

 

-STDAPI CreateCoder2(bool encode, int index, const GUID *iid, void **outObject)

+static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)

 {

   COM_TRY_BEGIN

-  *outObject = 0;

-  bool isCoder = (*iid == IID_ICompressCoder) != 0;

-  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;

-  bool isFilter = (*iid == IID_ICompressFilter) != 0;

+  

   const CCodecInfo &codec = *g_Codecs[index];

-  if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||

-      codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)

-    return E_NOINTERFACE;

+  

+  void *c;

   if (encode)

+    c = codec.CreateEncoder();

+  else

+    c = codec.CreateDecoder();

+  

+  if (c)

   {

-    if (!codec.CreateEncoder)

-      return CLASS_E_CLASSNOTAVAILABLE;

-    *outObject = codec.CreateEncoder();

+    IUnknown *unk;

+    if (codec.IsFilter)

+      unk = (IUnknown *)(ICompressFilter *)c;

+    else if (codec.NumStreams != 1)

+      unk = (IUnknown *)(ICompressCoder2 *)c;

+    else

+      unk = (IUnknown *)(ICompressCoder *)c;

+    unk->AddRef();

+    *coder = c;

+  }

+  return S_OK;

+  

+  COM_TRY_END

+}

+

+static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)

+{

+  *outObject = NULL;

+

+  const CCodecInfo &codec = *g_Codecs[index];

+

+  if (encode ? !codec.CreateEncoder : !codec.CreateDecoder)

+    return CLASS_E_CLASSNOTAVAILABLE;

+

+  if (codec.IsFilter)

+  {

+    if (*iid != IID_ICompressFilter) return E_NOINTERFACE;

+  }

+  else if (codec.NumStreams != 1)

+  {

+    if (*iid != IID_ICompressCoder2) return E_NOINTERFACE;

   }

   else

   {

-    if (!codec.CreateDecoder)

-      return CLASS_E_CLASSNOTAVAILABLE;

-    *outObject = codec.CreateDecoder();

+    if (*iid != IID_ICompressCoder) return E_NOINTERFACE;

   }

-  if (*outObject)

-  {

-    if (isCoder)

-      ((ICompressCoder *)*outObject)->AddRef();

-    else if (isCoder2)

-      ((ICompressCoder2 *)*outObject)->AddRef();

-    else

-      ((ICompressFilter *)*outObject)->AddRef();

-  }

-  return S_OK;

-  COM_TRY_END

+  

+  return CreateCoderMain(index, encode, outObject);

+}

+

+STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject)

+{

+  return CreateCoder2(false, index, iid, outObject);

+}

+

+STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject)

+{

+  return CreateCoder2(true, index, iid, outObject);

 }

 

 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)

 {

-  COM_TRY_BEGIN

-  *outObject = 0;

+  *outObject = NULL;

+

+  bool isFilter = false;

+  bool isCoder2 = false;

   bool isCoder = (*iid == IID_ICompressCoder) != 0;

-  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;

-  bool isFilter = (*iid == IID_ICompressFilter) != 0;

-  if (!isCoder && !isCoder2 && !isFilter)

-    return E_NOINTERFACE;

+  if (!isCoder)

+  {

+    isFilter = (*iid == IID_ICompressFilter) != 0;

+    if (!isFilter)

+    {

+      isCoder2 = (*iid == IID_ICompressCoder2) != 0;

+      if (!isCoder2)

+        return E_NOINTERFACE;

+    }

+  }

+  

   bool encode;

   int codecIndex;

   HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);

@@ -127,24 +172,9 @@
   if (codecIndex < 0)

     return CLASS_E_CLASSNOTAVAILABLE;

 

-  const CCodecInfo &codec = *g_Codecs[codecIndex];

-  if (encode)

-    *outObject = codec.CreateEncoder();

-  else

-    *outObject = codec.CreateDecoder();

-  if (*outObject)

-  {

-    if (isCoder)

-      ((ICompressCoder *)*outObject)->AddRef();

-    else if (isCoder2)

-      ((ICompressCoder2 *)*outObject)->AddRef();

-    else

-      ((ICompressFilter *)*outObject)->AddRef();

-  }

-  return S_OK;

-  COM_TRY_END

+  return CreateCoderMain(codecIndex, encode, outObject);

 }

-

+ 

 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)

 {

   ::VariantClear((VARIANTARG *)value);

@@ -156,24 +186,54 @@
       value->vt = VT_UI8;

       break;

     case NMethodPropID::kName:

-      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)

-        value->vt = VT_BSTR;

+      SetPropFromAscii(codec.Name, value);

       break;

     case NMethodPropID::kDecoder:

       if (codec.CreateDecoder)

-        return SetClassID(codec.Id, kDecodeId, value);

+        return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);

       break;

     case NMethodPropID::kEncoder:

       if (codec.CreateEncoder)

-        return SetClassID(codec.Id, kEncodeId, value);

+        return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value);

       break;

-    case NMethodPropID::kInStreams:

-      if (codec.NumInStreams != 1)

+    case NMethodPropID::kDecoderIsAssigned:

+        value->vt = VT_BOOL;

+        value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL);

+      break;

+    case NMethodPropID::kEncoderIsAssigned:

+        value->vt = VT_BOOL;

+        value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL);

+      break;

+    case NMethodPropID::kPackStreams:

+      if (codec.NumStreams != 1)

       {

         value->vt = VT_UI4;

-        value->ulVal = (ULONG)codec.NumInStreams;

+        value->ulVal = (ULONG)codec.NumStreams;

       }

       break;

+    /*

+    case NMethodPropID::kIsFilter:

+      // if (codec.IsFilter)

+      {

+        value->vt = VT_BOOL;

+        value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);

+      }

+      break;

+    */

+    /*

+    case NMethodPropID::kDecoderFlags:

+      {

+        value->vt = VT_UI4;

+        value->ulVal = (ULONG)codec.DecoderFlags;

+      }

+      break;

+    case NMethodPropID::kEncoderFlags:

+      {

+        value->vt = VT_UI4;

+        value->ulVal = (ULONG)codec.EncoderFlags;

+      }

+      break;

+    */

   }

   return S_OK;

 }

@@ -185,13 +245,15 @@
 }

 

 

-static int FindHasherClassId(const GUID *clsID)

+// ---------- Hashers ----------

+

+static int FindHasherClassId(const GUID *clsid) throw()

 {

-  if (clsID->Data1 != CLSID_CCodec.Data1 ||

-      clsID->Data2 != CLSID_CCodec.Data2 ||

-      clsID->Data3 != kHasherId)

+  if (clsid->Data1 != k_7zip_GUID_Data1 ||

+      clsid->Data2 != k_7zip_GUID_Data2 ||

+      clsid->Data3 != k_7zip_GUID_Data3_Hasher)

     return -1;

-  UInt64 id = GetUi64(clsID->Data4);

+  UInt64 id = GetUi64(clsid->Data4);

   for (unsigned i = 0; i < g_NumCodecs; i++)

     if (id == g_Hashers[i]->Id)

       return i;

@@ -230,12 +292,11 @@
       value->vt = VT_UI8;

       break;

     case NMethodPropID::kName:

-      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)

-        value->vt = VT_BSTR;

+      SetPropFromAscii(codec.Name, value);

       break;

     case NMethodPropID::kEncoder:

       if (codec.CreateHasher)

-        return SetClassID(codec.Id, kHasherId, value);

+        return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);

       break;

     case NMethodPropID::kDigestSize:

       value->ulVal = (ULONG)codec.DigestSize;

diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
index 66ab85e..925493f 100644
--- a/CPP/7zip/Compress/CopyCoder.cpp
+++ b/CPP/7zip/Compress/CopyCoder.cpp
@@ -4,17 +4,15 @@
 

 #include "../../../C/Alloc.h"

 

-#include "../Common/StreamUtils.h"

-

 #include "CopyCoder.h"

 

 namespace NCompress {

 

-static const UInt32 kBufferSize = 1 << 17;

+static const UInt32 kBufSize = 1 << 17;

 

 CCopyCoder::~CCopyCoder()

 {

-  ::MidFree(_buffer);

+  ::MidFree(_buf);

 }

 

 STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,

@@ -22,35 +20,78 @@
     const UInt64 * /* inSize */, const UInt64 *outSize,

     ICompressProgressInfo *progress)

 {

-  if (!_buffer)

+  if (!_buf)

   {

-    _buffer = (Byte *)::MidAlloc(kBufferSize);

-    if (!_buffer)

+    _buf = (Byte *)::MidAlloc(kBufSize);

+    if (!_buf)

       return E_OUTOFMEMORY;

   }

 

   TotalSize = 0;

+  

   for (;;)

   {

-    UInt32 size = kBufferSize;

+    UInt32 size = kBufSize;

     if (outSize && size > *outSize - TotalSize)

       size = (UInt32)(*outSize - TotalSize);

-    RINOK(inStream->Read(_buffer, size, &size));

     if (size == 0)

-      break;

+      return S_OK;

+    

+    HRESULT readRes = inStream->Read(_buf, size, &size);

+

+    if (size == 0)

+      return readRes;

+

     if (outStream)

     {

-      RINOK(WriteStream(outStream, _buffer, size));

+      UInt32 pos = 0;

+      do

+      {

+        UInt32 curSize = size - pos;

+        HRESULT res = outStream->Write(_buf + pos, curSize, &curSize);

+        pos += curSize;

+        TotalSize += curSize;

+        RINOK(res);

+        if (curSize == 0)

+          return E_FAIL;

+      }

+      while (pos < size);

     }

-    TotalSize += size;

+    else

+      TotalSize += size;

+

+    RINOK(readRes);

+

     if (progress)

     {

       RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));

     }

   }

+}

+

+STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream)

+{

+  _inStream = inStream;

+  TotalSize = 0;

   return S_OK;

 }

 

+STDMETHODIMP CCopyCoder::ReleaseInStream()

+{

+  _inStream.Release();

+  return S_OK;

+}

+

+STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize = 0;

+  HRESULT res = _inStream->Read(data, size, &realProcessedSize);

+  TotalSize += realProcessedSize;

+  if (processedSize)

+    *processedSize = realProcessedSize;

+  return res;

+}

+

 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)

 {

   *value = TotalSize;

diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
index 254266a..f2620f1 100644
--- a/CPP/7zip/Compress/CopyCoder.h
+++ b/CPP/7zip/Compress/CopyCoder.h
@@ -11,19 +11,30 @@
 

 class CCopyCoder:

   public ICompressCoder,

+  public ICompressSetInStream,

+  public ISequentialInStream,

   public ICompressGetInStreamProcessedSize,

   public CMyUnknownImp

 {

-  Byte *_buffer;

+  Byte *_buf;

+  CMyComPtr<ISequentialInStream> _inStream;

 public:

   UInt64 TotalSize;

-  CCopyCoder(): TotalSize(0), _buffer(0) {};

+  

+  CCopyCoder(): _buf(0), TotalSize(0) {};

   ~CCopyCoder();

 

-  MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)

+  MY_UNKNOWN_IMP4(

+      ICompressCoder,

+      ICompressSetInStream,

+      ISequentialInStream,

+      ICompressGetInStreamProcessedSize)

 

   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);

 };

 

diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
index 3ef2459..1c59fe0 100644
--- a/CPP/7zip/Compress/CopyRegister.cpp
+++ b/CPP/7zip/Compress/CopyRegister.cpp
@@ -6,9 +6,10 @@
 

 #include "CopyCoder.h"

 

-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); }

+namespace NCompress {

 

-static CCodecInfo g_CodecInfo =

-{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false };

+REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder())

 

-REGISTER_CODEC(Copy)

+REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy")

+

+}

diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
index a7f70fe..cdbd33d 100644
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -4,19 +4,28 @@
 

 #include "../../../C/Delta.h"

 

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

 #include "../Common/RegisterCodec.h"

 

-#include "BranchCoder.h"

+namespace NCompress {

+namespace NDelta {

 

 struct CDelta

 {

   unsigned _delta;

   Byte _state[DELTA_STATE_SIZE];

+

   CDelta(): _delta(1) {}

   void DeltaInit() { Delta_Init(_state); }

 };

 

-class CDeltaEncoder:

+

+#ifndef EXTRACT_ONLY

+

+class CEncoder:

   public ICompressFilter,

   public ICompressSetCoderProperties,

   public ICompressWriteCoderProperties,

@@ -24,39 +33,25 @@
   public CMyUnknownImp

 {

 public:

-  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  MY_UNKNOWN_IMP3(ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties)

+  INTERFACE_ICompressFilter(;)

   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

   STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

 };

 

-class CDeltaDecoder:

-  public ICompressFilter,

-  public ICompressSetDecoderProperties2,

-  CDelta,

-  public CMyUnknownImp

-{

-public:

-  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

-  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

-};

-

-STDMETHODIMP CDeltaEncoder::Init()

+STDMETHODIMP CEncoder::Init()

 {

   DeltaInit();

   return S_OK;

 }

 

-STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size)

+STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)

 {

   Delta_Encode(_state, _delta, data, size);

   return size;

 }

 

-STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

 {

   UInt32 delta = _delta;

   for (UInt32 i = 0; i < numProps; i++)

@@ -83,25 +78,40 @@
   return S_OK;

 }

 

-STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

 {

   Byte prop = (Byte)(_delta - 1);

   return outStream->Write(&prop, 1, NULL);

 }

 

-STDMETHODIMP CDeltaDecoder::Init()

+#endif

+

+

+class CDecoder:

+  public ICompressFilter,

+  public ICompressSetDecoderProperties2,

+  CDelta,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP2(ICompressFilter, ICompressSetDecoderProperties2)

+  INTERFACE_ICompressFilter(;)

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+};

+

+STDMETHODIMP CDecoder::Init()

 {

   DeltaInit();

   return S_OK;

 }

 

-STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size)

+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)

 {

   Delta_Decode(_state, _delta, data, size);

   return size;

 }

 

-STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)

+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)

 {

   if (size != 1)

     return E_INVALIDARG;

@@ -109,17 +119,10 @@
   return S_OK;

 }

 

-#define CREATE_CODEC(x) \

-  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \

-  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); }

 

-CREATE_CODEC(Delta)

+REGISTER_FILTER_E(Delta,

+    CDecoder(),

+    CEncoder(),

+    3, "Delta")

 

-#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true  }

-

-static CCodecInfo g_CodecsInfo[] =

-{

-  METHOD_ITEM(Delta, 3, L"Delta")

-};

-

-REGISTER_CODECS(Delta)

+}}

diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
index 8d3d830..8b4afe2 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -10,7 +10,7 @@
 

 static HRESULT SResToHRESULT(SRes res)

 {

-  switch(res)

+  switch (res)

   {

     case SZ_OK: return S_OK;

     case SZ_ERROR_MEM: return E_OUTOFMEMORY;

@@ -24,32 +24,40 @@
 namespace NCompress {

 namespace NLzma2 {

 

-static const UInt32 kInBufSize = 1 << 20;

-

-CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false)

+CDecoder::CDecoder():

+    _inBuf(NULL),

+    _inBufSize(0),

+    _inBufSizeNew(1 << 20),

+    _outStepSize(1 << 22),

+    _outSizeDefined(false),

+    _finishMode(false)

 {

   Lzma2Dec_Construct(&_state);

 }

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }

+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStepSize = size; return S_OK; }

 

 CDecoder::~CDecoder()

 {

   Lzma2Dec_Free(&_state, &g_Alloc);

-  MyFree(_inBuf);

+  MidFree(_inBuf);

 }

 

 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)

 {

-  if (size != 1) return SZ_ERROR_UNSUPPORTED;

+  if (size != 1)

+    return E_NOTIMPL;

+  

   RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));

-  if (_inBuf == 0)

+  if (!_inBuf || _inBufSize != _inBufSizeNew)

   {

-    _inBuf = (Byte *)MyAlloc(kInBufSize);

-    if (_inBuf == 0)

+    MidFree(_inBuf);

+    _inBufSize = 0;

+    _inBuf = (Byte *)MidAlloc(_inBufSizeNew);

+    if (!_inBuf)

       return E_OUTOFMEMORY;

+    _inBufSize = _inBufSizeNew;

   }

 

   return S_OK;

@@ -62,6 +70,7 @@
 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)

 {

   _outSizeDefined = (outSize != NULL);

+  _outSize = 0;

   if (_outSizeDefined)

     _outSize = *outSize;

 

@@ -72,39 +81,55 @@
   return S_OK;

 }

 

+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)

+{

+  _finishMode = (finishMode != 0);

+  return S_OK;

+}

+

 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,

-    ISequentialOutStream *outStream, const UInt64 * /* inSize */,

+    ISequentialOutStream *outStream, const UInt64 *inSize,

     const UInt64 *outSize, ICompressProgressInfo *progress)

 {

-  if (_inBuf == 0)

+  if (!_inBuf)

     return S_FALSE;

   SetOutStreamSize(outSize);

 

+  UInt32 step = _outStepSize;

+  const UInt32 kOutStepSize_Min = 1 << 12;

+  if (step < kOutStepSize_Min)

+    step = kOutStepSize_Min;

+  

+  SizeT wrPos = _state.decoder.dicPos;

+

+  SizeT next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?

+      _state.decoder.dicBufSize :

+      _state.decoder.dicPos + step;

+

+  HRESULT hres = S_OK;

+

   for (;;)

   {

     if (_inPos == _inSize)

     {

       _inPos = _inSize = 0;

-      RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));

+      hres = inStream->Read(_inBuf, _inBufSize, &_inSize);

+      if (hres != S_OK)

+        break;

     }

 

     SizeT dicPos = _state.decoder.dicPos;

-    SizeT curSize = _state.decoder.dicBufSize - dicPos;

-    const UInt32 kStepSize = ((UInt32)1 << 22);

-    if (curSize > kStepSize)

-      curSize = (SizeT)kStepSize;

-    

+    SizeT curSize = next - dicPos;

+   

     ELzmaFinishMode finishMode = LZMA_FINISH_ANY;

     if (_outSizeDefined)

     {

       const UInt64 rem = _outSize - _outSizeProcessed;

-      if (rem < curSize)

+      if (curSize >= rem)

       {

         curSize = (SizeT)rem;

-        /*

-        // finishMode = LZMA_FINISH_END;

-        we can't use LZMA_FINISH_END here to allow partial decoding

-        */

+        if (_finishMode)

+          finishMode = LZMA_FINISH_END;

       }

     }

 

@@ -117,71 +142,123 @@
     SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;

     _outSizeProcessed += outSizeProcessed;

 

-    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);

-    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);

+    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0

+        || status == LZMA_STATUS_FINISHED_WITH_MARK);

+    bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize);

 

-    if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding)

+    if (res != 0

+        || _state.decoder.dicPos >= next

+        || finished

+        || outFinished)

     {

-      HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos);

+      HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);

+

+      if (_state.decoder.dicPos == _state.decoder.dicBufSize)

+        _state.decoder.dicPos = 0;

+      

+      wrPos = _state.decoder.dicPos;

+

+      next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?

+          _state.decoder.dicBufSize :

+          _state.decoder.dicPos + step;

+

       if (res != 0)

         return S_FALSE;

       RINOK(res2);

-      if (stopDecoding)

-        return S_OK;

-      if (finished)

-        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);

-    }

-    if (_state.decoder.dicPos == _state.decoder.dicBufSize)

-      _state.decoder.dicPos = 0;

 

-    if (progress != NULL)

+      if (finished)

+      {

+        if (status == LZMA_STATUS_FINISHED_WITH_MARK)

+        {

+          if (_finishMode && inSize && *inSize != _inSizeProcessed)

+            return S_FALSE;

+          if (finishMode == LZMA_FINISH_END && !outFinished)

+            return S_FALSE;

+          return S_OK;

+        }

+        return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK;

+      }

+

+      if (outFinished && finishMode == LZMA_FINISH_ANY)

+        return S_OK;

+    }

+    

+    if (progress)

     {

       RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));

     }

   }

+

+  HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);

+  if (hres != S_OK)

+    return hres;

+  return res2;

 }

 

 #ifndef NO_READ_FROM_CODER

 

 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

+  UInt32 totalProcessed = 0;

+

   if (processedSize)

     *processedSize = 0;

-  do

+

+  for (;;)

   {

     if (_inPos == _inSize)

     {

       _inPos = _inSize = 0;

-      RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));

+      RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize));

     }

     {

-      SizeT inProcessed = _inSize - _inPos;

-

+      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;

       if (_outSizeDefined)

       {

         const UInt64 rem = _outSize - _outSizeProcessed;

-        if (rem < size)

+        if (rem <= size)

+        {

           size = (UInt32)rem;

+          if (_finishMode)

+            finishMode = LZMA_FINISH_END;

+        }

       }

 

       SizeT outProcessed = size;

+      SizeT inProcessed = _inSize - _inPos;

+      

       ELzmaStatus status;

       SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,

-          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);

+          _inBuf + _inPos, &inProcessed, finishMode, &status);

+

       _inPos += (UInt32)inProcessed;

       _inSizeProcessed += inProcessed;

       _outSizeProcessed += outProcessed;

       size -= (UInt32)outProcessed;

       data = (Byte *)data + outProcessed;

+      

+      totalProcessed += (UInt32)outProcessed;

       if (processedSize)

-        *processedSize += (UInt32)outProcessed;

-      RINOK(SResToHRESULT(res));

+        *processedSize = totalProcessed;

+

+      if (res != SZ_OK)

+      {

+        if (totalProcessed != 0)

+          return S_OK;

+        return SResToHRESULT(res);

+      }

+      

       if (inProcessed == 0 && outProcessed == 0)

         return S_OK;

+      if (status == LZMA_STATUS_FINISHED_WITH_MARK)

+        return S_OK;

+      if (outProcessed != 0)

+      {

+        if (finishMode != LZMA_FINISH_END || _outSize != _outSizeProcessed)

+          return S_OK;

+      }

     }

   }

-  while (size != 0);

-  return S_OK;

 }

 

 #endif

diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
index 3540097..0ae43b0 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/CPP/7zip/Compress/Lzma2Decoder.h
@@ -15,7 +15,9 @@
 class CDecoder:

   public ICompressCoder,

   public ICompressSetDecoderProperties2,

+  public ICompressSetFinishMode,

   public ICompressGetInStreamProcessedSize,

+  public ICompressSetBufSize,

   #ifndef NO_READ_FROM_CODER

   public ICompressSetInStream,

   public ICompressSetOutStreamSize,

@@ -27,36 +29,49 @@
   Byte *_inBuf;

   UInt32 _inPos;

   UInt32 _inSize;

-  CLzma2Dec _state;

+

+  bool _finishMode;

   bool _outSizeDefined;

   UInt64 _outSize;

+

   UInt64 _inSizeProcessed;

   UInt64 _outSizeProcessed;

+  

+  UInt32 _inBufSize;

+  UInt32 _inBufSizeNew;

+  UInt32 _outStepSize;

+

+  CLzma2Dec _state;

 public:

 

+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)

+  MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)

   #ifndef NO_READ_FROM_CODER

-  MY_UNKNOWN_IMP5(

-      ICompressSetDecoderProperties2,

-      ICompressGetInStreamProcessedSize,

-      ICompressSetInStream,

-      ICompressSetOutStreamSize,

-      ISequentialInStream)

-  #else

-  MY_UNKNOWN_IMP2(

-      ICompressSetDecoderProperties2,

-      ICompressGetInStreamProcessedSize)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)

+  MY_QUERYINTERFACE_ENTRY(ISequentialInStream)

   #endif

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

 

-  STDMETHOD(Code)(ISequentialInStream *inStream,

-      ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize,

-      ICompressProgressInfo *progress);

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

 

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

 

+  STDMETHOD(SetFinishMode)(UInt32 finishMode);

+

   STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);

 

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

+

   STDMETHOD(SetInStream)(ISequentialInStream *inStream);

   STDMETHOD(ReleaseInStream)();

+  

   STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

 

   #ifndef NO_READ_FROM_CODER

diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
index 871f146..7fea9cc 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -19,14 +19,6 @@
 

 namespace NLzma2 {

 

-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

-static void SzBigFree(void *, void *address) { BigFree(address); }

-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

-

-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

-static void SzFree(void *, void *address) { MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 CEncoder::CEncoder()

 {

   _encoder = 0;

@@ -46,7 +38,20 @@
   switch (propID)

   {

     case NCoderPropID::kBlockSize:

-      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break;

+    {

+      if (prop.vt == VT_UI4)

+        lzma2Props.blockSize = prop.ulVal;

+      else if (prop.vt == VT_UI8)

+      {

+        size_t v = (size_t)prop.uhVal.QuadPart;

+        if (v != prop.uhVal.QuadPart)

+          return E_INVALIDARG;

+        lzma2Props.blockSize = v;

+      }

+      else

+        return E_INVALIDARG;

+      break;

+    }

     case NCoderPropID::kNumThreads:

       if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;

     default:

diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
index fc43702..3b3d218 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/CPP/7zip/Compress/Lzma2Encoder.h
@@ -20,7 +20,7 @@
 {

   CLzma2EncHandle _encoder;

 public:

-  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

+  MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)

  

   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
index 28430b4..4367105 100644
--- a/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/CPP/7zip/Compress/Lzma2Register.cpp
@@ -6,15 +6,17 @@
 

 #include "Lzma2Decoder.h"

 

-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); }

 #ifndef EXTRACT_ONLY

 #include "Lzma2Encoder.h"

-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder);  }

-#else

-#define CreateCodecOut 0

 #endif

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false };

+namespace NCompress {

+namespace NLzma2 {

 

-REGISTER_CODEC(LZMA2)

+REGISTER_CODEC_E(LZMA2,

+    CDecoder(),

+    CEncoder(),

+    0x21,

+    "LZMA2")

+

+}}

diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
index 4ffb750..20e409e 100644
--- a/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -10,7 +10,7 @@
 

 static HRESULT SResToHRESULT(SRes res)

 {

-  switch(res)

+  switch (res)

   {

     case SZ_OK: return S_OK;

     case SZ_ERROR_MEM: return E_OUTOFMEMORY;

@@ -25,20 +25,16 @@
 namespace NLzma {

 

 CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),

-  _inBufSize(1 << 20),

-  _outBufSize(1 << 22),

-  FinishStream(false),

-  NeedMoreInput(false)

+    _inBufSize(1 << 20),

+    _outBufSize(1 << 22),

+    FinishStream(false),

+    NeedMoreInput(false)

 {

   _inSizeProcessed = 0;

   _inPos = _inSize = 0;

   LzmaDec_Construct(&_state);

 }

 

-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

-static void SzFree(void *p, void *address) { p = p; MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 CDecoder::~CDecoder()

 {

   LzmaDec_Free(&_state, &g_Alloc);

@@ -87,6 +83,12 @@
   return S_OK;

 }

 

+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)

+{

+  FinishStream = (finishMode != 0);

+  return S_OK;

+}

+

 HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)

 {

   if (_inBuf == 0 || !_propsWereSet)

diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
index 191fbf9..a4d7206 100644
--- a/CPP/7zip/Compress/LzmaDecoder.h
+++ b/CPP/7zip/Compress/LzmaDecoder.h
@@ -14,6 +14,7 @@
 class CDecoder:

   public ICompressCoder,

   public ICompressSetDecoderProperties2,

+  public ICompressSetFinishMode,

   public ICompressSetBufSize,

   #ifndef NO_READ_FROM_CODER

   public ICompressSetInStream,

@@ -45,6 +46,7 @@
 public:

   MY_QUERYINTERFACE_BEGIN2(ICompressCoder)

   MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)

   MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)

   #ifndef NO_READ_FROM_CODER

   MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)

@@ -57,6 +59,7 @@
   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+  STDMETHOD(SetFinishMode)(UInt32 finishMode);

   STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

   STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

   STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
index e6feb79..10af8c5 100644
--- a/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -12,29 +12,21 @@
 namespace NCompress {

 namespace NLzma {

 

-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

-static void SzBigFree(void *, void *address) { BigFree(address); }

-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

-

-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

-static void SzFree(void *, void *address) { MyFree(address); }

-static ISzAlloc g_Alloc = { SzAlloc, SzFree };

-

 CEncoder::CEncoder()

 {

-  _encoder = 0;

+  _encoder = NULL;

   _encoder = LzmaEnc_Create(&g_Alloc);

-  if (_encoder == 0)

+  if (!_encoder)

     throw 1;

 }

 

 CEncoder::~CEncoder()

 {

-  if (_encoder != 0)

+  if (_encoder)

     LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);

 }

 

-inline wchar_t GetUpperChar(wchar_t c)

+static inline wchar_t GetUpperChar(wchar_t c)

 {

   if (c >= 'a' && c <= 'z')

     c -= 0x20;

@@ -51,22 +43,21 @@
     int numHashBytesLoc = (int)(*s++ - L'0');

     if (numHashBytesLoc < 4 || numHashBytesLoc > 4)

       return 0;

-    if (*s++ != 0)

+    if (*s != 0)

       return 0;

     *btMode = 0;

     *numHashBytes = numHashBytesLoc;

     return 1;

   }

+

   if (c != L'B')

     return 0;

-

   if (GetUpperChar(*s++) != L'T')

     return 0;

   int numHashBytesLoc = (int)(*s++ - L'0');

   if (numHashBytesLoc < 2 || numHashBytesLoc > 4)

     return 0;

-  c = GetUpperChar(*s++);

-  if (c != L'\0')

+  if (*s != 0)

     return 0;

   *btMode = 1;

   *numHashBytes = numHashBytesLoc;

diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
index 3db30a9..7feafc2 100644
--- a/CPP/7zip/Compress/LzmaEncoder.h
+++ b/CPP/7zip/Compress/LzmaEncoder.h
@@ -21,7 +21,7 @@
   CLzmaEncHandle _encoder;

   UInt64 _inputProcessed;

 public:

-  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

+  MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)

     

   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

       const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
index 9c67eaf..4397595 100644
--- a/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/CPP/7zip/Compress/LzmaRegister.cpp
@@ -6,15 +6,17 @@
 

 #include "LzmaDecoder.h"

 

-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); }

 #ifndef EXTRACT_ONLY

 #include "LzmaEncoder.h"

-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder);  }

-#else

-#define CreateCodecOut 0

 #endif

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false };

+namespace NCompress {

+namespace NLzma {

 

-REGISTER_CODEC(LZMA)

+REGISTER_CODEC_E(LZMA,

+    CDecoder(),

+    CEncoder(),

+    0x30101,

+    "LZMA")

+

+}}

diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
index 2373185..f86005b 100644
--- a/CPP/7zip/Compress/PpmdDecoder.cpp
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -23,10 +23,6 @@
   kStatus_Error

 };

 

-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

-static void SzBigFree(void *, void *address) { BigFree(address); }

-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

-

 CDecoder::~CDecoder()

 {

   ::MidFree(_outBuf);

@@ -53,7 +49,7 @@
 

 HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)

 {

-  switch(_status)

+  switch (_status)

   {

     case kStatus_Finished: return S_OK;

     case kStatus_Error: return S_FALSE;

diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
index e232077..49d6508 100644
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -14,10 +14,6 @@
 

 static const UInt32 kBufSize = (1 << 20);

 

-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

-static void SzBigFree(void *, void *address) { BigFree(address); }

-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

-

 static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };

 

 void CEncProps::Normalize(int level)

@@ -40,7 +36,7 @@
       }

     }

   }

-  if (Order == -1) Order = kOrders[level];

+  if (Order == -1) Order = kOrders[(unsigned)level];

 }

 

 CEncoder::CEncoder():

diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h
index 66ce437..cdb0352 100644
--- a/CPP/7zip/Compress/PpmdEncoder.h
+++ b/CPP/7zip/Compress/PpmdEncoder.h
@@ -41,7 +41,8 @@
   CPpmd7 _ppmd;

   CEncProps _props;

 public:

-  MY_UNKNOWN_IMP2(

+  MY_UNKNOWN_IMP3(

+      ICompressCoder,

       ICompressSetCoderProperties,

       ICompressWriteCoderProperties)

   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
index e2fd007..c748696 100644
--- a/CPP/7zip/Compress/PpmdRegister.cpp
+++ b/CPP/7zip/Compress/PpmdRegister.cpp
@@ -1,5 +1,4 @@
 // PpmdRegister.cpp

-// 2009-05-30 : Igor Pavlov : Public domain

 

 #include "StdAfx.h"

 

@@ -7,15 +6,17 @@
 

 #include "PpmdDecoder.h"

 

-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); }

 #ifndef EXTRACT_ONLY

 #include "PpmdEncoder.h"

-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder);  }

-#else

-#define CreateCodecOut 0

 #endif

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false };

+namespace NCompress {

+namespace NPpmd {

 

-REGISTER_CODEC(PPMD)

+REGISTER_CODEC_E(PPMD,

+    CDecoder(),

+    CEncoder(),

+    0x30401,

+    "PPMD")

+

+}}

diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h
deleted file mode 100644
index 2c254a5..0000000
--- a/CPP/7zip/Compress/RangeCoder.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// Compress/RangeCoder.h

-// 2013-01-10 : Igor Pavlov : Public domain

-

-#ifndef __COMPRESS_RANGE_CODER_H

-#define __COMPRESS_RANGE_CODER_H

-

-#include "../Common/InBuffer.h"

-#include "../Common/OutBuffer.h"

-

-namespace NCompress {

-namespace NRangeCoder {

-

-const unsigned kNumTopBits = 24;

-const UInt32 kTopValue = (1 << kNumTopBits);

-

-class CEncoder

-{

-  UInt32 _cacheSize;

-  Byte _cache;

-public:

-  UInt64 Low;

-  UInt32 Range;

-  COutBuffer Stream;

-  bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }

-

-  void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }

-  void Init()

-  {

-    Stream.Init();

-    Low = 0;

-    Range = 0xFFFFFFFF;

-    _cacheSize = 1;

-    _cache = 0;

-  }

-

-  void FlushData()

-  {

-    // Low += 1;

-    for (int i = 0; i < 5; i++)

-      ShiftLow();

-  }

-

-  HRESULT FlushStream() { return Stream.Flush();  }

-

-  void Encode(UInt32 start, UInt32 size, UInt32 total)

-  {

-    Low += start * (Range /= total);

-    Range *= size;

-    while (Range < kTopValue)

-    {

-      Range <<= 8;

-      ShiftLow();

-    }

-  }

-

-  void ShiftLow()

-  {

-    if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0)

-    {

-      Byte temp = _cache;

-      do

-      {

-        Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));

-        temp = 0xFF;

-      }

-      while (--_cacheSize != 0);

-      _cache = (Byte)((UInt32)Low >> 24);

-    }

-    _cacheSize++;

-    Low = (UInt32)Low << 8;

-  }

-  

-  void EncodeDirectBits(UInt32 value, int numBits)

-  {

-    for (numBits--; numBits >= 0; numBits--)

-    {

-      Range >>= 1;

-      Low += Range & (0 - ((value >> numBits) & 1));

-      if (Range < kTopValue)

-      {

-        Range <<= 8;

-        ShiftLow();

-      }

-    }

-  }

-

-  void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)

-  {

-    UInt32 newBound = (Range >> numTotalBits) * size0;

-    if (symbol == 0)

-      Range = newBound;

-    else

-    {

-      Low += newBound;

-      Range -= newBound;

-    }

-    while (Range < kTopValue)

-    {

-      Range <<= 8;

-      ShiftLow();

-    }

-  }

-

-  UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }

-};

-

-class CDecoder

-{

-public:

-  CInBuffer Stream;

-  UInt32 Range;

-  UInt32 Code;

-  bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }

-

-  void Normalize()

-  {

-    while (Range < kTopValue)

-    {

-      Code = (Code << 8) | Stream.ReadByte();

-      Range <<= 8;

-    }

-  }

-  

-  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }

-  void Init()

-  {

-    Stream.Init();

-    Code = 0;

-    Range = 0xFFFFFFFF;

-    for (int i = 0; i < 5; i++)

-      Code = (Code << 8) | Stream.ReadByte();

-  }

-

-  UInt32 GetThreshold(UInt32 total)

-  {

-    return (Code) / (Range /= total);

-  }

-

-  void Decode(UInt32 start, UInt32 size)

-  {

-    Code -= start * Range;

-    Range *= size;

-    Normalize();

-  }

-

-  UInt32 DecodeDirectBits(int numTotalBits)

-  {

-    UInt32 range = Range;

-    UInt32 code = Code;

-    UInt32 result = 0;

-    for (int i = numTotalBits; i != 0; i--)

-    {

-      range >>= 1;

-      /*

-      result <<= 1;

-      if (code >= range)

-      {

-        code -= range;

-        result |= 1;

-      }

-      */

-      UInt32 t = (code - range) >> 31;

-      code -= range & (t - 1);

-      result = (result << 1) | (1 - t);

-

-      if (range < kTopValue)

-      {

-        code = (code << 8) | Stream.ReadByte();

-        range <<= 8;

-      }

-    }

-    Range = range;

-    Code = code;

-    return result;

-  }

-

-  UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)

-  {

-    UInt32 newBound = (Range >> numTotalBits) * size0;

-    UInt32 symbol;

-    if (Code < newBound)

-    {

-      symbol = 0;

-      Range = newBound;

-    }

-    else

-    {

-      symbol = 1;

-      Code -= newBound;

-      Range -= newBound;

-    }

-    Normalize();

-    return symbol;

-  }

-

-  UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); }

-};

-

-}}

-

-#endif

diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h
deleted file mode 100644
index 927a8dd..0000000
--- a/CPP/7zip/Compress/RangeCoderBit.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Compress/RangeCoderBit.h

-// 2013-01-10 : Igor Pavlov : Public domain

-

-#ifndef __COMPRESS_RANGE_CODER_BIT_H

-#define __COMPRESS_RANGE_CODER_BIT_H

-

-#include "RangeCoder.h"

-

-namespace NCompress {

-namespace NRangeCoder {

-

-const unsigned kNumBitModelTotalBits = 11;

-const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);

-

-const unsigned kNumMoveReducingBits = 4;

-

-const unsigned kNumBitPriceShiftBits = 4;

-const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;

-

-extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

-

-template <unsigned numMoveBits>

-class CBitModel

-{

-public:

-  UInt32 Prob;

-  void UpdateModel(UInt32 symbol)

-  {

-    /*

-    Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;

-    Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);

-    */

-    if (symbol == 0)

-      Prob += (kBitModelTotal - Prob) >> numMoveBits;

-    else

-      Prob -= (Prob) >> numMoveBits;

-  }

-public:

-  void Init() { Prob = kBitModelTotal / 2; }

-};

-

-template <unsigned numMoveBits>

-class CBitEncoder: public CBitModel<numMoveBits>

-{

-public:

-  void Encode(CEncoder *encoder, UInt32 symbol)

-  {

-    /*

-    encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);

-    this->UpdateModel(symbol);

-    */

-    UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;

-    if (symbol == 0)

-    {

-      encoder->Range = newBound;

-      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;

-    }

-    else

-    {

-      encoder->Low += newBound;

-      encoder->Range -= newBound;

-      this->Prob -= (this->Prob) >> numMoveBits;

-    }

-    if (encoder->Range < kTopValue)

-    {

-      encoder->Range <<= 8;

-      encoder->ShiftLow();

-    }

-  }

-  UInt32 GetPrice(UInt32 symbol) const

-  {

-    return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];

-  }

-  UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }

-  UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }

-};

-

-

-template <unsigned numMoveBits>

-class CBitDecoder: public CBitModel<numMoveBits>

-{

-public:

-  UInt32 Decode(CDecoder *decoder)

-  {

-    UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;

-    if (decoder->Code < newBound)

-    {

-      decoder->Range = newBound;

-      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;

-      if (decoder->Range < kTopValue)

-      {

-        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();

-        decoder->Range <<= 8;

-      }

-      return 0;

-    }

-    else

-    {

-      decoder->Range -= newBound;

-      decoder->Code -= newBound;

-      this->Prob -= (this->Prob) >> numMoveBits;

-      if (decoder->Range < kTopValue)

-      {

-        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();

-        decoder->Range <<= 8;

-      }

-      return 1;

-    }

-  }

-};

-

-}}

-

-#endif

diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
index 444f8fe..1da536a 100644
--- a/CPP/7zip/Crc.mak
+++ b/CPP/7zip/Crc.mak
@@ -1,6 +1,6 @@
 C_OBJS = $(C_OBJS) \

   $O\7zCrc.obj

-!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS"

+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM"

 C_OBJS = $(C_OBJS) \

 !ELSE

 ASM_OBJS = $(ASM_OBJS) \

diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp
index 70c8473..f412bf9 100644
--- a/CPP/7zip/Crypto/7zAes.cpp
+++ b/CPP/7zip/Crypto/7zAes.cpp
@@ -4,9 +4,12 @@
 

 #include "../../../C/Sha256.h"

 

-#include "../../Windows/Synchronization.h"

+#include "../../Common/ComTry.h"

 

-#include "../Common/StreamObjects.h"

+#ifndef _7ZIP_ST

+#include "../../Windows/Synchronization.h"

+#endif

+

 #include "../Common/StreamUtils.h"

 

 #include "7zAes.h"

@@ -16,60 +19,71 @@
 #include "RandGen.h"

 #endif

 

-using namespace NWindows;

-

 namespace NCrypto {

-namespace NSevenZ {

+namespace N7z {

+

+static const unsigned k_NumCyclesPower_Supported_MAX = 24;

 

 bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const

 {

   if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)

     return false;

-  for (UInt32 i = 0; i < SaltSize; i++)

+  for (unsigned i = 0; i < SaltSize; i++)

     if (Salt[i] != a.Salt[i])

       return false;

   return (Password == a.Password);

 }

 

-void CKeyInfo::CalculateDigest()

+void CKeyInfo::CalcKey()

 {

   if (NumCyclesPower == 0x3F)

   {

-    UInt32 pos;

+    unsigned pos;

     for (pos = 0; pos < SaltSize; pos++)

       Key[pos] = Salt[pos];

-    for (UInt32 i = 0; i < Password.Size() && pos < kKeySize; i++)

+    for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++)

       Key[pos++] = Password[i];

     for (; pos < kKeySize; pos++)

       Key[pos] = 0;

   }

   else

   {

+    size_t bufSize = 8 + SaltSize + Password.Size();

+    CObjArray<Byte> buf(bufSize);

+    memcpy(buf, Salt, SaltSize);

+    memcpy(buf + SaltSize, Password, Password.Size());

+    

     CSha256 sha;

     Sha256_Init(&sha);

-    const UInt64 numRounds = (UInt64)1 << NumCyclesPower;

-    Byte temp[8] = { 0,0,0,0,0,0,0,0 };

-    for (UInt64 round = 0; round < numRounds; round++)

+    

+    Byte *ctr = buf + SaltSize + Password.Size();

+    

+    for (unsigned i = 0; i < 8; i++)

+      ctr[i] = 0;

+    

+    UInt64 numRounds = (UInt64)1 << NumCyclesPower;

+

+    do

     {

-      Sha256_Update(&sha, Salt, (size_t)SaltSize);

-      Sha256_Update(&sha, Password, Password.Size());

-      Sha256_Update(&sha, temp, 8);

-      for (int i = 0; i < 8; i++)

-        if (++(temp[i]) != 0)

+      Sha256_Update(&sha, buf, bufSize);

+      for (unsigned i = 0; i < 8; i++)

+        if (++(ctr[i]) != 0)

           break;

     }

+    while (--numRounds != 0);

+

     Sha256_Final(&sha, Key);

   }

 }

 

-bool CKeyInfoCache::Find(CKeyInfo &key)

+bool CKeyInfoCache::GetKey(CKeyInfo &key)

 {

   FOR_VECTOR (i, Keys)

   {

     const CKeyInfo &cached = Keys[i];

     if (key.IsEqualTo(cached))

     {

-      for (int j = 0; j < kKeySize; j++)

+      for (unsigned j = 0; j < kKeySize; j++)

         key.Key[j] = cached.Key[j];

       if (i != 0)

         Keys.MoveToFront(i);

@@ -79,40 +93,60 @@
   return false;

 }

 

-void CKeyInfoCache::Add(CKeyInfo &key)

+void CKeyInfoCache::FindAndAdd(const CKeyInfo &key)

 {

-  if (Find(key))

-    return;

+  FOR_VECTOR (i, Keys)

+  {

+    const CKeyInfo &cached = Keys[i];

+    if (key.IsEqualTo(cached))

+    {

+      if (i != 0)

+        Keys.MoveToFront(i);

+      return;

+    }

+  }

+  Add(key);

+}

+

+void CKeyInfoCache::Add(const CKeyInfo &key)

+{

   if (Keys.Size() >= Size)

     Keys.DeleteBack();

   Keys.Insert(0, key);

 }

 

 static CKeyInfoCache g_GlobalKeyCache(32);

-static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;

+

+#ifndef _7ZIP_ST

+  static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;

+  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);

+#else

+  #define MT_LOCK

+#endif

 

 CBase::CBase():

   _cachedKeys(16),

   _ivSize(0)

 {

-  for (int i = 0; i < sizeof(_iv); i++)

+  for (unsigned i = 0; i < sizeof(_iv); i++)

     _iv[i] = 0;

 }

 

-void CBase::CalculateDigest()

+void CBase::PrepareKey()

 {

-  NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);

-  if (_cachedKeys.Find(_key))

-    g_GlobalKeyCache.Add(_key);

-  else

+  // BCJ2 threads use same password. So we use long lock.

+  MT_LOCK

+  

+  bool finded = false;

+  if (!_cachedKeys.GetKey(_key))

   {

-    if (!g_GlobalKeyCache.Find(_key))

-    {

-      _key.CalculateDigest();

-      g_GlobalKeyCache.Add(_key);

-    }

+    finded = g_GlobalKeyCache.GetKey(_key);

+    if (!finded)

+      _key.CalcKey();

     _cachedKeys.Add(_key);

   }

+  if (!finded)

+    g_GlobalKeyCache.FindAndAdd(_key);

 }

 

 #ifndef EXTRACT_ONLY

@@ -128,102 +162,114 @@
 

 STDMETHODIMP CEncoder::ResetInitVector()

 {

+  for (unsigned i = 0; i < sizeof(_iv); i++)

+    _iv[i] = 0;

   _ivSize = 8;

-  g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);

+  g_RandomGenerator.Generate(_iv, _ivSize);

   return S_OK;

 }

 

 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

 {

-   // _key.Init();

-   for (UInt32 i = _ivSize; i < sizeof(_iv); i++)

-    _iv[i] = 0;

+  Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];

+  unsigned propsSize = 1;

 

-  UInt32 ivSize = _ivSize;

-  

-  // _key.NumCyclesPower = 0x3F;

-  _key.NumCyclesPower = 19;

+  props[0] = (Byte)(_key.NumCyclesPower

+      | (_key.SaltSize == 0 ? 0 : (1 << 7))

+      | (_ivSize       == 0 ? 0 : (1 << 6)));

 

-  Byte firstByte = (Byte)(_key.NumCyclesPower |

-    (((_key.SaltSize == 0) ? 0 : 1) << 7) |

-    (((ivSize == 0) ? 0 : 1) << 6));

-  RINOK(outStream->Write(&firstByte, 1, NULL));

-  if (_key.SaltSize == 0 && ivSize == 0)

-    return S_OK;

-  Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1));

-  Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1));

-  Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec);

-  RINOK(outStream->Write(&secondByte, 1, NULL));

-  if (_key.SaltSize > 0)

+  if (_key.SaltSize != 0 || _ivSize != 0)

   {

-    RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize));

+    props[1] = (Byte)(

+        ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4)

+        | (_ivSize      == 0 ? 0 : _ivSize - 1));

+    memcpy(props + 2, _key.Salt, _key.SaltSize);

+    propsSize = 2 + _key.SaltSize;

+    memcpy(props + propsSize, _iv, _ivSize);

+    propsSize += _ivSize;

   }

-  if (ivSize > 0)

-  {

-    RINOK(WriteStream(outStream, _iv, ivSize));

-  }

-  return S_OK;

+

+  return WriteStream(outStream, props, propsSize);

 }

 

-HRESULT CEncoder::CreateFilter()

+CEncoder::CEncoder()

 {

+  // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);

+  // _key.NumCyclesPower = 0x3F;

+  _key.NumCyclesPower = 19;

   _aesFilter = new CAesCbcEncoder(kKeySize);

-  return S_OK;

 }

 

 #endif

 

+CDecoder::CDecoder()

+{

+  _aesFilter = new CAesCbcDecoder(kKeySize);

+}

+

 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)

 {

-  _key.Init();

-  UInt32 i;

+  _key.ClearProps();

+ 

+  _ivSize = 0;

+  unsigned i;

   for (i = 0; i < sizeof(_iv); i++)

     _iv[i] = 0;

+  

   if (size == 0)

     return S_OK;

-  UInt32 pos = 0;

-  Byte firstByte = data[pos++];

-

-  _key.NumCyclesPower = firstByte & 0x3F;

-  if ((firstByte & 0xC0) == 0)

-    return S_OK;

-  _key.SaltSize = (firstByte >> 7) & 1;

-  UInt32 ivSize = (firstByte >> 6) & 1;

-

-  if (pos >= size)

-    return E_INVALIDARG;

-  Byte secondByte = data[pos++];

   

-  _key.SaltSize += (secondByte >> 4);

-  ivSize += (secondByte & 0x0F);

-  

-  if (pos + _key.SaltSize + ivSize > size)

+  Byte b0 = data[0];

+

+  _key.NumCyclesPower = b0 & 0x3F;

+  if ((b0 & 0xC0) == 0)

+    return size == 1 ? S_OK : E_INVALIDARG;

+

+  if (size <= 1)

     return E_INVALIDARG;

-  for (i = 0; i < _key.SaltSize; i++)

-    _key.Salt[i] = data[pos++];

+

+  Byte b1 = data[1];

+

+  unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);

+  unsigned ivSize   = ((b0 >> 6) & 1) + (b1 & 0x0F);

+  

+  if (size != 2 + saltSize + ivSize)

+    return E_INVALIDARG;

+  _key.SaltSize = saltSize;

+  data += 2;

+  for (i = 0; i < saltSize; i++)

+    _key.Salt[i] = *data++;

   for (i = 0; i < ivSize; i++)

-    _iv[i] = data[pos++];

-  return (_key.NumCyclesPower <= 24) ? S_OK :  E_NOTIMPL;

+    _iv[i] = *data++;

+  return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX

+      || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;

 }

 

+

 STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)

 {

+  COM_TRY_BEGIN

+  

   _key.Password.CopyFrom(data, (size_t)size);

   return S_OK;

+  

+  COM_TRY_END

 }

 

 STDMETHODIMP CBaseCoder::Init()

 {

-  CalculateDigest();

-  if (_aesFilter == 0)

-  {

-    RINOK(CreateFilter());

-  }

+  COM_TRY_BEGIN

+  

+  PrepareKey();

   CMyComPtr<ICryptoProperties> cp;

   RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));

-  RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));

+  if (!cp)

+    return E_FAIL;

+  RINOK(cp->SetKey(_key.Key, kKeySize));

   RINOK(cp->SetInitVector(_iv, sizeof(_iv)));

   return _aesFilter->Init();

+  

+  COM_TRY_END

 }

 

 STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)

@@ -231,10 +277,4 @@
   return _aesFilter->Filter(data, size);

 }

 

-HRESULT CDecoder::CreateFilter()

-{

-  _aesFilter = new CAesCbcDecoder(kKeySize);

-  return S_OK;

-}

-

 }}

diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h
index baa1258..5a09436 100644
--- a/CPP/7zip/Crypto/7zAes.h
+++ b/CPP/7zip/Crypto/7zAes.h
@@ -11,28 +11,30 @@
 #include "../IPassword.h"

 

 namespace NCrypto {

-namespace NSevenZ {

+namespace N7z {

 

-const int kKeySize = 32;

+const unsigned kKeySize = 32;

+const unsigned kSaltSizeMax = 16;

+const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE;

 

 class CKeyInfo

 {

 public:

-  int NumCyclesPower;

-  UInt32 SaltSize;

-  Byte Salt[16];

+  unsigned NumCyclesPower;

+  unsigned SaltSize;

+  Byte Salt[kSaltSizeMax];

   CByteBuffer Password;

   Byte Key[kKeySize];

 

   bool IsEqualTo(const CKeyInfo &a) const;

-  void CalculateDigest();

+  void CalcKey();

 

-  CKeyInfo() { Init(); }

-  void Init()

+  CKeyInfo() { ClearProps(); }

+  void ClearProps()

   {

     NumCyclesPower = 0;

     SaltSize = 0;

-    for (int i = 0; i < sizeof(Salt); i++)

+    for (unsigned i = 0; i < sizeof(Salt); i++)

       Salt[i] = 0;

   }

 };

@@ -43,9 +45,9 @@
   CObjectVector<CKeyInfo> Keys;

 public:

   CKeyInfoCache(unsigned size): Size(size) {}

-  bool Find(CKeyInfo &key);

-  // HRESULT Calculate(CKeyInfo &key);

-  void Add(CKeyInfo &key);

+  bool GetKey(CKeyInfo &key);

+  void Add(const CKeyInfo &key);

+  void FindAndAdd(const CKeyInfo &key);

 };

 

 class CBase

@@ -53,9 +55,10 @@
   CKeyInfoCache _cachedKeys;

 protected:

   CKeyInfo _key;

-  Byte _iv[16];

-  UInt32 _ivSize;

-  void CalculateDigest();

+  Byte _iv[kIvSizeMax];

+  unsigned _ivSize;

+  

+  void PrepareKey();

   CBase();

 };

 

@@ -68,13 +71,8 @@
 protected:

   CMyComPtr<ICompressFilter> _aesFilter;

 

-  virtual HRESULT CreateFilter() = 0;

-  #ifndef CRYPTO_AES

-  HRESULT CreateFilterFromDLL(REFCLSID clsID);

-  #endif

 public:

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  INTERFACE_ICompressFilter(;)

   

   STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);

 };

@@ -87,9 +85,9 @@
   // public ICryptoResetSalt,

   public ICryptoResetInitVector

 {

-  virtual HRESULT CreateFilter();

 public:

-  MY_UNKNOWN_IMP3(

+  MY_UNKNOWN_IMP4(

+      ICompressFilter,

       ICryptoSetPassword,

       ICompressWriteCoderProperties,

       // ICryptoResetSalt,

@@ -97,19 +95,22 @@
   STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

   // STDMETHOD(ResetSalt)();

   STDMETHOD(ResetInitVector)();

+  CEncoder();

 };

+

 #endif

 

 class CDecoder:

   public CBaseCoder,

   public ICompressSetDecoderProperties2

 {

-  virtual HRESULT CreateFilter();

 public:

-  MY_UNKNOWN_IMP2(

+  MY_UNKNOWN_IMP3(

+      ICompressFilter,

       ICryptoSetPassword,

       ICompressSetDecoderProperties2)

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+  CDecoder();

 };

 

 }}

diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp
index 87f8ae9..c0b2060 100644
--- a/CPP/7zip/Crypto/7zAesRegister.cpp
+++ b/CPP/7zip/Crypto/7zAesRegister.cpp
@@ -3,16 +3,15 @@
 #include "StdAfx.h"

 

 #include "../Common/RegisterCodec.h"

+

 #include "7zAes.h"

 

-static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); }

-#ifndef EXTRACT_ONLY

-static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); }

-#else

-#define CreateCodecOut 0

-#endif

+namespace NCrypto {

+namespace N7z {

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true };

+REGISTER_FILTER_E(7zAES,

+    CDecoder(),

+    CEncoder(),

+    0x6F10701, "7zAES")

 

-REGISTER_CODEC(7zAES)

+}}

diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
index 71f3fa7..2c10048 100644
--- a/CPP/7zip/Crypto/MyAes.h
+++ b/CPP/7zip/Crypto/MyAes.h
@@ -26,13 +26,17 @@
   Byte _iv[AES_BLOCK_SIZE];

 

   bool SetFunctions(UInt32 algo);

+

 public:

   CAesCbcCoder(bool encodeMode, unsigned keySize);

-  MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties)

-  STDMETHOD(Init)();

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  

+  MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)

+  

+  INTERFACE_ICompressFilter(;)

+  

   STDMETHOD(SetKey)(const Byte *data, UInt32 size);

   STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);

+  

   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

 };

 

@@ -46,7 +50,6 @@
   CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {}

 };

 

-

 }

 

 #endif

diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp
index 2815b1d..3427ad6 100644
--- a/CPP/7zip/Crypto/MyAesReg.cpp
+++ b/CPP/7zip/Crypto/MyAesReg.cpp
@@ -6,14 +6,11 @@
 

 #include "MyAes.h"

 

-static void *CreateCodecCbc() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcDecoder(32)); }

-#ifndef EXTRACT_ONLY

-static void *CreateCodecCbcOut() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcEncoder(32)); }

-#else

-#define CreateCodecCbcOut 0

-#endif

+namespace NCrypto {

 

-static CCodecInfo g_CodecInfo =

-  { CreateCodecCbc, CreateCodecCbcOut, 0x06F00181, L"AES256CBC", 1, true };

-REGISTER_CODEC(AES256CBC)

+REGISTER_FILTER_E(AES256CBC,

+    CAesCbcDecoder(32),

+    CAesCbcEncoder(32),

+    0x6F00181, "AES256CBC")

 

+}

diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp
index 983662a..542f39b 100644
--- a/CPP/7zip/Crypto/RandGen.cpp
+++ b/CPP/7zip/Crypto/RandGen.cpp
@@ -2,7 +2,9 @@
 

 #include "StdAfx.h"

 

+#ifndef _7ZIP_ST

 #include "../../Windows/Synchronization.h"

+#endif

 

 #include "RandGen.h"

 

@@ -71,8 +73,10 @@
     HASH_UPD(v2);

     #endif

 

+    #ifdef _WIN32

     DWORD tickCount = ::GetTickCount();

     HASH_UPD(tickCount);

+    #endif

     

     for (unsigned j = 0; j < 100; j++)

     {

@@ -85,14 +89,20 @@
   _needInit = false;

 }

 

-static NWindows::NSynchronization::CCriticalSection g_CriticalSection;

+#ifndef _7ZIP_ST

+  static NWindows::NSynchronization::CCriticalSection g_CriticalSection;

+  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);

+#else

+  #define MT_LOCK

+#endif

 

 void CRandomGenerator::Generate(Byte *data, unsigned size)

 {

-  g_CriticalSection.Enter();

+  MT_LOCK

+

   if (_needInit)

     Init();

-  while (size > 0)

+  while (size != 0)

   {

     CSha256 hash;

     

@@ -106,10 +116,9 @@
     Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);

     Byte buff[SHA256_DIGEST_SIZE];

     Sha256_Final(&hash, buff);

-    for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--)

+    for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)

       *data++ = buff[i];

   }

-  g_CriticalSection.Leave();

 }

 

 CRandomGenerator g_RandomGenerator;

diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index 2b01644..c746316 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -3,18 +3,23 @@
 00 IProgress.h

 

   05  IProgress

+  // 050002  IProgress2

 

 01 IFolderArchive.h

 

   // 05  IArchiveFolder   // old 

   // 06  IInFolderArchive // old

   07  IFileExtractCallback.h::IFolderArchiveExtractCallback

+  08  IFileExtractCallback.h::IFolderArchiveExtractCallback2

   // 0A  IOutFolderArchive

   0B  IFolderArchiveUpdateCallback

   0C  Agent.h::IArchiveFolderInternal

   0D  IArchiveFolder

   0E  IInFolderArchive

   0F  IOutFolderArchive

+  10  IFolderArchiveUpdateCallback2

+  11  IFolderScanProgress

+  

   20  IFileExtractCallback.h::IGetProp

   30  IFileExtractCallback.h::IFolderExtractToStreamCallback

 

@@ -25,7 +30,7 @@
   03  IInStream

   04  IOutStream

   06  IStreamGetSize

-  07  IOutStreamFlush

+  07  IOutStreamFinish

   08  IStreamGetProps

   09  IStreamGetProps2

 

@@ -41,12 +46,20 @@
   23  ICompressWriteCoderProperties

   24  ICompressGetInStreamProcessedSize

   25  ICompressSetCoderMt

+  26  ICompressSetFinishMode

+

   30  ICompressGetSubStreamSize

   31  ICompressSetInStream

   32  ICompressSetOutStream

-  33  ICompressSetInStreamSize

+//  33  ICompressSetInStreamSize

   34  ICompressSetOutStreamSize

   35  ICompressSetBufSize

+  36  ICompressInitEncoder

+  37  ICompressSetInStream2

+//  38  ICompressSetOutStream2

+//  39  SetInStreamSize2

+//  3A  SetOutStreamSize2

+

   40  ICompressFilter

   60  ICompressCodecsInfo

   61  ISetCompressCodecsInfo

@@ -72,7 +85,10 @@
   05  IArchiveAllowTail

 

   10  IArchiveOpenCallback

+  

   20  IArchiveExtractCallback

+  21  IArchiveExtractCallbackMessage

+  

   30  IArchiveOpenVolumeCallback

   40  IInArchiveGetStream

   50  IArchiveOpenSetSubArchiveName

@@ -83,6 +99,8 @@
 

   80  IArchiveUpdateCallback

   82  IArchiveUpdateCallback2

+  83  IArchiveUpdateCallbackFile

+

   A0  IOutArchive

 

 

@@ -112,6 +130,7 @@
   14 IFolderCalcItemFullSize

   15 IFolderCompare

   16 IFolderGetItemName

+  17 IFolderAltStreams

 

 

 09 IFolder.h :: FOLDER_MANAGER_INTERFACE

@@ -144,6 +163,12 @@
   0C xz

   0D ppmd

 

+  C7 Ext

+  C8 VMDK

+  C9 VDI

+  CA Qcow

+  CB GPT

+  CC Rar5

   CD IHex

   CE Hxs

   CF TE

@@ -180,12 +205,11 @@
   EE Tar

   EF GZip

 

-{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle

 {23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu

 

-{23170F69-40C1-278B- old codecs clsids

-

-{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions

+// {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler

+// {23170F69-40C1-278B- old codecs clsids

+// {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions

 

 {23170F69-40C1-2790-id} Codec Decoders

 {23170F69-40C1-2791-id} Codec Encoders

diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
index 9153adc..454240d 100644
--- a/CPP/7zip/ICoder.h
+++ b/CPP/7zip/ICoder.h
@@ -10,6 +10,15 @@
 CODER_INTERFACE(ICompressProgressInfo, 0x04)

 {

   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;

+  

+  /* (inSize) can be NULL, if unknown

+     (outSize) can be NULL, if unknown

+

+  returns:

+    S_OK

+    E_ABORT  : Break by user

+    another error codes

+  */

 };

 

 CODER_INTERFACE(ICompressCoder, 0x05)

@@ -21,11 +30,75 @@
 

 CODER_INTERFACE(ICompressCoder2, 0x18)

 {

-  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

-      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+  STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,

+      ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,

       ICompressProgressInfo *progress) PURE;

 };

 

+/*

+  ICompressCoder::Code

+  ICompressCoder2::Code

+  

+  returns:

+    S_OK     : OK

+    S_FALSE  : data error (for decoders)

+    E_OUTOFMEMORY : memory allocation error

+    another error code : some error. For example, it can be error code received from inStream or outStream function.

+  

+  Parameters:

+    (inStream != NULL)

+    (outStream != NULL)

+

+    if (inSize != NULL)

+    {

+      Encoders in 7-Zip ignore (inSize).

+      Decoder can use (*inSize) to check that stream was decoded correctly.

+      Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode)

+    }

+

+    If it's required to limit the reading from input stream (inStream), it can

+      be done with ISequentialInStream implementation.

+

+    if (outSize != NULL)

+    {

+      Encoders in 7-Zip ignore (outSize).

+      Decoder unpacks no more than (*outSize) bytes.

+    }

+    

+    (progress == NULL) is allowed.

+

+

+  Decoding with Code() function

+  -----------------------------

+   

+  You can request some interfaces before decoding

+   - ICompressSetDecoderProperties2

+   - ICompressSetFinishMode

+

+  If you need to decode full stream:

+  {

+    1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1);

+    2) call the Code() function with specified (inSize) and (outSize), if these sizes are known.

+  }

+

+  If you need to decode only part of stream:

+  {

+    1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0);

+    2) Call the Code() function with specified (inSize = NULL) and specified (outSize).

+  }

+

+  Encoding with Code() function

+  -----------------------------

+  

+  You can request some interfaces :

+  - ICompressSetCoderProperties   - use it before encoding to set properties

+  - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties.

+

+  ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1)

+     The rules are similar to ICompressCoder rules

+*/

+

+

 namespace NCoderPropID

 {

   enum EEnum

@@ -64,6 +137,12 @@
 

 CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)

 {

+  /* returns:

+    S_OK

+    E_NOTIMP      : unsupported properties

+    E_INVALIDARG  : incorrect (or unsupported) properties

+    E_OUTOFMEMORY : memory allocation error

+  */

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;

 };

 

@@ -82,9 +161,34 @@
   STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;

 };

 

+CODER_INTERFACE(ICompressSetFinishMode, 0x26)

+{

+  STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE;

+

+  /* finishMode:

+    0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined.

+    1 : full decoding. The stream must be finished at the end of decoding. */

+};

+

+

 CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)

 {

   STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;

+

+  /* returns:

+    S_OK     : (*value) contains the size or estimated size (can be incorrect size)

+    S_FALSE  : size is undefined

+    E_NOTIMP : the feature is not implemented

+

+  Let's (read_size) is size of data that was already read by ISequentialInStream::Read().

+  The caller should call GetSubStreamSize() after each Read() and check sizes:

+    if (start_of_subStream + *value < read_size)

+    {

+      // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream:

+      start_of_subStream += *value;

+      subStream++;

+    }

+  */

 };

 

 CODER_INTERFACE(ICompressSetInStream, 0x31)

@@ -99,14 +203,21 @@
   STDMETHOD(ReleaseOutStream)() PURE;

 };

 

+/*

 CODER_INTERFACE(ICompressSetInStreamSize, 0x33)

 {

   STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;

 };

+*/

 

 CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)

 {

   STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;

+

+  /* That function initializes decoder structures.

+     Call this function only for stream version of decoder.

+       if (outSize == NULL), then output size is unknown

+       if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */

 };

 

 CODER_INTERFACE(ICompressSetBufSize, 0x35)

@@ -115,25 +226,62 @@
   STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;

 };

 

+CODER_INTERFACE(ICompressInitEncoder, 0x36)

+{

+  STDMETHOD(InitEncoder)() PURE;

+

+  /* That function initializes encoder structures.

+     Call this function only for stream version of encoder. */

+};

+

+CODER_INTERFACE(ICompressSetInStream2, 0x37)

+{

+  STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE;

+  STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE;

+};

+

+/*

+CODER_INTERFACE(ICompressSetOutStream2, 0x38)

+{

+  STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE;

+  STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE;

+};

+

+CODER_INTERFACE(ICompressSetInStreamSize2, 0x39)

+{

+  STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE;

+};

+*/

+

+

+/*

+  ICompressFilter

+  Filter() converts as most as possible bytes

+     returns: (outSize):

+       if (outSize <= size) : Filter have converted outSize bytes

+       if (outSize >  size) : Filter have not converted anything.

+           and it needs at least outSize bytes to convert one block

+           (it's for crypto block algorithms).

+*/

+

+#define INTERFACE_ICompressFilter(x) \

+  STDMETHOD(Init)() x; \

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \

+

 CODER_INTERFACE(ICompressFilter, 0x40)

 {

-  STDMETHOD(Init)() PURE;

-  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;

-  // Filter converts as most as possible bytes

-  // Filter return outSize (UInt32)

-  // if (outSize <= size): Filter have converted outSize bytes

-  // if (outSize > size): Filter have not converted anything.

-  //      and it needs at least outSize bytes to convert one block

-  //      (it's for crypto block algorithms).

+  INTERFACE_ICompressFilter(PURE);

 };

 

+

 CODER_INTERFACE(ICompressCodecsInfo, 0x60)

 {

-  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;

+  STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE;

   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;

   STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;

   STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;

 };

+

 CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)

 {

   STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;

@@ -155,6 +303,10 @@
 CODER_INTERFACE(ICryptoResetInitVector, 0x8C)

 {

   STDMETHOD(ResetInitVector)() PURE;

+

+  /* Call ResetInitVector() only for encoding.

+     Call ResetInitVector() before encoding and before WriteCoderProperties().

+     Crypto encoder can create random IV in that function. */

 };

 

 CODER_INTERFACE(ICryptoSetPassword, 0x90)

@@ -167,8 +319,7 @@
   STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;

 };

 

-//////////////////////

-// It's for DLL file

+

 namespace NMethodPropID

 {

   enum EEnum

@@ -177,8 +328,8 @@
     kName,

     kDecoder,

     kEncoder,

-    kInStreams,

-    kOutStreams,

+    kPackStreams,

+    kUnpackStreams,

     kDescription,

     kDecoderIsAssigned,

     kEncoderIsAssigned,

@@ -186,12 +337,16 @@
   };

 }

 

+

+#define INTERFACE_IHasher(x) \

+  STDMETHOD_(void, Init)() throw() x; \

+  STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \

+  STDMETHOD_(void, Final)(Byte *digest) throw() x; \

+  STDMETHOD_(UInt32, GetDigestSize)() throw() x; \

+

 CODER_INTERFACE(IHasher, 0xC0)

 {

-  STDMETHOD_(void, Init)() PURE;

-  STDMETHOD_(void, Update)(const void *data, UInt32 size) PURE;

-  STDMETHOD_(void, Final)(Byte *digest) PURE;

-  STDMETHOD_(UInt32, GetDigestSize)() PURE;

+  INTERFACE_IHasher(PURE)

 };

 

 CODER_INTERFACE(IHashers, 0xC1)

@@ -205,7 +360,12 @@
 {

   typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);

   typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject);

+  typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject);

+

   typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);

+  

+  typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo);

 }

 

 #endif

diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
index 768bbe7..5a34b0e 100644
--- a/CPP/7zip/IDecl.h
+++ b/CPP/7zip/IDecl.h
@@ -5,10 +5,23 @@
 

 #include "../Common/MyUnknown.h"

 

+#define k_7zip_GUID_Data1 0x23170F69

+#define k_7zip_GUID_Data2 0x40C1

+

+#define k_7zip_GUID_Data3_Common  0x278A

+

+#define k_7zip_GUID_Data3_Decoder 0x2790

+#define k_7zip_GUID_Data3_Encoder 0x2791

+#define k_7zip_GUID_Data3_Hasher  0x2792

+

+

 #define DECL_INTERFACE_SUB(i, base, groupId, subId) \

-DEFINE_GUID(IID_ ## i, \

-0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \

-struct i: public base

+  DEFINE_GUID(IID_ ## i, \

+    k_7zip_GUID_Data1, \

+    k_7zip_GUID_Data2, \

+    k_7zip_GUID_Data3_Common, \

+    0, 0, 0, (groupId), 0, (subId), 0, 0); \

+  struct i: public base

 

 #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)

 

diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
index b98f480..d54529c 100644
--- a/CPP/7zip/IProgress.h
+++ b/CPP/7zip/IProgress.h
@@ -1,10 +1,9 @@
-// Interface/IProgress.h

+// IProgress.h

 

 #ifndef __IPROGRESS_H

 #define __IPROGRESS_H

 

 #include "../Common/MyTypes.h"

-#include "../Common/MyUnknown.h"

 

 #include "IDecl.h"

 

@@ -17,17 +16,4 @@
   INTERFACE_IProgress(PURE)

 };

 

-/*

-// {23170F69-40C1-278A-0000-000000050002}

-DEFINE_GUID(IID_IProgress2,

-0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);

-MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")

-IProgress2: public IUnknown

-{

-public:

-  STDMETHOD(SetTotal)(const UInt64 *total) PURE;

-  STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;

-};

-*/

-

 #endif

diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
index d347def..436e919 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"

 

@@ -95,9 +95,9 @@
   STDMETHOD(GetSize)(UInt64 *size) PURE;

 };

 

-STREAM_INTERFACE(IOutStreamFlush, 0x07)

+STREAM_INTERFACE(IOutStreamFinish, 0x07)

 {

-  STDMETHOD(Flush)() PURE;

+  STDMETHOD(OutStreamFinish)() PURE;

 };

 

 

diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
index 06e6c58..0d50f94 100644
--- a/CPP/7zip/MyVersion.h
+++ b/CPP/7zip/MyVersion.h
@@ -1,6 +1,2 @@
-#include "..\..\C\7zVersion.h"

-

-#undef MY_COPYRIGHT

-#undef MY_VERSION_COPYRIGHT_DATE

-#define MY_COPYRIGHT "Copyright (c) 1999-2014 Igor Pavlov"

-#define MY_VERSION_COPYRIGHT_DATE MY_VERSION "  " MY_COPYRIGHT "  " MY_DATE

+#define USE_COPYRIGHT_CR

+#include "../../C/7zVersion.h"

diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index da2acd7..126af67 100644
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -100,13 +100,16 @@
   kpidHardLink,

   kpidINode,

   kpidStreamId,

+  kpidReadOnly,

+  kpidOutName,

+  kpidCopyLink,

 

   kpid_NUM_DEFINED,

 

   kpidUserDefined = 0x10000

 };

 

-extern Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE

+extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE

 

 const UInt32 kpv_ErrorFlags_IsNotArc              = 1 << 0;

 const UInt32 kpv_ErrorFlags_HeadersError          = 1 << 1;

diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 011eb56..5f25f19 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"

 

@@ -32,8 +34,14 @@
 // Tou can find the list of all GUIDs in Guid.txt file.

 // use another CLSIDs, if you want to support other formats (zip, rar, ...).

 // {23170F69-40C1-278A-1000-000110070000}

+

 DEFINE_GUID(CLSID_CFormat7z,

   0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);

+DEFINE_GUID(CLSID_CFormatXz,

+  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00);

+

+#define CLSID_Format CLSID_CFormat7z

+// #define CLSID_Format CLSID_CFormatXz

 

 using namespace NWindows;

 using namespace NFile;

@@ -301,7 +309,7 @@
     NCOM::CPropVariant prop;

     RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));

     _processedFileInfo.MTimeDefined = false;

-    switch(prop.vt)

+    switch (prop.vt)

     {

       case VT_EMPTY:

         // _processedFileInfo.MTime = _utcMTimeDefault;

@@ -326,7 +334,7 @@
   

   {

     // Create folders for file

-    int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);

+    int slashPos = _filePath.ReverseFind_PathSepar();

     if (slashPos >= 0)

       CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));

   }

@@ -433,7 +441,7 @@
     }

   }

 

-  if (_outFileStream != NULL)

+  if (_outFileStream)

   {

     if (_processedFileInfo.MTimeDefined)

       _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);

@@ -491,7 +499,6 @@
   STDMETHOD(SetCompleted)(const UInt64 *completeValue);

 

   // IUpdateCallback2

-  STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);

   STDMETHOD(GetUpdateItemInfo)(UInt32 index,

       Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);

   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

@@ -543,20 +550,14 @@
   return S_OK;

 }

 

-

-STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)

-{

-  return E_NOTIMPL;

-}

-

 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,

       Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)

 {

-  if (newData != NULL)

+  if (newData)

     *newData = BoolToInt(true);

-  if (newProperties != NULL)

+  if (newProperties)

     *newProperties = BoolToInt(true);

-  if (indexInArchive != NULL)

+  if (indexInArchive)

     *indexInArchive = (UInt32)(Int32)-1;

   return S_OK;

 }

@@ -574,7 +575,7 @@
 

   {

     const CDirItem &dirItem = (*DirItems)[index];

-    switch(propID)

+    switch (propID)

     {

       case kpidPath:  prop = dirItem.Name; break;

       case kpidIsDir:  prop = dirItem.isDir(); break;

@@ -662,7 +663,7 @@
   ConvertUInt32ToString(index + 1, temp);

   UString res = temp;

   while (res.Len() < 2)

-    res = UString(L'0') + res;

+    res.InsertAtFront(L'0');

   UString fileName = VolName;

   fileName += L'.';

   fileName += res;

@@ -692,7 +693,7 @@
   return StringToBstr(Password, password);

 }

 

-//////////////////////////////////////////////////////////////////////////

+

 // Main function

 

 #define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;

@@ -708,12 +709,14 @@
     PrintStringLn(kHelpString);

     return 1;

   }

+  

   NDLL::CLibrary lib;

   if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName)))

   {

     PrintError("Can not load 7-zip library");

     return 1;

   }

+

   Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject");

   if (!createObjectFunc)

   {

@@ -731,7 +734,9 @@
     }

     c = (char)MyCharLower_Ascii(command[0]);

   }

+

   FString archiveName = CmdStringToFString(args[2]);

+  

   if (c == 'a')

   {

     // create archive command

@@ -765,6 +770,7 @@
         dirItems.Add(di);

       }

     }

+

     COutFileStream *outFileStreamSpec = new COutFileStream;

     CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;

     if (!outFileStreamSpec->Create(archiveName, false))

@@ -774,7 +780,7 @@
     }

 

     CMyComPtr<IOutArchive> outArchive;

-    if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)

+    if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK)

     {

       PrintError("Can not get class object");

       return 1;

@@ -811,17 +817,21 @@
     */

     

     HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);

+    

     updateCallbackSpec->Finilize();

+    

     if (result != S_OK)

     {

       PrintError("Update Error");

       return 1;

     }

+    

     FOR_VECTOR (i, updateCallbackSpec->FailedFiles)

     {

       PrintNewLine();

       PrintError("Error for file", updateCallbackSpec->FailedFiles[i]);

     }

+    

     if (updateCallbackSpec->FailedFiles.Size() != 0)

       return 1;

   }

@@ -834,6 +844,7 @@
     }

 

     bool listCommand;

+    

     if (c == 'l')

       listCommand = true;

     else if (c == 'x')

@@ -845,7 +856,7 @@
     }

   

     CMyComPtr<IInArchive> archive;

-    if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)

+    if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK)

     {

       PrintError("Can not get class object");

       return 1;

@@ -867,7 +878,8 @@
       // openCallbackSpec->PasswordIsDefined = true;

       // openCallbackSpec->Password = L"1";

       

-      if (archive->Open(file, 0, openCallback) != S_OK)

+      const UInt64 scanSize = 1 << 23;

+      if (archive->Open(file, &scanSize, openCallback) != S_OK)

       {

         PrintError("Can not open file as archive", archiveName);

         return 1;

@@ -911,7 +923,27 @@
       extractCallbackSpec->PasswordIsDefined = false;

       // extractCallbackSpec->PasswordIsDefined = true;

       // extractCallbackSpec->Password = L"1";

+

+      /*

+      const wchar_t *names[] =

+      {

+        L"mt",

+        L"mtf"

+      };

+      const unsigned kNumProps = sizeof(names) / sizeof(names[0]);

+      NCOM::CPropVariant values[kNumProps] =

+      {

+        (UInt32)1,

+        false

+      };

+      CMyComPtr<ISetProperties> setProperties;

+      archive->QueryInterface(IID_ISetProperties, (void **)&setProperties);

+      if (setProperties)

+        setProperties->SetProperties(names, values, kNumProps);

+      */

+

       HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);

+  

       if (result != S_OK)

       {

         PrintError("Extract Error");

@@ -919,5 +951,6 @@
       }

     }

   }

+

   return 0;

 }

diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc
index 97086e9..0ca293c 100644
--- a/CPP/7zip/UI/Client7z/resource.rc
+++ b/CPP/7zip/UI/Client7z/resource.rc
@@ -1,3 +1,3 @@
-#include "../../../../C/7zVersion.rc"

+#include "../../MyVersionInfo.rc"

 

 MY_VERSION_INFO_APP("7-Zip client", "7zcl")

diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 9e0eab0..ad48b5e 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -59,17 +59,12 @@
   return *end == 0;

 }

 

-static void AddNewLine(UString &s)

-{

-  s += L'\n';

-}

-

 CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u)

 {

   (*this) += MultiByteToUnicodeString(a);

   if (u)

   {

-    AddNewLine(*this);

+    this->Add_LF();

     (*this) += u;

   }

 }

@@ -82,37 +77,53 @@
   kHelp1 = 0,

   kHelp2,

   kHelp3,

+  

   kDisableHeaders,

   kDisablePercents,

-  kArchiveType,

+  kShowTime,

+  kLogLevel,

+

+  kOutStream,

+  kErrStream,

+  kPercentStream,

+

   kYes,

-  #ifndef _NO_CRYPTO

-  kPassword,

-  #endif

+

+  kShowDialog,

+  kOverwrite,

+

+  kArchiveType,

+  kExcludedArcType,

+

   kProperty,

   kOutputDir,

   kWorkingDir,

+  

   kInclude,

   kExclude,

   kArInclude,

   kArExclude,

   kNoArName,

+

   kUpdate,

   kVolume,

   kRecursed,

+

+  kAffinity,

   kSfx,

+  kEmail,

+  kHash,

+ 

   kStdIn,

   kStdOut,

-  kOverwrite,

-  kEmail,

-  kShowDialog,

+

   kLargePages,

   kListfileCharSet,

   kConsoleCharSet,

   kTechMode,

+  

   kShareForWrite,

   kCaseSensitive,

-  kHash,

   kArcNameMode,

 

   kDisableWildcardParsing,

@@ -127,8 +138,11 @@
   kWriteToAltStreamIfColon,

 

   kDeleteAfterCompressing,

-  kSetArcMTime,

-  kExcludedArcType

+  kSetArcMTime

+

+  #ifndef _NO_CRYPTO

+  , kPassword

+  #endif

 };

 

 }

@@ -139,6 +153,8 @@
 

 static const char *k_ArcNameMode_PostCharSet = "sea";

 

+static const char *k_Stream_PostCharSet = "012";

+

 static inline const EArcNameMode ParseArcNameMode(int postCharIndex)

 {

   switch (postCharIndex)

@@ -166,7 +182,7 @@
 

 static const char *kOverwritePostCharSet = "asut";

 

-NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =

+static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =

 {

   NExtract::NOverwriteMode::kOverwrite,

   NExtract::NOverwriteMode::kSkip,

@@ -179,37 +195,53 @@
   { "?" },

   { "h" },

   { "-help" },

+  

   { "ba" },

   { "bd" },

-  { "t",  NSwitchType::kString, false, 1 },

+  { "bt" },

+  { "bb", NSwitchType::kString, false, 0 },

+

+  { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },

+  { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },

+  { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },

+  

   { "y" },

-  #ifndef _NO_CRYPTO

-  { "p",  NSwitchType::kString },

-  #endif

+  

+  { "ad" },

+  { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet},

+

+  { "t",  NSwitchType::kString, false, 1 },

+  { "stx", NSwitchType::kString, true, 1 },

+  

   { "m",  NSwitchType::kString, true, 1 },

   { "o",  NSwitchType::kString, false, 1 },

   { "w",  NSwitchType::kString },

+

   { "i",  NSwitchType::kString, true, kSomeCludePostStringMinSize},

   { "x",  NSwitchType::kString, true, kSomeCludePostStringMinSize},

   { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize},

   { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize},

   { "an" },

+  

   { "u",  NSwitchType::kString, true, 1},

   { "v",  NSwitchType::kString, true, 1},

   { "r",  NSwitchType::kChar, false, 0, kRecursedPostCharSet },

+  

+  { "stm", NSwitchType::kString },

   { "sfx", NSwitchType::kString },

+  { "seml", NSwitchType::kString, false, 0},

+  { "scrc", NSwitchType::kString, true, 0 },

+  

   { "si", NSwitchType::kString },

   { "so" },

-  { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet},

-  { "seml", NSwitchType::kString, false, 0},

-  { "ad" },

+

   { "slp", NSwitchType::kMinus },

   { "scs", NSwitchType::kString },

   { "scc", NSwitchType::kString },

   { "slt" },

+

   { "ssw" },

   { "ssc", NSwitchType::kMinus },

-  { "scrc", NSwitchType::kString, true, 0 },

   { "sa",  NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },

   

   { "spd" },

@@ -220,26 +252,26 @@
   { "snl", NSwitchType::kMinus },

   { "sni" },

   { "sns", NSwitchType::kMinus },

-  

   { "snr" },

   { "snc" },

   

   { "sdel" },

-  { "stl" },

-  { "stx", NSwitchType::kString, true, 1 }

+  { "stl" }

+

+  #ifndef _NO_CRYPTO

+  , { "p",  NSwitchType::kString }

+  #endif

 };

 

 static const wchar_t *kUniversalWildcard = L"*";

-static const int kMinNonSwitchWords = 1;

-static const int kCommandIndex = 0;

+static const unsigned kMinNonSwitchWords = 1;

+static const unsigned kCommandIndex = 0;

 

 // static const char *kUserErrorMessage  = "Incorrect command line";

 static const char *kCannotFindListFile = "Cannot find listfile";

 static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";

-// static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile";

-// static const char *kIncorrectWildcardInCommandLine  = "Incorrect wildcard in command line";

 static const char *kTerminalOutError = "I won't write compressed data to a terminal";

-static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";

+static const char *kSameTerminalError = "I won't write data and program's messages to same stream";

 static const char *kEmptyFilePath = "Empty file path";

 static const char *kCannotFindArchive = "Cannot find archive";

 

@@ -350,13 +382,13 @@
   {

     UString val;

     val += pair.OldName;

-    AddNewLine(val);

+    val.Add_LF();

     val += pair.NewName;

-    AddNewLine(val);

+    val.Add_LF();

     if (type == NRecursedType::kRecursed)

-      val += L"-r";

-    else if (type == NRecursedType::kRecursed)

-      val += L"-r0";

+      val.AddAscii("-r");

+    else if (type == NRecursedType::kWildcardOnlyRecursed)

+      val.AddAscii("-r0");

     throw CArcCmdLineException("Unsupported rename command:", val);

   }

 }

@@ -411,7 +443,7 @@
     else if (renamePairs)

     {

       if (oldIndex == -1)

-        oldIndex = startIndex;

+        oldIndex = i;

       else

       {

         // NRecursedType::EEnum type is used for global wildcard (-i! switches)

@@ -461,7 +493,7 @@
   if (pos2 < 0)

     return k_IncorrectMapCommand;

 

-  CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1));

+  CEventSetEnd eventSetEnd((const wchar_t *)s + ((unsigned)pos2 + 1));

   s.DeleteFrom(pos2);

   UInt32 size;

   if (!StringToUInt32(s.Ptr(pos + 1), size)

@@ -561,7 +593,7 @@
     #endif

     else

     {

-      errorMessage = "Incorrect wildcarc type marker";

+      errorMessage = "Incorrect wildcard type marker";

       break;

     }

   }

@@ -579,8 +611,10 @@
     return;

   NFind::CFileInfo fi;

   const FString path = us2fs(prefix + name);

+  #ifndef UNDER_CE

   if (NFile::NName::IsDevicePath(path))

     return;

+  #endif

   if (fi.Find(path))

     name = fs2us(fi.Name);

 }

@@ -617,7 +651,7 @@
     for (unsigned j = i + 1; j < node.SubNodes.Size();)

     {

       const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];

-      if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name))

+      if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))

       {

         nextNode1.IncludeItems += nextNode2.IncludeItems;

         nextNode1.ExcludeItems += nextNode2.ExcludeItems;

@@ -685,9 +719,9 @@
     c = command[i];

     if (c < '0' || c >= '0' + kNumUpdatePairActions)

       return false;

-    int actionPos = c - '0';

-    actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);

-    if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)

+    unsigned actionPos = c - '0';

+    actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);

+    if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos)

       return false;

     i++;

   }

@@ -817,6 +851,12 @@
 

 CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {}

 

+static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res)

+{

+  if (sw.ThereIs)

+    res = sw.PostCharIndex;

+}

+

 void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,

     CArcCmdLineOptions &options)

 {

@@ -826,10 +866,40 @@
   options.IsInTerminal = MY_IS_TERMINAL(stdin);

   options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);

   options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);

+

+  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;

+

   options.StdInMode = parser[NKey::kStdIn].ThereIs;

   options.StdOutMode = parser[NKey::kStdOut].ThereIs;

   options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;

-  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;

+  options.TechMode = parser[NKey::kTechMode].ThereIs;

+  options.ShowTime = parser[NKey::kShowTime].ThereIs;

+

+  if (parser[NKey::kDisablePercents].ThereIs

+      || options.StdOutMode

+      || !options.IsStdOutTerminal)

+    options.Number_for_Percents = k_OutStream_disabled;

+

+  if (options.StdOutMode)

+    options.Number_for_Out = k_OutStream_disabled;

+

+  SetStreamMode(parser[NKey::kOutStream], options.Number_for_Out);

+  SetStreamMode(parser[NKey::kErrStream], options.Number_for_Errors);

+  SetStreamMode(parser[NKey::kPercentStream], options.Number_for_Percents);

+

+  if (parser[NKey::kLogLevel].ThereIs)

+  {

+    const UString &s = parser[NKey::kLogLevel].PostStrings[0];

+    if (s.IsEmpty())

+      options.LogLevel = 1;

+    else

+    {

+      UInt32 v;

+      if (!StringToUInt32(s, v))

+        throw CArcCmdLineException("Unsupported switch postfix -bb", s);

+      options.LogLevel = (unsigned)v;

+    }

+  }

 

   if (parser[NKey::kCaseSensitive].ThereIs)

   {

@@ -838,12 +908,37 @@
     options.CaseSensitive = g_CaseSensitive;

   }

 

-  #ifdef _WIN32

   options.LargePages = false;

   if (parser[NKey::kLargePages].ThereIs)

-  {

     options.LargePages = !parser[NKey::kLargePages].WithMinus;

+

+

+  #ifndef UNDER_CE

+

+  if (parser[NKey::kAffinity].ThereIs)

+  {

+    const UString &s = parser[NKey::kAffinity].PostStrings[0];

+    if (!s.IsEmpty())

+    {

+      UInt32 v = 0;

+      AString a;

+      a.SetFromWStr_if_Ascii(s);

+      if (!a.IsEmpty())

+      {

+        const char *end;

+        v = ConvertHexStringToUInt32(a, &end);

+        if (*end != 0)

+          a.Empty();

+      }

+      if (a.IsEmpty())

+        throw CArcCmdLineException("Unsupported switch postfix -stm", s);

+      

+      #ifdef _WIN32

+      SetProcessAffinityMask(GetCurrentProcess(), v);

+      #endif

+    }

   }

+

   #endif

 }

 

@@ -855,7 +950,7 @@
 

 static const unsigned kNumByteOnlyCodePages = 3;

 

-static CCodePagePair g_CodePagePairs[] =

+static const CCodePagePair g_CodePagePairs[] =

 {

   { "utf-8", CP_UTF8 },

   { "win", CP_ACP },

@@ -864,7 +959,7 @@
   { "utf-16be", MY__CP_UTF16BE }

 };

 

-static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex,

+static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex,

     bool byteOnlyCodePages, Int32 defaultVal)

 {

   if (!parser[keyIndex].ThereIs)

@@ -887,29 +982,26 @@
   }

 }

 

-void EnumerateDirItemsAndSort(

-    bool storeAltStreams,

+HRESULT EnumerateDirItemsAndSort(

     NWildcard::CCensor &censor,

     NWildcard::ECensorPathMode censorPathMode,

     const UString &addPathPrefix,

     UStringVector &sortedPaths,

-    UStringVector &sortedFullPaths)

+    UStringVector &sortedFullPaths,

+    CDirItemsStat &st,

+    IDirItemsCallback *callback)

 {

-  UStringVector paths;

+  FStringVector paths;

+  

   {

     CDirItems dirItems;

+    dirItems.Callback = callback;

     {

-      dirItems.ScanAltStreams = storeAltStreams;

-      HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL);

-      if (res != S_OK || dirItems.ErrorPaths.Size() > 0)

-      {

-        UString errorPath;

-        if (dirItems.ErrorPaths.Size() > 0)

-          errorPath = fs2us(dirItems.ErrorPaths[0]);

-        throw CArcCmdLineException(kCannotFindArchive,

-            dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL);

-      }

+      HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);

+      st = dirItems.Stat;

+      RINOK(res);

     }

+  

     FOR_VECTOR (i, dirItems.Items)

     {

       const CDirItem &dirItem = dirItems.Items[i];

@@ -924,24 +1016,29 @@
   UStringVector fullPaths;

   

   unsigned i;

+  

   for (i = 0; i < paths.Size(); i++)

   {

     FString fullPath;

-    NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath);

+    NFile::NDir::MyGetFullPathName(paths[i], fullPath);

     fullPaths.Add(fs2us(fullPath));

   }

+  

   CUIntVector indices;

   SortFileNames(fullPaths, indices);

   sortedPaths.ClearAndReserve(indices.Size());

   sortedFullPaths.ClearAndReserve(indices.Size());

+

   for (i = 0; i < indices.Size(); i++)

   {

     unsigned index = indices[i];

-    sortedPaths.AddInReserved(paths[index]);

+    sortedPaths.AddInReserved(fs2us(paths[index]));

     sortedFullPaths.AddInReserved(fullPaths[index]);

     if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)

       throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]);

   }

+

+  return S_OK;

 }

 

 static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)

@@ -954,14 +1051,13 @@
 void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)

 {

   const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

-  int numNonSwitchStrings = nonSwitchStrings.Size();

+  unsigned numNonSwitchStrings = nonSwitchStrings.Size();

   if (numNonSwitchStrings < kMinNonSwitchWords)

-    throw CArcCmdLineException("The command must be spcified");

+    throw CArcCmdLineException("The command must be specified");

 

   if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))

     throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);

 

-  options.TechMode = parser[NKey::kTechMode].ThereIs;

   if (parser[NKey::kHash].ThereIs)

     options.HashMethods = parser[NKey::kHash].PostStrings;

   

@@ -1012,7 +1108,7 @@
     AddSwitchWildcardsToCensor(options.Censor,

         parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage);

  

-  int curCommandIndex = kCommandIndex + 1;

+  unsigned curCommandIndex = kCommandIndex + 1;

   bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&

       options.Command.CommandType != NCommandType::kBenchmark &&

       options.Command.CommandType != NCommandType::kInfo &&

@@ -1035,6 +1131,9 @@
     options.ArchiveName = nonSwitchStrings[curCommandIndex++];

     if (options.ArchiveName.IsEmpty())

       throw CArcCmdLineException("Archive name cannot by empty");

+    #ifdef _WIN32

+    // options.ArchiveName.Replace(L'/', WCHAR_PATH_SEPARATOR);

+    #endif

   }

 

   AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL,

@@ -1060,15 +1159,6 @@
 

   SetMethodOptions(parser, options.Properties);

 

-  options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

-  

-  if (options.EnablePercents)

-  {

-    if ((options.StdOutMode && !options.IsStdErrTerminal) ||

-      (!options.StdOutMode && !options.IsStdOutTerminal))

-      options.EnablePercents = false;

-  }

-

   if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue();

 

   SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);

@@ -1106,7 +1196,7 @@
     if (!options.Censor.AllAreRelative())

       throw CArcCmdLineException("Cannot use absolute pathnames for this command");

 

-    NWildcard::CCensor arcCensor;

+    NWildcard::CCensor &arcCensor = options.arcCensor;

 

     if (parser[NKey::kArInclude].ThereIs)

       AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage);

@@ -1125,26 +1215,30 @@
     arcCensor.ExtendExclude();

 

     if (options.StdInMode)

-    {

-      UString arcName = parser[NKey::kStdIn].PostStrings.Front();

-      options.ArchivePathsSorted.Add(arcName);

-      options.ArchivePathsFullSorted.Add(arcName);

-    }

-    else

-    {

-      EnumerateDirItemsAndSort(

-          false,     // scanAltStreams

-          arcCensor,

-          NWildcard::k_RelatPath,

-          UString(), // addPathPrefix

-          options.ArchivePathsSorted,

-          options.ArchivePathsFullSorted);

-    }

+      options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front();

     

     if (isExtractGroupCommand)

     {

-      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)

-        throw CArcCmdLineException(kSameTerminalError);

+      if (options.StdOutMode)

+      {

+        if (

+                  options.Number_for_Percents == k_OutStream_stdout

+            // || options.Number_for_Out      == k_OutStream_stdout

+            // || options.Number_for_Errors   == k_OutStream_stdout

+            ||

+            (

+              (options.IsStdOutTerminal && options.IsStdErrTerminal)

+              &&

+              (

+                      options.Number_for_Percents != k_OutStream_disabled

+                // || options.Number_for_Out      != k_OutStream_disabled

+                // || options.Number_for_Errors   != k_OutStream_disabled

+              )

+            )

+           )

+          throw CArcCmdLineException(kSameTerminalError);

+      }

+      

       if (parser[NKey::kOutputDir].ThereIs)

       {

         eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);

@@ -1154,7 +1248,7 @@
       eo.OverwriteMode = NExtract::NOverwriteMode::kAsk;

       if (parser[NKey::kOverwrite].ThereIs)

       {

-        eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];

+        eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex];

         eo.OverwriteMode_Force = true;

       }

       else if (options.YesToAll)

@@ -1217,8 +1311,18 @@
 

     if (updateOptions.StdOutMode && updateOptions.EMailMode)

       throw CArcCmdLineException("stdout mode and email mode cannot be combined");

-    if (updateOptions.StdOutMode && options.IsStdOutTerminal)

-      throw CArcCmdLineException(kTerminalOutError);

+    

+    if (updateOptions.StdOutMode)

+    {

+      if (options.IsStdOutTerminal)

+        throw CArcCmdLineException(kTerminalOutError);

+      

+      if (options.Number_for_Percents == k_OutStream_stdout

+          || options.Number_for_Out == k_OutStream_stdout

+          || options.Number_for_Errors == k_OutStream_stdout)

+        throw CArcCmdLineException(kSameTerminalError);

+    }

+    

     if (updateOptions.StdInMode)

       updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

 

@@ -1253,5 +1357,5 @@
   {

   }

   else

-    throw 9815676711;

+    throw 20150919;

 }

diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 3f4186f..a91df0c 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -40,13 +40,18 @@
   NExtract::NPathMode::EEnum GetPathMode() const;

 };

 

+enum

+{

+  k_OutStream_disabled = 0,

+  k_OutStream_stdout = 1,

+  k_OutStream_stderr = 2

+};

+

 struct CArcCmdLineOptions

 {

   bool HelpMode;

 

-  #ifdef _WIN32

   bool LargePages;

-  #endif

   bool CaseSensitiveChange;

   bool CaseSensitive;

 

@@ -70,12 +75,16 @@
   #endif

 

   bool TechMode;

+  bool ShowTime;

   

   UStringVector HashMethods;

 

   bool AppendName;

-  UStringVector ArchivePathsSorted;

-  UStringVector ArchivePathsFullSorted;

+  // UStringVector ArchivePathsSorted;

+  // UStringVector ArchivePathsFullSorted;

+  NWildcard::CCensor arcCensor;

+  UString ArcName_for_StdInMode;

+

   CObjectVector<CProperty> Properties;

 

   CExtractOptionsBase ExtractOptions;

@@ -89,17 +98,32 @@
   CHashOptions HashOptions;

   UString ArcType;

   UStringVector ExcludedArcTypes;

-  bool EnablePercents;

+  

+  unsigned Number_for_Out;

+  unsigned Number_for_Errors;

+  unsigned Number_for_Percents;

+  unsigned LogLevel;

+

+  // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; }

 

   // Benchmark

   UInt32 NumIterations;

 

   CArcCmdLineOptions():

+      LargePages(false),

+      CaseSensitiveChange(false),

+      CaseSensitive(false),

+

       StdInMode(false),

       StdOutMode(false),

-      CaseSensitiveChange(false),

-      CaseSensitive(false)

-      {};

+

+      Number_for_Out(k_OutStream_stdout),

+      Number_for_Errors(k_OutStream_stderr),

+      Number_for_Percents(k_OutStream_stdout),

+

+      LogLevel(0)

+  {

+  };

 };

 

 class CArcCmdLineParser

@@ -111,12 +135,13 @@
   void Parse2(CArcCmdLineOptions &options);

 };

 

-void EnumerateDirItemsAndSort(

-    bool storeAltStreams,

+HRESULT EnumerateDirItemsAndSort(

     NWildcard::CCensor &censor,

     NWildcard::ECensorPathMode pathMode,

     const UString &addPathPrefix,

     UStringVector &sortedPaths,

-    UStringVector &sortedFullPaths);

+    UStringVector &sortedFullPaths,

+    CDirItemsStat &st,

+    IDirItemsCallback *callback);

 

 #endif

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 315945b..39e9653 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -5,10 +5,14 @@
 #undef sprintf

 #undef printf

 

+#include "../../../../C/Alloc.h"

+

 #include "../../../Common/ComTry.h"

+#include "../../../Common/IntToString.h"

 #include "../../../Common/StringConvert.h"

 #include "../../../Common/Wildcard.h"

 

+#include "../../../Windows/ErrorMsg.h"

 #include "../../../Windows/FileDir.h"

 #include "../../../Windows/FileFind.h"

 #include "../../../Windows/FileName.h"

@@ -21,6 +25,7 @@
 #endif

 

 #include "../../Common/FilePathAutoRename.h"

+// #include "../../Common/StreamUtils.h"

 

 #include "../Common/ExtractingFilePath.h"

 #include "../Common/PropIDUtils.h"

@@ -84,7 +89,7 @@
   return MyCompare(INode, a.INode);

 }

 

-HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)

+static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)

 {

   h.INode = 0;

   h.StreamId = (UInt64)(Int64)-1;

@@ -128,9 +133,16 @@
     {

       CHardLinkNode h;

       bool defined;

-      RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined));

+      UInt32 realIndex = realIndices ? (*realIndices)[i] : i;

+

+      RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined));

       if (defined)

-        hardIDs.Add(h);

+      {

+        bool isAltStream = false;

+        RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream));

+        if (!isAltStream)

+          hardIDs.Add(h);

+      }

     }

   }

   

@@ -181,7 +193,7 @@
     IFolderArchiveExtractCallback *extractCallback2,

     bool stdOutMode, bool testMode,

     const FString &directoryPath,

-    const UStringVector &removePathParts,

+    const UStringVector &removePathParts, bool removePartsForAltStreams,

     UInt64 packSize)

 {

   _extractedFolderPaths.Clear();

@@ -191,17 +203,28 @@
   _hardLinks.Clear();

   #endif

 

+  #ifdef SUPPORT_ALT_STREAMS

+  _renamedFiles.Clear();

+  #endif

+

   _ntOptions = ntOptions;

   _wildcardCensor = wildcardCensor;

 

   _stdOutMode = stdOutMode;

   _testMode = testMode;

-  _unpTotal = 1;

+  

+  // _progressTotal = 0;

+  // _progressTotal_Defined = false;

+  

   _packTotal = packSize;

+  _progressTotal = packSize;

+  _progressTotal_Defined = true;

 

   _extractCallback2 = extractCallback2;

   _compressProgress.Release();

   _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);

+  _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage);

+  _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);

 

   #ifndef _SFX

 

@@ -221,19 +244,31 @@
   LocalProgressSpec->SendProgress = false;

  

   _removePathParts = removePathParts;

+  _removePartsForAltStreams = removePartsForAltStreams;

+

+  #ifndef _SFX

   _baseParentFolder = (UInt32)(Int32)-1;

   _use_baseParentFolder_mode = false;

+  #endif

 

   _arc = arc;

-  _directoryPath = directoryPath;

-  NName::NormalizeDirPathPrefix(_directoryPath);

-  NDir::MyGetFullPathName(directoryPath, _directoryPathFull);

+  _dirPathPrefix = directoryPath;

+  _dirPathPrefix_Full = directoryPath;

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  if (!NName::IsAltPathPrefix(_dirPathPrefix))

+  #endif

+  {

+    NName::NormalizeDirPathPrefix(_dirPathPrefix);

+    NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full);

+    NName::NormalizeDirPathPrefix(_dirPathPrefix_Full);

+  }

 }

 

 STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)

 {

   COM_TRY_BEGIN

-  _unpTotal = size;

+  _progressTotal = size;

+  _progressTotal_Defined = true;

   if (!_multiArchives && _extractCallback2)

     return _extractCallback2->SetTotal(size);

   return S_OK;

@@ -262,18 +297,20 @@
 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)

 {

   COM_TRY_BEGIN

+  

   if (!_extractCallback2)

     return S_OK;

 

+  UInt64 packCur;

   if (_multiArchives)

   {

-    if (completeValue != NULL)

-    {

-      UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);

-      return _extractCallback2->SetCompleted(&packCur);

-    }

+    packCur = LocalProgressSpec->InSize;

+    if (completeValue && _progressTotal_Defined)

+      packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);

+    completeValue = &packCur;

   }

   return _extractCallback2->SetCompleted(completeValue);

+ 

   COM_TRY_END

 }

 

@@ -284,13 +321,6 @@
   COM_TRY_END

 }

 

-#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')

-

-static inline bool IsDriveName(const UString &s)

-{

-  return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]);

-}

-

 void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)

 {

   bool isAbsPath = false;

@@ -300,10 +330,10 @@
     const UString &s = dirPathParts[0];

     if (s.IsEmpty())

       isAbsPath = true;

-    #ifdef _WIN32

+    #if defined(_WIN32) && !defined(UNDER_CE)

     else

     {

-      if (dirPathParts.Size() > 1 && IsDriveName(s))

+      if (NName::IsDrivePath2(s))

         isAbsPath = true;

     }

     #endif

@@ -312,17 +342,17 @@
   if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)

     fullPath.Empty();

   else

-    fullPath = _directoryPath;

+    fullPath = _dirPathPrefix;

 

   FOR_VECTOR (i, dirPathParts)

   {

-    if (i > 0)

-      fullPath += FCHAR_PATH_SEPARATOR;

+    if (i != 0)

+      fullPath.Add_PathSepar();

     const UString &s = dirPathParts[i];

     fullPath += us2fs(s);

-    #ifdef _WIN32

+    #if defined(_WIN32) && !defined(UNDER_CE)

     if (_pathMode == NExtract::NPathMode::kAbsPaths)

-      if (i == 0 && IsDriveName(s))

+      if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))

         continue;

     #endif

     CreateDir(fullPath);

@@ -349,32 +379,57 @@
   return _arc->GetItemSize(_index, _curSize, _curSizeDefined);

 }

 

+static void AddPathToMessage(UString &s, const FString &path)

+{

+  s.AddAscii(" : ");

+  s += fs2us(path);

+}

+

 HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)

 {

-  return _extractCallback2->MessageError(

-      UString(L"ERROR: ") +

-      GetUnicodeString(message) + L": " + fs2us(path));

+  UString s;

+  s.AddAscii(message);

+  AddPathToMessage(s, path);

+  return _extractCallback2->MessageError(s);

+}

+

+HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)

+{

+  DWORD errorCode = GetLastError();

+  UString s;

+  s.AddAscii(message);

+  if (errorCode != 0)

+  {

+    s.AddAscii(" : ");

+    s += NError::MyFormatMessage(errorCode);

+  }

+  AddPathToMessage(s, path);

+  return _extractCallback2->MessageError(s);

 }

 

 HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)

 {

-  return _extractCallback2->MessageError(

-      UString(L"ERROR: ") +

-      GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2));

+  UString s;

+  s.AddAscii(message);

+  AddPathToMessage(s, path1);

+  AddPathToMessage(s, path2);

+  return _extractCallback2->MessageError(s);

 }

 

 #ifndef _SFX

 

 STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)

 {

+  /*

   if (propID == kpidName)

   {

     COM_TRY_BEGIN

-    NCOM::CPropVariant prop = Name.Ptr();

+    NCOM::CPropVariant prop = Name;

     prop.Detach(value);

     return S_OK;

     COM_TRY_END

   }

+  */

   return Arc->Archive->GetProperty(IndexInArc, propID, value);

 }

 

@@ -388,46 +443,164 @@
   UString s = src;

   if (!s.IsEmpty())

   {

-    if (s.Back() == WCHAR_PATH_SEPARATOR)

+    if (IsPathSepar(s.Back()))

       s.DeleteBack();

-    int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);

+    int pos = s.ReverseFind_PathSepar();

     s.DeleteFrom(pos + 1);

   }

   return s;

 }

 

-static bool IsSafePath(const UString &path)

+#endif

+

+

+bool IsSafePath(const UString &path)

 {

+  if (NName::IsAbsolutePath(path))

+    return false;

+

   UStringVector parts;

   SplitPathToParts(path, parts);

-  int level = 0;

-  FOR_VECTOR(i, parts)

+  unsigned level = 0;

+  

+  FOR_VECTOR (i, parts)

   {

     const UString &s = parts[i];

     if (s.IsEmpty())

+    {

+      if (i == 0)

+        return false;

       continue;

+    }

     if (s == L".")

       continue;

     if (s == L"..")

     {

-      if (level <= 0)

+      if (level == 0)

         return false;

       level--;

     }

     else

       level++;

   }

+  

   return level > 0;

 }

 

-#endif

 

+bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include)

+{

+  bool found = false;

+  

+  if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include))

+  {

+    if (!include)

+      return true;

+    

+    #ifdef SUPPORT_ALT_STREAMS

+    if (!item.IsAltStream)

+      return true;

+    #endif

+    

+    found = true;

+  }

+  

+  #ifdef SUPPORT_ALT_STREAMS

+

+  if (!item.IsAltStream)

+    return false;

+  

+  UStringVector pathParts2 = item.PathParts;

+  if (pathParts2.IsEmpty())

+    pathParts2.AddNew();

+  UString &back = pathParts2.Back();

+  back += L':';

+  back += item.AltStreamName;

+  bool include2;

+  

+  if (node.CheckPathVect(pathParts2,

+      true, // isFile,

+      include2))

+  {

+    include = include2;

+    return true;

+  }

+

+  #endif

+

+  return found;

+}

+

+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item)

+{

+  bool include;

+  if (CensorNode_CheckPath2(node, item, include))

+    return include;

+  return false;

+}

+

+static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)

+{

+  FString s = prefix;

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back()))

+  {

+    if (!NName::IsDriveRootPath_SuperAllowed(prefix))

+      s.DeleteBack();

+  }

+  #endif

+  s += 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)

@@ -438,19 +611,40 @@
   _outFileStream.Release();

 

   _encrypted = false;

+  _position = 0;

   _isSplit = false;

-  _isAltStream = false;

+  

   _curSize = 0;

   _curSizeDefined = false;

   _index = index;

 

-  UString fullPath;

+  _diskFilePath.Empty();

+

+  // _fi.Clear();

+

+  #ifdef SUPPORT_LINKS

+  // _CopyFile_Path.Empty();

+  linkPath.Empty();

+  #endif

 

   IInArchive *archive = _arc->Archive;

-  RINOK(_arc->GetItemPath(index, fullPath));

-  RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir));

 

-  _filePath = fullPath;

+  #ifndef _SFX

+  _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;

+  if (_use_baseParentFolder_mode)

+  {

+    _item._baseParentFolder = _baseParentFolder;

+    if (_pathMode == NExtract::NPathMode::kFullPaths ||

+        _pathMode == NExtract::NPathMode::kAbsPaths)

+      _item._baseParentFolder = -1;

+  }

+  #endif

+

+  #ifdef SUPPORT_ALT_STREAMS

+  _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;

+  #endif

+

+  RINOK(_arc->GetItem(index, _item));

 

   {

     NCOM::CPropVariant prop;

@@ -466,46 +660,56 @@
 

   #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;

-      linkPath = prop.bstrVal;

-      isRelative = false; // TAR: hard links are from root folder of archive

+      // isCopyLink = false;

+      isRelative = false; // RAR5, TAR: hard links are from root folder of archive

+      linkPath.SetFromBstr(prop.bstrVal);

     }

-    else if (prop.vt == VT_EMPTY)

-    {

-      // linkPath.Empty();

-    }

-    else

+    else if (prop.vt != VT_EMPTY)

       return E_FAIL;

   }

+  

+  /*

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetProperty(index, kpidCopyLink, &prop));

+    if (prop.vt == VT_BSTR)

+    {

+      isHardLink = false;

+      isCopyLink = true;

+      isRelative = false; // RAR5: copy links are from root folder of archive

+      linkPath.SetFromBstr(prop.bstrVal);

+    }

+    else if (prop.vt != VT_EMPTY)

+      return E_FAIL;

+  }

+  */

+

   {

     NCOM::CPropVariant prop;

     RINOK(archive->GetProperty(index, kpidSymLink, &prop));

     if (prop.vt == VT_BSTR)

     {

       isHardLink = false;

-      linkPath = prop.bstrVal;

-      isRelative = true; // TAR: symbolic links are relative

+      // isCopyLink = false;

+      isRelative = true; // RAR5, TAR: symbolic links can be relative

+      linkPath.SetFromBstr(prop.bstrVal);

     }

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

@@ -513,7 +717,9 @@
     const void *data;

     UInt32 dataSize;

     UInt32 propType;

+    

     _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);

+    

     if (dataSize != 0)

     {

       if (propType != NPropDataType::kRaw)

@@ -524,11 +730,12 @@
       if (isOkReparse)

       {

         isHardLink = false;

+        // isCopyLink = false;

         linkPath = reparse.GetPath();

         isJunction = reparse.IsMountPoint();

         isRelative = reparse.IsRelative();

         #ifndef _WIN32

-        linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', );

+        linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);

         #endif

       }

     }

@@ -537,8 +744,15 @@
   if (!linkPath.IsEmpty())

   {

     #ifdef _WIN32

-    linkPath.Replace('/', WCHAR_PATH_SEPARATOR);

+    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))

@@ -566,7 +780,7 @@
     }

     if (!badPrefix)

       pathParts.DeleteFrontal(_removePathParts.Size());

-    linkPath = MakePathNameFromParts(pathParts);

+    linkPath = MakePathFromParts(pathParts);

   }

 

   #endif

@@ -575,56 +789,97 @@
 

   RINOK(GetUnpackSize());

 

-  RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream));

-

-  if (!_ntOptions.AltStreams.Val && _isAltStream)

+  #ifdef SUPPORT_ALT_STREAMS

+  

+  if (!_ntOptions.AltStreams.Val && _item.IsAltStream)

     return S_OK;

 

+  #endif

+

+

+  UStringVector &pathParts = _item.PathParts;

+

   if (_wildcardCensor)

   {

-    if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir))

+    if (!CensorNode_CheckPath(*_wildcardCensor, _item))

       return S_OK;

   }

 

-

-  UStringVector pathParts;

-

+  #ifndef _SFX

   if (_use_baseParentFolder_mode)

   {

-    int baseParent = _baseParentFolder;

-    if (_pathMode == NExtract::NPathMode::kFullPaths ||

-        _pathMode == NExtract::NPathMode::kAbsPaths)

-      baseParent = -1;

-    RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts));

-    if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty())

-      pathParts.DeleteFrontal(pathParts.Size() - 1);

+    if (!pathParts.IsEmpty())

+    {

+      unsigned numRemovePathParts = 0;

+      

+      #ifdef SUPPORT_ALT_STREAMS

+      if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream)

+        numRemovePathParts = pathParts.Size();

+      else

+      #endif

+      if (_pathMode == NExtract::NPathMode::kNoPaths ||

+          _pathMode == NExtract::NPathMode::kNoPathsAlt)

+        numRemovePathParts = pathParts.Size() - 1;

+      pathParts.DeleteFrontal(numRemovePathParts);

+    }

   }

   else

+  #endif

   {

-    SplitPathToParts(fullPath, pathParts);

-    

     if (pathParts.IsEmpty())

-      return E_FAIL;

+    {

+      if (_item.IsDir)

+        return S_OK;

+      /*

+      #ifdef SUPPORT_ALT_STREAMS

+      if (!_item.IsAltStream)

+      #endif

+        return E_FAIL;

+      */

+    }

+

     unsigned numRemovePathParts = 0;

     

     switch (_pathMode)

     {

+      case NExtract::NPathMode::kFullPaths:

       case NExtract::NPathMode::kCurPaths:

       {

+        if (_removePathParts.IsEmpty())

+          break;

         bool badPrefix = false;

-        if (pathParts.Size() <= _removePathParts.Size())

+        

+        if (pathParts.Size() < _removePathParts.Size())

           badPrefix = true;

         else

         {

+          if (pathParts.Size() == _removePathParts.Size())

+          {

+            if (_removePartsForAltStreams)

+            {

+              #ifdef SUPPORT_ALT_STREAMS

+              if (!_item.IsAltStream)

+              #endif

+                badPrefix = true;

+            }

+            else

+            {

+              if (!_item.MainIsDir)

+                badPrefix = true;

+            }

+          }

+          

+          if (!badPrefix)

           FOR_VECTOR (i, _removePathParts)

           {

-            if (!_removePathParts[i].IsEqualToNoCase(pathParts[i]))

+            if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)

             {

               badPrefix = true;

               break;

             }

           }

         }

+        

         if (badPrefix)

         {

           if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)

@@ -634,9 +889,22 @@
           numRemovePathParts = _removePathParts.Size();

         break;

       }

+      

       case NExtract::NPathMode::kNoPaths:

       {

-        numRemovePathParts = pathParts.Size() - 1;

+        if (!pathParts.IsEmpty())

+          numRemovePathParts = pathParts.Size() - 1;

+        break;

+      }

+      case NExtract::NPathMode::kNoPathsAlt:

+      {

+        #ifdef SUPPORT_ALT_STREAMS

+        if (_item.IsAltStream)

+          numRemovePathParts = pathParts.Size();

+        else

+        #endif

+        if (!pathParts.IsEmpty())

+          numRemovePathParts = pathParts.Size() - 1;

         break;

       }

       /*

@@ -660,9 +928,18 @@
     }

     GetProp_Spec->Arc = _arc;

     GetProp_Spec->IndexInArc = index;

-    GetProp_Spec->Name = MakePathNameFromParts(pathParts);

+    UString name = MakePathFromParts(pathParts);

+    

+    #ifdef SUPPORT_ALT_STREAMS

+    if (_item.IsAltStream)

+    {

+      if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))

+        name += L':';

+      name += _item.AltStreamName;

+    }

+    #endif

 

-    return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp);

+    return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp);

   }

 

   #endif

@@ -698,18 +975,44 @@
     bool isAnti = false;

     RINOK(_arc->IsItemAnti(index, isAnti));

 

-    bool replace = _isAltStream ?

-        _ntOptions.ReplaceColonForAltStream :

-        !_ntOptions.WriteToAltStreamIfColon;

+    #ifdef SUPPORT_ALT_STREAMS

+    if (!_item.IsAltStream

+        || !pathParts.IsEmpty()

+        || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))

+    #endif

+      Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, pathParts, _item.MainIsDir);

 

-    if (_pathMode != NExtract::NPathMode::kAbsPaths)

-      MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace);

-    Correct_IfEmptyLastPart(pathParts);

-    UString processedPath = MakePathNameFromParts(pathParts);

+    #ifdef SUPPORT_ALT_STREAMS

+    

+    if (_item.IsAltStream)

+    {

+      UString s = _item.AltStreamName;

+      Correct_AltStream_Name(s);

+      bool needColon = true;

+

+      if (pathParts.IsEmpty())

+      {

+        pathParts.AddNew();

+        if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)

+          needColon = false;

+      }

+      else if (_pathMode == NExtract::NPathMode::kAbsPaths &&

+          NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size())

+        pathParts.AddNew();

+

+      UString &name = pathParts.Back();

+      if (needColon)

+        name += (wchar_t)(_ntOptions.ReplaceColonForAltStream ? L'_' : L':');

+      name += s;

+    }

+    

+    #endif

+

+    UString processedPath = MakePathFromParts(pathParts);

     

     if (!isAnti)

     {

-      if (!_fi.IsDir)

+      if (!_item.IsDir)

       {

         if (!pathParts.IsEmpty())

           pathParts.DeleteBack();

@@ -719,7 +1022,7 @@
       {

         FString fullPathNew;

         CreateComplexDirectory(pathParts, fullPathNew);

-        if (_fi.IsDir)

+        if (_item.IsDir)

         {

           _extractedFolderPaths.Add(fullPathNew);

           _extractedFolderIndices.Add(index);

@@ -733,11 +1036,33 @@
 

 

     FString fullProcessedPath = us2fs(processedPath);

-    if (_pathMode != NExtract::NPathMode::kAbsPaths ||

-        !NName::IsAbsolutePath(processedPath))

-      fullProcessedPath = _directoryPath + fullProcessedPath;

+    if (_pathMode != NExtract::NPathMode::kAbsPaths

+        || !NName::IsAbsolutePath(processedPath))

+    {

+       fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath);

+    }

 

-    if (_fi.IsDir)

+    #ifdef SUPPORT_ALT_STREAMS

+    

+    if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)

+    {

+      int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));

+      if (renIndex >= 0)

+      {

+        const CIndexToPathPair &pair = _renamedFiles[renIndex];

+        fullProcessedPath = pair.Path;

+        fullProcessedPath += (FChar)':';

+        UString s = _item.AltStreamName;

+        Correct_AltStream_Name(s);

+        fullProcessedPath += us2fs(s);

+      }

+    }

+    

+    #endif

+

+    bool isRenamed = false;

+

+    if (_item.IsDir)

     {

       _diskFilePath = fullProcessedPath;

       if (isAnti)

@@ -749,6 +1074,8 @@
     }

     else if (!_isSplit)

     {

+    

+    // ----- Is file (not split) -----

     NFind::CFileInfo fileInfo;

     if (fileInfo.Find(fullProcessedPath))

     {

@@ -758,21 +1085,17 @@
           return S_OK;

         case NExtract::NOverwriteMode::kAsk:

         {

-          int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));

-          #ifdef _WIN32

-          int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));

-          slashPos = MyMax(slashPos, slash1Pos);

-          #endif

+          int slashPos = fullProcessedPath.ReverseFind_PathSepar();

           FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;

 

-          Int32 overwiteResult;

+          Int32 overwriteResult;

           RINOK(_extractCallback2->AskOverwrite(

-              fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath,

+              fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path,

               _fi.MTimeDefined ? &_fi.MTime : NULL,

               _curSizeDefined ? &_curSize : NULL,

-              &overwiteResult))

+              &overwriteResult))

 

-          switch (overwiteResult)

+          switch (overwriteResult)

           {

             case NOverwriteAnswer::kCancel: return E_ABORT;

             case NOverwriteAnswer::kNo: return S_OK;

@@ -792,6 +1115,7 @@
           RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));

           return E_FAIL;

         }

+        isRenamed = true;

       }

       else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)

       {

@@ -801,10 +1125,10 @@
           RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));

           return E_FAIL;

         }

-        // MyMoveFile can raname folders. So it's OK to use it folders too

+        // MyMoveFile can raname folders. So it's OK to use it for folders too

         if (!MyMoveFile(fullProcessedPath, existPath))

         {

-          RINOK(SendMessageError(kCantRenameFile, fullProcessedPath));

+          RINOK(SendMessageError2(kCantRenameFile, existPath, fullProcessedPath));

           return E_FAIL;

         }

       }

@@ -815,18 +1139,45 @@
           // do we need to delete all files in folder?

           if (!RemoveDir(fullProcessedPath))

           {

-            RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath));

+            RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath));

             return S_OK;

           }

         }

-        else if (!DeleteFileAlways(fullProcessedPath))

+        else

         {

-          RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath));

-          return S_OK;

-          // return E_FAIL;

+          bool needDelete = true;

+          if (needDelete)

+          {

+            if (!DeleteFileAlways(fullProcessedPath))

+            {

+              RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath));

+              return S_OK;

+              // return E_FAIL;

+            }

+          }

         }

       }

     }

+    else // not Find(fullProcessedPath)

+    {

+      // we need to clear READ-ONLY of parent before creating alt stream

+      #if defined(_WIN32) && !defined(UNDER_CE)

+      int colonPos = NName::FindAltStreamColon(fullProcessedPath);

+      if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)

+      {

+        FString parentFsPath = fullProcessedPath;

+        parentFsPath.DeleteFrom(colonPos);

+        NFind::CFileInfo parentFi;

+        if (parentFi.Find(parentFsPath))

+        {

+          if (parentFi.IsReadOnly())

+            SetFileAttrib(parentFsPath, parentFi.Attrib & ~FILE_ATTRIBUTE_READONLY);

+        }

+      }

+      #endif

+    }

+    // ----- END of code for    Is file (not split) -----

+

     }

     _diskFilePath = fullProcessedPath;

     

@@ -841,7 +1192,7 @@
 

         UString relatPath;

         if (isRelative)

-          relatPath = GetDirPrefixOf(_filePath);

+          relatPath = GetDirPrefixOf(_item.Path);

         relatPath += linkPath;

         

         if (!IsSafePath(relatPath))

@@ -851,9 +1202,9 @@
         else

         {

           FString existPath;

-          if (isHardLink || !isRelative)

+          if (isHardLink /* || isCopyLink */ || !isRelative)

           {

-            if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath))

+            if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))

             {

               RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));

             }

@@ -865,18 +1216,42 @@
           

           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)

             {

               // bool isSymLink = true; // = false for junction

-              if (_fi.IsDir && !isRelative)

+              if (_item.IsDir && !isRelative)

               {

                 // if it's before Vista we use Junction Point

                 // isJunction = true;

@@ -889,12 +1264,13 @@
                 CReparseAttr attr;

                 if (!attr.Parse(data, data.Size()))

                 {

-                  return E_FAIL; // "Internal conversion error";

+                  RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)));

+                  // return E_FAIL;

                 }

-                

-                if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size()))

+                else

+                if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size()))

                 {

-                  RINOK(SendMessageError("Can not set reparse data", fullProcessedPath));

+                  RINOK(SendMessageError_with_LastError("Can not create symbolic link", fullProcessedPath));

                 }

               }

             }

@@ -903,13 +1279,14 @@
         

         #endif

       }

-      else

+      

+      if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)

       #endif // SUPPORT_LINKS

       {

         bool needWriteFile = true;

         

         #ifdef SUPPORT_LINKS

-        if (!_hardLinks.IDs.IsEmpty())

+        if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream)

         {

           CHardLinkNode h;

           bool defined;

@@ -941,20 +1318,34 @@
         if (needWriteFile)

         {

           _outFileStreamSpec = new COutFileStream;

-          CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

+          CMyComPtr<ISequentialOutStream> outStreamLoc2(_outFileStreamSpec);

           if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))

           {

             // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)

             {

-              RINOK(SendMessageError("Can not open output file ", fullProcessedPath));

+              RINOK(SendMessageError_with_LastError("Can not open output file", fullProcessedPath));

               return S_OK;

             }

           }

+

+

+          #ifdef SUPPORT_ALT_STREAMS

+          if (isRenamed && !_item.IsAltStream)

+          {

+            CIndexToPathPair pair(index, fullProcessedPath);

+            unsigned oldSize = _renamedFiles.Size();

+            unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair);

+            if (oldSize == _renamedFiles.Size())

+              _renamedFiles[insertIndex].Path = fullProcessedPath;

+          }

+          #endif

+

           if (_isSplit)

           {

             RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));

           }

-          _outFileStream = outStreamLoc;

+         

+          _outFileStream = outStreamLoc2;

         }

       }

     }

@@ -979,12 +1370,34 @@
 

   #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

@@ -995,6 +1408,7 @@
   #endif

   

   _extractMode = false;

+  

   switch (askExtractMode)

   {

     case NArchive::NExtract::NAskMode::kExtract:

@@ -1004,25 +1418,34 @@
         _extractMode = true;

       break;

   };

-  return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir,

+  

+  return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),

       askExtractMode, _isSplit ? &_position: 0);

+  

   COM_TRY_END

 }

 

-STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)

+

+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)

 {

   COM_TRY_BEGIN

 

   #ifndef _SFX

   if (ExtractToStreamCallback)

-    return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted);

+    return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted));

   #endif

 

   #ifndef _SFX

 

   if (_hashStreamWasUsed)

   {

-    _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath);

+    _hashStreamSpec->_hash->Final(_item.IsDir,

+        #ifdef SUPPORT_ALT_STREAMS

+          _item.IsAltStream

+        #else

+          false

+        #endif

+        , _item.Path);

     _curSize = _hashStreamSpec->GetSize();

     _curSizeDefined = true;

     _hashStreamSpec->ReleaseStream();

@@ -1044,7 +1467,7 @@
   }

   

   #ifdef _USE_SECURITY_CODE

-  if (_ntOptions.NtSecurity.Val && _arc->GetRawProps)

+  if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)

   {

     const void *data;

     UInt32 dataSize;

@@ -1067,42 +1490,67 @@
 

   if (!_curSizeDefined)

     GetUnpackSize();

+  

   if (_curSizeDefined)

   {

-    if (_isAltStream)

+    #ifdef SUPPORT_ALT_STREAMS

+    if (_item.IsAltStream)

       AltStreams_UnpackSize += _curSize;

     else

+    #endif

       UnpackSize += _curSize;

   }

     

-  if (_fi.IsDir)

+  if (_item.IsDir)

     NumFolders++;

-  else if (_isAltStream)

+  #ifdef SUPPORT_ALT_STREAMS

+  else if (_item.IsAltStream)

     NumAltStreams++;

+  #endif

   else

     NumFiles++;

 

-  if (_extractMode && _fi.AttribDefined)

+  if (!_stdOutMode && _extractMode && _fi.AttribDefined)

     SetFileAttrib(_diskFilePath, _fi.Attrib);

-  RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));

+  

+  RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));

+  

   return S_OK;

+  

   COM_TRY_END

 }

 

-/*

-STDMETHODIMP CArchiveExtractCallback::GetInStream(

-    const wchar_t *name, ISequentialInStream **inStream)

+STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)

 {

-  COM_TRY_BEGIN

-  CInFileStream *inFile = new CInFileStream;

-  CMyComPtr<ISequentialInStream> inStreamTemp = inFile;

-  if (!inFile->Open(_srcDirectoryPrefix + name))

-    return ::GetLastError();

-  *inStream = inStreamTemp.Detach();

+  if (_folderArchiveExtractCallback2)

+  {

+    bool isEncrypted = false;

+    wchar_t temp[16];

+    UString s2;

+    const wchar_t *s = NULL;

+    

+    if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)

+    {

+      CReadArcItem item;

+      RINOK(_arc->GetItem(index, item));

+      s2 = item.Path;

+      s = s2;

+      RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted));

+    }

+    else

+    {

+      temp[0] = '#';

+      ConvertUInt32ToString(index, temp + 1);

+      s = temp;

+      // if (indexType == NArchive::NEventIndexType::kBlockIndex) {}

+    }

+    

+    return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s);

+  }

+

   return S_OK;

-  COM_TRY_END

 }

-*/

+

 

 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)

 {

@@ -1119,8 +1567,8 @@
 

 struct CExtrRefSortPair

 {

-  int Len;

-  int Index;

+  unsigned Len;

+  unsigned Index;

 

   int Compare(const CExtrRefSortPair &a) const;

 };

@@ -1133,18 +1581,14 @@
   return MyCompare(Index, a.Index);

 }

 

-static int GetNumSlashes(const FChar *s)

+static unsigned GetNumSlashes(const FChar *s)

 {

-  for (int numSlashes = 0;;)

+  for (unsigned numSlashes = 0;;)

   {

     FChar c = *s++;

     if (c == 0)

       return numSlashes;

-    if (

-        #ifdef _WIN32

-        c == FTEXT('\\') ||

-        #endif

-        c == FTEXT('/'))

+    if (IS_PATH_SEPAR(c))

       numSlashes++;

   }

 }

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 7000532..37979f4 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -76,7 +76,7 @@
 public:

   const CArc *Arc;

   UInt32 IndexInArc;

-  UString Name; // relative path

+  // UString Name; // relative path

 

   MY_UNKNOWN_IMP1(IGetProp)

   INTERFACE_IGetProp(;)

@@ -124,9 +124,27 @@
 

 #endif

 

+#ifdef SUPPORT_ALT_STREAMS

+

+struct CIndexToPathPair

+{

+  UInt32 Index;

+  FString Path;

+

+  CIndexToPathPair(UInt32 index): Index(index) {}

+  CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}

+

+  int Compare(const CIndexToPathPair &pair) const

+  {

+    return MyCompare(Index, pair.Index);

+  }

+};

+

+#endif

+

 class CArchiveExtractCallback:

   public IArchiveExtractCallback,

-  // public IArchiveVolumeExtractCallback,

+  public IArchiveExtractCallbackMessage,

   public ICryptoGetTextPassword,

   public ICompressProgressInfo,

   public CMyUnknownImp

@@ -134,12 +152,15 @@
   const CArc *_arc;

   CExtractNtOptions _ntOptions;

 

-  const NWildcard::CCensorNode *_wildcardCensor;

+  const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)

   CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;

   CMyComPtr<ICompressProgressInfo> _compressProgress;

   CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;

-  FString _directoryPath;

-  FString _directoryPathFull;

+  CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;

+  CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;

+

+  FString _dirPathPrefix;

+  FString _dirPathPrefix_Full;

   NExtract::NPathMode::EEnum _pathMode;

   NExtract::NOverwriteMode::EEnum _overwriteMode;

 

@@ -151,11 +172,10 @@
   

   #endif

 

+  CReadArcItem _item;

   FString _diskFilePath;

-  UString _filePath;

   UInt64 _position;

   bool _isSplit;

-  bool _isAltStream;

 

   bool _extractMode;

 

@@ -176,8 +196,6 @@
     bool ATimeDefined;

     bool MTimeDefined;

     bool AttribDefined;

-

-    bool IsDir;

   } _fi;

 

   UInt32 _index;

@@ -194,9 +212,13 @@
   

   #endif

 

+  bool _removePartsForAltStreams;

   UStringVector _removePathParts;

+  

+  #ifndef _SFX

   bool _use_baseParentFolder_mode;

   UInt32 _baseParentFolder;

+  #endif

 

   bool _stdOutMode;

   bool _testMode;

@@ -204,7 +226,9 @@
 

   CMyComPtr<ICompressProgressInfo> _localProgress;

   UInt64 _packTotal;

-  UInt64 _unpTotal;

+  

+  UInt64 _progressTotal;

+  bool _progressTotal_Defined;

 

   FStringVector _extractedFolderPaths;

   CRecordVector<UInt32> _extractedFolderIndices;

@@ -218,6 +242,7 @@
   HRESULT GetUnpackSize();

 

   HRESULT SendMessageError(const char *message, const FString &path);

+  HRESULT SendMessageError_with_LastError(const char *message, const FString &path);

   HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);

 

 public:

@@ -230,16 +255,13 @@
   UInt64 UnpackSize;

   UInt64 AltStreams_UnpackSize;

   

-  MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)

-  // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)

+  MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)

 

   INTERFACE_IArchiveExtractCallback(;)

+  INTERFACE_IArchiveExtractCallbackMessage(;)

 

   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

 

-  // IArchiveVolumeExtractCallback

-  // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);

-

   STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

   CArchiveExtractCallback();

@@ -274,26 +296,43 @@
       IFolderArchiveExtractCallback *extractCallback2,

       bool stdOutMode, bool testMode,

       const FString &directoryPath,

-      const UStringVector &removePathParts,

+      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

 

   // call it after Init()

 

+  #ifndef _SFX

   void SetBaseParentFolderIndex(UInt32 indexInArc)

   {

-    _use_baseParentFolder_mode = true;

     _baseParentFolder = indexInArc;

+    _use_baseParentFolder_mode = true;

   }

+  #endif

 

   HRESULT SetDirsTimes();

 };

 

+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);

+

 #endif

diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
index cabc955..c5dad2a 100644
--- a/CPP/7zip/UI/Common/ArchiveName.cpp
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -3,68 +3,76 @@
 #include "StdAfx.h"

 

 #include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileName.h"

 

 #include "ExtractingFilePath.h"

 #include "ArchiveName.h"

 

 using namespace NWindows;

+using namespace NFile;

 

-UString CreateArchiveName(const NFile::NFind::CFileInfo fileInfo, bool keepName)

+UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName)

 {

-  FString resultName = fileInfo.Name;

-  if (!fileInfo.IsDir() && !keepName)

+  FString resultName = fi.Name;

+  if (!fi.IsDir() && !keepName)

   {

-    int dotPos = resultName.ReverseFind(FTEXT('.'));

+    int dotPos = resultName.ReverseFind_Dot();

     if (dotPos > 0)

     {

       FString archiveName2 = resultName.Left(dotPos);

-      if (archiveName2.ReverseFind(FTEXT('.')) < 0)

+      if (archiveName2.ReverseFind_Dot() < 0)

         resultName = archiveName2;

     }

   }

-  return GetCorrectFsPath(fs2us(resultName));

+  return Get_Correct_FsFile_Name(fs2us(resultName));

 }

 

-static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName)

+static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)

 {

   FString resultName = FTEXT("Archive");

   if (fromPrev)

   {

     FString dirPrefix;

-    if (NFile::NDir::GetOnlyDirPrefix(srcName, dirPrefix))

+    if (NDir::GetOnlyDirPrefix(path, dirPrefix))

     {

-      if (dirPrefix.Len() > 0)

-        if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR)

+      if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))

+      {

+        #if defined(_WIN32) && !defined(UNDER_CE)

+        if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))

+          resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter

+        else

+        #endif

         {

           dirPrefix.DeleteBack();

-          NFile::NFind::CFileInfo fileInfo;

-          if (fileInfo.Find(dirPrefix))

-            resultName = fileInfo.Name;

+          NFind::CFileInfo fi;

+          if (fi.Find(dirPrefix))

+            resultName = fi.Name;

         }

+      }

     }

   }

   else

   {

-    NFile::NFind::CFileInfo fileInfo;

-    if (!fileInfo.Find(srcName))

-      // return resultName;

-      return srcName;

-    resultName = fileInfo.Name;

-    if (!fileInfo.IsDir() && !keepName)

+    NFind::CFileInfo fi;

+    if (fi.Find(path))

     {

-      int dotPos = resultName.ReverseFind('.');

-      if (dotPos > 0)

+      resultName = fi.Name;

+      if (!fi.IsDir() && !keepName)

       {

-        FString archiveName2 = resultName.Left(dotPos);

-        if (archiveName2.ReverseFind(FTEXT('.')) < 0)

-          resultName = archiveName2;

+        int dotPos = resultName.ReverseFind_Dot();

+        if (dotPos > 0)

+        {

+          FString name2 = resultName.Left(dotPos);

+          if (name2.ReverseFind_Dot() < 0)

+            resultName = name2;

+        }

       }

     }

   }

   return resultName;

 }

 

-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)

+UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName)

 {

-  return GetCorrectFsPath(fs2us(CreateArchiveName2(us2fs(srcName), fromPrev, keepName)));

+  return Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(path), fromPrev, keepName)));

 }

diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
index e67cf1e..7b49c7b 100644
--- a/CPP/7zip/UI/Common/ArchiveName.h
+++ b/CPP/7zip/UI/Common/ArchiveName.h
@@ -7,7 +7,7 @@
 

 #include "../../../Windows/FileFind.h"

 

-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);

-UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo fileInfo, bool keepName);

+UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName);

+UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo &fileInfo, bool keepName);

 

 #endif

diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index f268dd9..a9fda7b 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -40,12 +40,13 @@
   COM_TRY_BEGIN

   NCOM::CPropVariant prop;

   if (_subArchiveMode)

-    switch(propID)

+    switch (propID)

     {

       case kpidName: prop = _subArchiveName; break;

+      // case kpidSize:  prop = _subArchiveSize; break; // we don't use it now

     }

   else

-    switch(propID)

+    switch (propID)

     {

       case kpidName:  prop = _fileInfo.Name; break;

       case kpidIsDir:  prop = _fileInfo.IsDir(); break;

@@ -73,18 +74,40 @@
   }

 };

 

+

+// from ArchiveExtractCallback.cpp

+bool IsSafePath(const UString &path);

+

 STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)

 {

   COM_TRY_BEGIN

   *inStream = NULL;

+  

   if (_subArchiveMode)

     return S_FALSE;

   if (Callback)

   {

     RINOK(Callback->Open_CheckBreak());

   }

+

+  UString name2 = name;

+

+  

+  #ifndef _SFX

+  

+  #ifdef _WIN32

+  name2.Replace(L'/', WCHAR_PATH_SEPARATOR);

+  #endif

+

+  // if (!allowAbsVolPaths)

+  if (!IsSafePath(name2))

+    return S_FALSE;

+  

+  #endif

+

+

   FString fullPath;

-  if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath))

+  if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))

     return S_FALSE;

   if (!_fileInfo.Find(fullPath))

     return S_FALSE;

@@ -93,10 +116,15 @@
   CInFileStreamVol *inFile = new CInFileStreamVol;

   CMyComPtr<IInStream> inStreamTemp = inFile;

   if (!inFile->Open(fullPath))

-    return ::GetLastError();

+  {

+    DWORD lastError = ::GetLastError();

+    if (lastError == 0)

+      return E_FAIL;

+    return HRESULT_FROM_WIN32(lastError);

+  }

 

   FileSizes.Add(_fileInfo.Size);

-  FileNames.Add(name);

+  FileNames.Add(name2);

   inFile->FileNameIndex = FileNames_WasUsed.Add(true);

   inFile->OpenCallbackImp = this;

   inFile->OpenCallbackRef = this;

@@ -119,6 +147,7 @@
   }

   if (!Callback)

     return E_NOTIMPL;

+  PasswordWasAsked = true;

   return Callback->Open_CryptoGetTextPassword(password);

   COM_TRY_END

 }

diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index f7b3618..7f7548f 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -20,9 +20,9 @@
 

 #define INTERFACE_IOpenCallbackUI_Crypto(x) \

   virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \

-  virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \

-  virtual bool Open_WasPasswordAsked() x; \

-  virtual void Open_ClearPasswordWasAskedFlag() x; \

+  /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \

+  /* virtual bool Open_WasPasswordAsked() x; */ \

+  /* virtual void Open_Clear_PasswordWasAsked_Flag() x; */  \

   

 #endif

 

@@ -30,6 +30,7 @@
   virtual HRESULT Open_CheckBreak() x; \

   virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \

   virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \

+  virtual HRESULT Open_Finished() x; \

   INTERFACE_IOpenCallbackUI_Crypto(x)

 

 struct IOpenCallbackUI

@@ -47,18 +48,13 @@
   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(;)

@@ -85,12 +81,15 @@
   UStringVector FileNames;

   CBoolVector FileNames_WasUsed;

   CRecordVector<UInt64> FileSizes;

+  

+  bool PasswordWasAsked;

 

   IOpenCallbackUI *Callback;

   CMyComPtr<IArchiveOpenCallback> ReOpenCallback;

   // UInt64 TotalSize;

 

-  COpenCallbackImp(): Callback(NULL) {}

+  COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}

+  

   void Init(const FString &folderPrefix, const FString &fileName)

   {

     _folderPrefix = folderPrefix;

@@ -101,7 +100,9 @@
     FileSizes.Clear();

     _subArchiveMode = false;

     // 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 d8dc3a8..14aabcc 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -2,6 +2,8 @@
 

 #include "StdAfx.h"

 

+#include <stdio.h>

+

 #ifndef _WIN32

 #define USE_POSIX_TIME

 #define USE_POSIX_TIME2

@@ -30,15 +32,22 @@
 #include "../../../../C/Alloc.h"

 #include "../../../../C/CpuArch.h"

 

-#if !defined(_7ZIP_ST) || defined(_WIN32)

 #include "../../../Windows/System.h"

-#endif

 

 #ifndef _7ZIP_ST

 #include "../../../Windows/Synchronization.h"

 #include "../../../Windows/Thread.h"

 #endif

 

+#if defined(_WIN32) || defined(UNIX_USE_WIN_FILE)

+#define USE_WIN_FILE

+#endif

+

+#ifdef USE_WIN_FILE

+#include "../../../Windows/FileIO.h"

+#endif

+

+

 #include "../../../Common/IntToString.h"

 #include "../../../Common/StringConvert.h"

 #include "../../../Common/StringToInt.h"

@@ -50,6 +59,8 @@
 

 using namespace NWindows;

 

+static const UInt32 k_LZMA = 0x030101;

+

 static const UInt64 kComplexInCommands = (UInt64)1 <<

   #ifdef UNDER_CE

     31;

@@ -57,15 +68,17 @@
     34;

   #endif

 

-static const UInt64 kComplexInSeconds = 4;

+static const UInt32 kComplexInSeconds = 4;

 

-static void SetComplexCommands(UInt32 complexInSeconds, UInt64 cpuFreq, UInt64 &complexInCommands)

+static void SetComplexCommands(UInt32 complexInSeconds,

+    bool isSpecifiedFreq, UInt64 cpuFreq, UInt64 &complexInCommands)

 {

   complexInCommands = kComplexInCommands;

-  const UInt64 kMinFreq = (UInt64)1000000 * 30;

+  const UInt64 kMinFreq = (UInt64)1000000 * 4;

   const UInt64 kMaxFreq = (UInt64)1000000 * 20000;

-  if (cpuFreq < kMinFreq) cpuFreq = kMinFreq;

-  if (cpuFreq < kMaxFreq)

+  if (cpuFreq < kMinFreq && !isSpecifiedFreq)

+    cpuFreq = kMinFreq;

+  if (cpuFreq < kMaxFreq || isSpecifiedFreq)

   {

     if (complexInSeconds != 0)

       complexInCommands = complexInSeconds * cpuFreq;

@@ -98,87 +111,154 @@
   }

 };

 

-class CBenchBuffer

+

+static const unsigned kBufferAlignment = 1 << 4;

+

+struct CBenchBuffer

 {

-public:

   size_t BufferSize;

+

+  #ifdef _WIN32

+

   Byte *Buffer;

 

-  CBenchBuffer(): Buffer(0) {}

-  virtual ~CBenchBuffer() { Free(); }

-  void Free()

+  CBenchBuffer(): BufferSize(0), Buffer(NULL) {}

+  ~CBenchBuffer() { ::MidFree(Buffer); }

+  

+  void AllocAlignedMask(size_t size, size_t)

   {

     ::MidFree(Buffer);

-    Buffer = 0;

+    BufferSize = 0;

+    Buffer = (Byte *)::MidAlloc(size);

+    if (Buffer)

+      BufferSize = size;

   }

-  bool Alloc(size_t bufferSize)

+  

+  #else

+  

+  Byte *Buffer;

+  Byte *_bufBase;

+

+  CBenchBuffer(): BufferSize(0), Buffer(NULL), _bufBase(NULL){}

+  ~CBenchBuffer() { ::MidFree(_bufBase); }

+  

+  void AllocAlignedMask(size_t size, size_t alignMask)

   {

-    if (Buffer != 0 && BufferSize == bufferSize)

+    ::MidFree(_bufBase);

+    Buffer = NULL;

+    BufferSize = 0;

+    _bufBase = (Byte *)::MidAlloc(size + alignMask);

+    

+    if (_bufBase)

+    {

+      // Buffer = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);

+         Buffer = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);

+      BufferSize = size;

+    }

+  }

+

+  #endif

+

+  bool Alloc(size_t size)

+  {

+    if (Buffer && BufferSize == size)

       return true;

-    Free();

-    Buffer = (Byte *)::MidAlloc(bufferSize);

-    BufferSize = bufferSize;

-    return (Buffer != 0 || bufferSize == 0);

+    AllocAlignedMask(size, kBufferAlignment - 1);

+    return (Buffer != NULL || size == 0);

   }

 };

 

+

 class CBenchRandomGenerator: public CBenchBuffer

 {

-  CBaseRandomGenerator *RG;

-public:

-  void Set(CBaseRandomGenerator *rg) { RG = rg; }

-  UInt32 GetVal(UInt32 &res, unsigned numBits)

+  static UInt32 GetVal(UInt32 &res, unsigned numBits)

   {

     UInt32 val = res & (((UInt32)1 << numBits) - 1);

     res >>= numBits;

     return val;

   }

-  UInt32 GetLen(UInt32 &res)

+  

+  static UInt32 GetLen(UInt32 &r)

   {

-    UInt32 len = GetVal(res, 2);

-    return GetVal(res, 1 + len);

+    UInt32 len = GetVal(r, 2);

+    return GetVal(r, 1 + len);

   }

 

-  void GenerateSimpleRandom()

+public:

+  

+  void GenerateSimpleRandom(CBaseRandomGenerator *_RG_)

   {

-    for (UInt32 i = 0; i < BufferSize; i++)

-      Buffer[i] = (Byte)RG->GetRnd();

+    CBaseRandomGenerator rg = *_RG_;

+    const size_t bufSize = BufferSize;

+    Byte *buf = Buffer;

+    for (size_t i = 0; i < bufSize; i++)

+      buf[i] = (Byte)rg.GetRnd();

+    *_RG_ = rg;

   }

 

-  void Generate(unsigned dictBits)

+  void GenerateLz(unsigned dictBits, CBaseRandomGenerator *_RG_)

   {

+    CBaseRandomGenerator rg = *_RG_;

     UInt32 pos = 0;

     UInt32 rep0 = 1;

-    while (pos < BufferSize)

+    const size_t bufSize = BufferSize;

+    Byte *buf = Buffer;

+    unsigned posBits = 1;

+    

+    while (pos < bufSize)

     {

-      UInt32 res = RG->GetRnd();

-      res >>= 1;

-      if (GetVal(res, 1) == 0 || pos < 1024)

-        Buffer[pos++] = (Byte)(res & 0xFF);

+      UInt32 r = rg.GetRnd();

+      if (GetVal(r, 1) == 0 || pos < 1024)

+        buf[pos++] = (Byte)(r & 0xFF);

       else

       {

         UInt32 len;

-        len = 1 + GetLen(res);

-        if (GetVal(res, 3) != 0)

+        len = 1 + GetLen(r);

+        

+        if (GetVal(r, 3) != 0)

         {

-          len += GetLen(res);

-          do

+          len += GetLen(r);

+

+          while (((UInt32)1 << posBits) < pos)

+            posBits++;

+

+          unsigned numBitsMax = dictBits;

+          if (numBitsMax > posBits)

+            numBitsMax = posBits;

+

+          const unsigned kAddBits = 6;

+          unsigned numLogBits = 5;

+          if (numBitsMax <= (1 << 4) - 1 + kAddBits)

+            numLogBits = 4;

+

+          for (;;)

           {

-            UInt32 ppp = GetVal(res, 5) + 6;

-            res = RG->GetRnd();

-            if (ppp > dictBits)

+            UInt32 ppp = GetVal(r, numLogBits) + kAddBits;

+            r = rg.GetRnd();

+            if (ppp > numBitsMax)

               continue;

-            rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);

-            res = RG->GetRnd();

+            rep0 = GetVal(r, ppp);

+            if (rep0 < pos)

+              break;

+            r = rg.GetRnd();

           }

-          while (rep0 >= pos);

           rep0++;

         }

 

-        for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)

-          Buffer[pos] = Buffer[pos - rep0];

+        {

+          UInt32 rem = (UInt32)bufSize - pos;

+          if (len > rem)

+            len = rem;

+        }

+        Byte *dest = buf + pos;

+        const Byte *src = dest - rep0;

+        pos += len;

+        for (UInt32 i = 0; i < len; i++)

+          *dest++ = *src++;

       }

     }

+

+    *_RG_ = rg;

   }

 };

 

@@ -212,7 +292,7 @@
   for (UInt32 i = 0; i < size; i++)

     ((Byte *)data)[i] = Data[Pos + i];

   Pos += size;

-  if(processedSize != NULL)

+  if (processedSize)

     *processedSize = size;

   return S_OK;

 }

@@ -224,7 +304,7 @@
 {

   // bool _overflow;

 public:

-  UInt32 Pos;

+  size_t Pos;

   bool RealCopy;

   bool CalcCrc;

   UInt32 Crc;

@@ -238,6 +318,9 @@
     // _overflow = false;

     Pos = 0;

   }

+

+  // void Print() { printf("\n%8d %8d\n", (unsigned)BufferSize, (unsigned)Pos); }

+

   MY_UNKNOWN_IMP

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

@@ -247,12 +330,15 @@
   size_t curSize = BufferSize - Pos;

   if (curSize > size)

     curSize = size;

-  if (RealCopy)

-    memcpy(Buffer + Pos, data, curSize);

-  if (CalcCrc)

-    Crc = CrcUpdate(Crc, data, curSize);

-  Pos += (UInt32)curSize;

-  if(processedSize != NULL)

+  if (curSize != 0)

+  {

+    if (RealCopy)

+      memcpy(Buffer + Pos, data, curSize);

+    if (CalcCrc)

+      Crc = CrcUpdate(Crc, data, curSize);

+    Pos += curSize;

+  }

+  if (processedSize)

     *processedSize = (UInt32)curSize;

   if (curSize != size)

   {

@@ -280,7 +366,7 @@
 {

   if (CalcCrc)

     Crc = CrcUpdate(Crc, data, size);

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = size;

   return S_OK;

 }

@@ -472,11 +558,11 @@
   return res;

 }

 

-static const int kSubBits = 8;

+static const unsigned kSubBits = 8;

 

 static UInt32 GetLogSize(UInt32 size)

 {

-  for (int i = kSubBits; i < 32; i++)

+  for (unsigned i = kSubBits; i < 32; i++)

     for (UInt32 j = 0; j < (1 << kSubBits); j++)

       if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))

         return (i << kSubBits) + j;

@@ -616,6 +702,7 @@
   CBenchProgressInfo *progressInfoSpec[2];

   CMyComPtr<ICompressProgressInfo> progressInfo[2];

   UInt64 NumIterations;

+

   #ifdef USE_ALLOCA

   size_t AllocaSize;

   #endif

@@ -630,10 +717,11 @@
   {

     CEncoderInfo *Encoder;

     UInt32 DecoderIndex;

+    bool CallbackMode;

+    

     #ifdef USE_ALLOCA

     size_t AllocaSize;

     #endif

-    bool CallbackMode;

   };

   CDecoderInfo decodersInfo[2];

 

@@ -646,31 +734,36 @@
   IBenchCallback *callback;

   IBenchPrintCallback *printCallback;

   UInt32 crc;

-  UInt32 kBufferSize;

-  UInt32 compressedSize;

+  size_t kBufferSize;

+  size_t compressedSize;

+  const Byte *uncompressedDataPtr;

+

+  const Byte *fileData;

   CBenchRandomGenerator rg;

+

   CBenchBuffer rgCopy; // it must be 16-byte aligned !!!

   CBenchmarkOutStream *propStreamSpec;

   CMyComPtr<ISequentialOutStream> propStream;

 

   // for decode

   COneMethodInfo _method;

-  UInt32 _uncompressedDataSize;

+  size_t _uncompressedDataSize;

 

   HRESULT Init(

       const COneMethodInfo &method,

-      UInt32 uncompressedDataSize,

       unsigned generateDictBits,

       CBaseRandomGenerator *rg);

   HRESULT Encode();

   HRESULT Decode(UInt32 decoderIndex);

 

   CEncoderInfo():

+    fileData(NULL),

     CheckCrc_Enc(true),

     CheckCrc_Dec(true),

     outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {}

 

   #ifndef _7ZIP_ST

+  

   static THREAD_FUNC_DECL EncodeThreadFunction(void *param)

   {

     HRESULT res;

@@ -680,6 +773,7 @@
       #ifdef USE_ALLOCA

       alloca(encoder->AllocaSize);

       #endif

+

       res = encoder->Encode();

       encoder->Results[0] = res;

     }

@@ -691,12 +785,15 @@
       encoder->progressInfoSpec[0]->Status->SetResult(res);

     return 0;

   }

+  

   static THREAD_FUNC_DECL DecodeThreadFunction(void *param)

   {

     CDecoderInfo *decoder = (CDecoderInfo *)param;

+    

     #ifdef USE_ALLOCA

     alloca(decoder->AllocaSize);

     #endif

+    

     CEncoderInfo *encoder = decoder->Encoder;

     encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);

     return 0;

@@ -707,7 +804,7 @@
     return thread[0].Create(EncodeThreadFunction, this);

   }

 

-  HRESULT CreateDecoderThread(int index, bool callbackMode

+  HRESULT CreateDecoderThread(unsigned index, bool callbackMode

       #ifdef USE_ALLOCA

       , size_t allocaSize

       #endif

@@ -716,49 +813,63 @@
     CDecoderInfo &decoder = decodersInfo[index];

     decoder.DecoderIndex = index;

     decoder.Encoder = this;

+    

     #ifdef USE_ALLOCA

     decoder.AllocaSize = allocaSize;

     #endif

+    

     decoder.CallbackMode = callbackMode;

     return thread[index].Create(DecodeThreadFunction, &decoder);

   }

+  

   #endif

 };

 

-static const UInt32 k_LZMA  = 0x030101;

 

 HRESULT CEncoderInfo::Init(

     const COneMethodInfo &method,

-    UInt32 uncompressedDataSize,

     unsigned generateDictBits,

     CBaseRandomGenerator *rgLoc)

 {

-  rg.Set(rgLoc);

-  kBufferSize = uncompressedDataSize;

-  UInt32 kCompressedBufferSize =

-      kBufferSize + kCompressedAdditionalSize;

-      // (kBufferSize - kBufferSize / 4) + kCompressedAdditionalSize;

-  if (!rg.Alloc(kBufferSize))

-    return E_OUTOFMEMORY;

-  if (generateDictBits == 0)

-    rg.GenerateSimpleRandom();

-  else

-    rg.Generate(generateDictBits);

-  crc = CrcCalc(rg.Buffer, rg.BufferSize);

+  // we need extra space, if input data is already compressed

+  const size_t kCompressedBufferSize =

+      kCompressedAdditionalSize +

+      kBufferSize + kBufferSize / 16;

+      // kBufferSize / 2;

 

+  if (kCompressedBufferSize < kBufferSize)

+    return E_FAIL;

+

+  uncompressedDataPtr = fileData;

+  

+  if (!fileData)

+  {

+    if (!rg.Alloc(kBufferSize))

+      return E_OUTOFMEMORY;

+    

+    // DWORD ttt = GetTickCount();

+    if (generateDictBits == 0)

+      rg.GenerateSimpleRandom(rgLoc);

+    else

+      rg.GenerateLz(generateDictBits, rgLoc);

+    // printf("\n%d\n            ", GetTickCount() - ttt);

+

+    crc = CrcCalc(rg.Buffer, rg.BufferSize);

+    uncompressedDataPtr = rg.Buffer;

+  }

+  

   if (_encoderFilter)

   {

-    if (!rgCopy.Alloc(rg.BufferSize))

+    if (!rgCopy.Alloc(kBufferSize))

       return E_OUTOFMEMORY;

   }

 

 

   outStreamSpec = new CBenchmarkOutStream;

+  outStream = outStreamSpec;

   if (!outStreamSpec->Alloc(kCompressedBufferSize))

     return E_OUTOFMEMORY;

 

-  outStream = outStreamSpec;

-

   propStreamSpec = 0;

   if (!propStream)

   {

@@ -780,7 +891,7 @@
     coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);

     if (scp)

     {

-      UInt64 reduceSize = uncompressedDataSize;

+      UInt64 reduceSize = kBufferSize;

       RINOK(method.SetCoderProps(scp, &reduceSize));

     }

     else

@@ -805,15 +916,8 @@
 

         // we must call encoding one time to calculate password key for key cache.

         // it must be after WriteCoderProperties!

-        CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

-        CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

         Byte temp[16];

         memset(temp, 0, sizeof(temp));

-        inStreamSpec->Init(temp, sizeof(temp));

-        

-        CCrcOutStream *outStreamSpec = new CCrcOutStream;

-        CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;

-        outStreamSpec->Init();

         

         if (_encoderFilter)

         {

@@ -822,15 +926,42 @@
         }

         else

         {

-          RINOK(_encoder->Code(inStream, outStream, 0, 0, NULL));

+          CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

+          CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

+          inStreamSpec->Init(temp, sizeof(temp));

+          

+          CCrcOutStream *crcStreamSpec = new CCrcOutStream;

+          CMyComPtr<ISequentialOutStream> crcStream = crcStreamSpec;

+          crcStreamSpec->Init();

+

+          RINOK(_encoder->Code(inStream, crcStream, 0, 0, NULL));

         }

       }

     }

-

   }

+

   return S_OK;

 }

 

+

+static void My_FilterBench(ICompressFilter *filter, Byte *data, size_t size)

+{

+  while (size != 0)

+  {

+    UInt32 cur = (UInt32)1 << 31;

+    if (cur > size)

+      cur = (UInt32)size;

+    UInt32 processed = filter->Filter(data, cur);

+    data += processed;

+    // if (processed > size) (in AES filter), we must fill last block with zeros.

+    // but it is not important for benchmark. So we just copy that data without filtering.

+    if (processed > size || processed == 0)

+      break;

+    size -= processed;

+  }

+}

+

+

 HRESULT CEncoderInfo::Encode()

 {

   CBenchInfo &bi = progressInfoSpec[0]->BenchInfo;

@@ -869,31 +1000,36 @@
     

     if (_encoderFilter)

     {

-      memcpy(rgCopy.Buffer, rg.Buffer, rg.BufferSize);

+      memcpy(rgCopy.Buffer, uncompressedDataPtr, kBufferSize);

       _encoderFilter->Init();

-      _encoderFilter->Filter(rgCopy.Buffer, (UInt32)rg.BufferSize);

-      RINOK(WriteStream(outStream, rgCopy.Buffer, rg.BufferSize));

+      My_FilterBench(_encoderFilter, rgCopy.Buffer, kBufferSize);

+      RINOK(WriteStream(outStream, rgCopy.Buffer, kBufferSize));

     }

     else

     {

-      inStreamSpec->Init(rg.Buffer, rg.BufferSize);

-      RINOK(_encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));

+      inStreamSpec->Init(uncompressedDataPtr, kBufferSize);

+      RINOK(_encoder->Code(inStream, outStream, NULL, NULL, progressInfo[0]));

     }

 

+    // outStreamSpec->Print();

+

     UInt32 crcNew = CRC_GET_DIGEST(outStreamSpec->Crc);

     if (i == 0)

       crcPrev = crcNew;

     else if (calcCrc && crcPrev != crcNew)

       return E_FAIL;

+    

     compressedSize = outStreamSpec->Pos;

-    bi.UnpackSize += rg.BufferSize;

+    bi.UnpackSize += kBufferSize;

     bi.PackSize += compressedSize;

   }

+  

   _encoder.Release();

   _encoderFilter.Release();

   return S_OK;

 }

 

+

 HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)

 {

   CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

@@ -945,7 +1081,7 @@
   

   if (setDecProps)

   {

-    RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));

+    RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, (UInt32)propStreamSpec->Pos));

   }

 

   {

@@ -978,29 +1114,33 @@
     

     UInt64 outSize = kBufferSize;

     crcOutStreamSpec->CalcCrc = ((i & 0x7F) == 0 || CheckCrc_Dec);

+    

     if (_decoderFilter)

     {

       if (compressedSize > rgCopy.BufferSize)

         return E_FAIL;

       memcpy(rgCopy.Buffer, outStreamSpec->Buffer, compressedSize);

       _decoderFilter->Init();

-      _decoderFilter->Filter(rgCopy.Buffer, compressedSize);

-      RINOK(WriteStream(crcOutStream, rgCopy.Buffer, rg.BufferSize));

+      My_FilterBench(_decoderFilter, rgCopy.Buffer, compressedSize);

+      RINOK(WriteStream(crcOutStream, rgCopy.Buffer, compressedSize));

     }

     else

     {

       RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));

     }

+  

     if (crcOutStreamSpec->CalcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)

       return S_FALSE;

     pi->BenchInfo.UnpackSize += kBufferSize;

     pi->BenchInfo.PackSize += compressedSize;

   }

+  

   decoder.Release();

   _decoderFilter.Release();

   return S_OK;

 }

 

+

 static const UInt32 kNumThreadsMax = (1 << 12);

 

 struct CBenchEncoders

@@ -1010,6 +1150,7 @@
   ~CBenchEncoders() { delete []encoders; }

 };

 

+

 static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands)

 {

   if (numCommands < (1 << 4))

@@ -1018,26 +1159,37 @@
   return (res == 0 ? 1 : res);

 }

 

+

 static HRESULT MethodBench(

     DECL_EXTERNAL_CODECS_LOC_VARS

     UInt64 complexInCommands,

-    bool oldLzmaBenchMode,

-    UInt32 numThreads,

+    bool

+      #ifndef _7ZIP_ST

+        oldLzmaBenchMode

+      #endif

+    ,

+    UInt32

+      #ifndef _7ZIP_ST

+        numThreads

+      #endif

+    ,

     const COneMethodInfo &method2,

-    UInt32 uncompressedDataSize,

+    size_t uncompressedDataSize,

+    const Byte *fileData,

     unsigned generateDictBits,

+

     IBenchPrintCallback *printCallback,

     IBenchCallback *callback,

     CBenchProps *benchProps)

 {

   COneMethodInfo method = method2;

   UInt64 methodId;

-  UInt32 numInStreams, numOutStreams;

+  UInt32 numStreams;

   if (!FindMethod(

       EXTERNAL_CODECS_LOC_VARS

-      method.MethodName, methodId, numInStreams, numOutStreams))

+      method.MethodName, methodId, numStreams))

     return E_NOTIMPL;

-  if (numInStreams != 1 || numOutStreams != 1)

+  if (numStreams != 1)

     return E_INVALIDARG;

 

   UInt32 numEncoderThreads = 1;

@@ -1051,7 +1203,7 @@
       bool fixedNumber;

       UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber);

       if (!fixedNumber && numThreads == 1)

-        method.AddNumThreadsProp(1);

+        method.AddProp_NumThreads(1);

       if (numThreads > 1 && numLzmaThreads > 1)

       {

         numEncoderThreads = numThreads / 2;

@@ -1064,18 +1216,20 @@
   CEncoderInfo *encoders = encodersSpec.encoders;

 

   UInt32 i;

+  

   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

     encoder.callback = (i == 0) ? callback : 0;

     encoder.printCallback = printCallback;

 

-    CMyComPtr<ICompressCoder2> coder2;

-    RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,

-        encoder._encoderFilter, encoder._encoder, coder2, true, false));

-    if (!encoder._encoder && !encoder._encoderFilter)

-      return E_NOTIMPL;

-    // encoder._encoderFilter.Release(); // we can disable filter to check the speed of FilterCoder.

+    {

+      CCreatedCoder cod;

+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, true, encoder._encoderFilter, cod));

+      encoder._encoder = cod.Coder;

+      if (!encoder._encoder && !encoder._encoderFilter)

+        return E_NOTIMPL;

+    }

 

     encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ;

     encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ;

@@ -1086,10 +1240,10 @@
 

     for (UInt32 j = 0; j < numSubDecoderThreads; j++)

     {

-      CMyComPtr<ICompressCoder2> coder2de;

+      CCreatedCoder cod;

       CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j];

-      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,

-        encoder._decoderFilter, decoder, coder2de, false, false));

+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod));

+      decoder = cod.Coder;

       if (!encoder._decoderFilter && !decoder)

         return E_NOTIMPL;

     }

@@ -1097,12 +1251,21 @@
 

   CBaseRandomGenerator rg;

   rg.Init();

+

+  UInt32 crc = 0;

+  if (fileData)

+    crc = CrcCalc(fileData, uncompressedDataSize);

+

   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

     encoder._method = method;

     encoder._uncompressedDataSize = uncompressedDataSize;

-    RINOK(encoders[i].Init(method, uncompressedDataSize, generateDictBits, &rg));

+    encoder.kBufferSize = uncompressedDataSize;

+    encoder.fileData = fileData;

+    encoder.crc = crc;

+

+    RINOK(encoders[i].Init(method, generateDictBits, &rg));

   }

 

   CBenchProgressStatus status;

@@ -1121,6 +1284,7 @@
       encoder.progressInfo[j] = spec;

       spec->Status = &status;

     }

+    

     if (i == 0)

     {

       CBenchProgressInfo *bpi = encoder.progressInfoSpec[0];

@@ -1135,6 +1299,7 @@
       #ifdef USE_ALLOCA

       encoder.AllocaSize = (i * 16 * 21) & 0x7FF;

       #endif

+

       RINOK(encoder.CreateEncoderThread())

     }

     else

@@ -1143,6 +1308,7 @@
       RINOK(encoder.Encode());

     }

   }

+  

   #ifndef _7ZIP_ST

   if (numEncoderThreads > 1)

     for (i = 0; i < numEncoderThreads; i++)

@@ -1157,12 +1323,14 @@
   info.UnpackSize = 0;

   info.PackSize = 0;

   info.NumIterations = encoders[0].NumIterations;

+  

   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

     info.UnpackSize += encoder.kBufferSize;

     info.PackSize += encoder.compressedSize;

   }

+  

   RINOK(callback->SetEncodeResult(info, true));

 

 

@@ -1170,6 +1338,7 @@
   status.EncodeMode = false;

 

   UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;

+  

   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

@@ -1208,6 +1377,7 @@
       RINOK(encoder.Decode(0));

     }

   }

+  

   #ifndef _7ZIP_ST

   HRESULT res = S_OK;

   if (numDecoderThreads > 1)

@@ -1221,8 +1391,10 @@
       }

   RINOK(res);

   #endif

+  

   RINOK(status.Res);

   encoders[0].progressInfoSpec[0]->SetFinishTime(info);

+  

   #ifndef _7ZIP_ST

   #ifdef UNDER_CE

   if (numDecoderThreads > 1)

@@ -1235,22 +1407,26 @@
       }

   #endif

   #endif

+  

   info.UnpackSize = 0;

   info.PackSize = 0;

   info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;

+  

   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

     info.UnpackSize += encoder.kBufferSize;

     info.PackSize += encoder.compressedSize;

   }

+  

   RINOK(callback->SetDecodeResult(info, false));

   RINOK(callback->SetDecodeResult(info, true));

+  

   return S_OK;

 }

 

 

-inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)

+static inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)

 {

   UInt32 hs = dictionary - 1;

   hs |= (hs >> 1);

@@ -1266,14 +1442,16 @@
       (1 << 20) + (multiThread ? (6 << 20) : 0);

 }

 

-UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)

+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench)

 {

   const UInt32 kBufferSize = dictionary;

-  const UInt32 kCompressedBufferSize = (kBufferSize / 2);

-  UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;

-  UInt32 numBigThreads = numThreads / numSubThreads;

-  return (kBufferSize + kCompressedBufferSize +

-    GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;

+  const UInt32 kCompressedBufferSize = kBufferSize; // / 2;

+  bool lzmaMt = (totalBench || numThreads > 1);

+  UInt32 numBigThreads = numThreads;

+  if (!totalBench && lzmaMt)

+    numBigThreads /= 2;

+  return ((UInt64)kBufferSize + kCompressedBufferSize +

+    GetLZMAUsage(lzmaMt, dictionary) + (2 << 20)) * numBigThreads;

 }

 

 static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations,

@@ -1301,7 +1479,6 @@
       sum ^= GetUi32(hash + j);

     if (checkSum && sum != *checkSum)

     {

-      // printf(" %08X ", sum);

       return S_FALSE;

     }

   }

@@ -1316,6 +1493,8 @@
 #define YY7 YY5 YY5 YY5 YY5

 static const UInt32 kNumFreqCommands = 128;

 

+EXTERN_C_BEGIN

+

 static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val)

 {

   for (UInt32 i = 0; i < num; i++)

@@ -1325,6 +1504,9 @@
   return sum;

 }

 

+EXTERN_C_END

+

+

 #ifndef _7ZIP_ST

 

 struct CFreqInfo

@@ -1392,6 +1574,10 @@
   CMyComPtr<IHasher> Hasher;

   HRESULT Res;

 

+  #ifdef USE_ALLOCA

+  size_t AllocaSize;

+  #endif

+

   void Wait()

   {

     Thread.Wait();

@@ -1402,6 +1588,11 @@
 static THREAD_FUNC_DECL CrcThreadFunction(void *param)

 {

   CCrcInfo *p = (CCrcInfo *)param;

+  

+  #ifdef USE_ALLOCA

+  alloca(p->AllocaSize);

+  #endif

+

   p->Res = CrcBig(p->Data, p->Size, p->NumIterations,

       p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher,

       p->Callback);

@@ -1475,6 +1666,7 @@
 

 struct CBenchMethod

 {

+  unsigned Weight;

   unsigned DictBits;

   UInt32 EncComplex;

   UInt32 DecComplexCompr;

@@ -1484,27 +1676,33 @@
 

 static const CBenchMethod g_Bench[] =

 {

-  { 17,  357,  145,   20, "LZMA:x1" },

-  { 24, 1220,  145,   20, "LZMA:x5:mt1" },

-  { 24, 1220,  145,   20, "LZMA:x5:mt2" },

-  { 16,  124,   40,   14, "Deflate:x1" },

-  { 16,  376,   40,   14, "Deflate:x5" },

-  { 16, 1082,   40,   14, "Deflate:x7" },

-  { 17,  422,   40,   14, "Deflate64:x5" },

-  { 15,  590,   69,   69, "BZip2:x1" },

-  { 19,  815,  122,  122, "BZip2:x5" },

-  { 19,  815,  122,  122, "BZip2:x5:mt2" },

-  { 19, 2530,  122,  122, "BZip2:x7" },

-  { 18, 1010,    0, 1150, "PPMD:x1" },

-  { 22, 1655,    0, 1830, "PPMD:x5" },

-  {  0,    6,    0,    6, "Delta:4" },

-  {  0,    4,    0,    4, "BCJ" },

-  {  0,   24,    0,   24, "AES256CBC:1" },

-  {  0,    8,    0,    2, "AES256CBC:2" }

+  { 40, 17,  357,  145,   20, "LZMA:x1" },

+  { 80, 24, 1220,  145,   20, "LZMA:x5:mt1" },

+  { 80, 24, 1220,  145,   20, "LZMA:x5:mt2" },

+

+  { 10, 16,  124,   40,   14, "Deflate:x1" },

+  { 20, 16,  376,   40,   14, "Deflate:x5" },

+  { 10, 16, 1082,   40,   14, "Deflate:x7" },

+  { 10, 17,  422,   40,   14, "Deflate64:x5" },

+

+  { 10, 15,  590,   69,   69, "BZip2:x1" },

+  { 20, 19,  815,  122,  122, "BZip2:x5" },

+  { 10, 19,  815,  122,  122, "BZip2:x5:mt2" },

+  { 10, 19, 2530,  122,  122, "BZip2:x7" },

+

+  { 10, 18, 1010,    0, 1150, "PPMD:x1" },

+  { 10, 22, 1655,    0, 1830, "PPMD:x5" },

+

+  {  2,  0,    6,    0,    6, "Delta:4" },

+  {  2,  0,    4,    0,    4, "BCJ" },

+

+  { 10,  0,   24,    0,   24, "AES256CBC:1" },

+  {  2,  0,    8,    0,    2, "AES256CBC:2" }

 };

 

 struct CBenchHash

 {

+  unsigned Weight;

   UInt32 Complex;

   UInt32 CheckSum;

   const char *Name;

@@ -1512,33 +1710,40 @@
 

 static const CBenchHash g_Hash[] =

 {

-  {   558, 0x8F8FEDAB, "CRC32:4" },

-  {   339, 0x8F8FEDAB, "CRC32:8" },

-  {   512, 0xDF1C17CC, "CRC64" },

-  { 11900, 0x2D79FF2E, "SHA256" },

-  {  5230, 0x4C25132B, "SHA1" }

+  {  1,  1820, 0x8F8FEDAB, "CRC32:1" },

+  { 10,   558, 0x8F8FEDAB, "CRC32:4" },

+  { 10,   339, 0x8F8FEDAB, "CRC32:8" },

+  { 10,   512, 0xDF1C17CC, "CRC64" },

+  { 10,  5100, 0x2D79FF2E, "SHA256" },

+  { 10,  2340, 0x4C25132B, "SHA1" },

+  {  2,  5500, 0xE084E913, "BLAKE2sp" }

 };

 

 struct CTotalBenchRes

 {

-  UInt64 NumIterations;

+  // UInt64 NumIterations1; // for Usage

+  UInt64 NumIterations2; // for Rating / RPU

+

   UInt64 Rating;

   UInt64 Usage;

   UInt64 RPU;

-  void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }

+  

+  void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; }

+

   void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2)

   {

     Rating = (r1.Rating + r2.Rating);

     Usage = (r1.Usage + r2.Usage);

     RPU = (r1.RPU + r2.RPU);

-    NumIterations = (r1.NumIterations + r2.NumIterations);

+    // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1);

+    NumIterations2 = (r1.NumIterations2 + r2.NumIterations2);

   }

 };

 

-static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size)

+static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size)

 {

   char s[128];

-  int startPos = (int)sizeof(s) - 32;

+  unsigned startPos = (unsigned)sizeof(s) - 32;

   memset(s, ' ', startPos);

   ConvertUInt64ToString(value, s + startPos);

   // if (withSpace)

@@ -1546,7 +1751,7 @@
     startPos--;

     size++;

   }

-  int len = (int)strlen(s + startPos);

+  unsigned len = (unsigned)strlen(s + startPos);

   if (size > len)

   {

     startPos -= (size - len);

@@ -1556,31 +1761,31 @@
   f.Print(s + startPos);

 }

 

-static const int kFieldSize_Name = 12;

-static const int kFieldSize_SmallName = 4;

-static const int kFieldSize_Speed = 9;

-static const int kFieldSize_Usage = 5;

-static const int kFieldSize_RU = 6;

-static const int kFieldSize_Rating = 6;

-static const int kFieldSize_EU = 5;

-static const int kFieldSize_Effec = 5;

+static const unsigned kFieldSize_Name = 12;

+static const unsigned kFieldSize_SmallName = 4;

+static const unsigned kFieldSize_Speed = 9;

+static const unsigned kFieldSize_Usage = 5;

+static const unsigned kFieldSize_RU = 6;

+static const unsigned kFieldSize_Rating = 6;

+static const unsigned kFieldSize_EU = 5;

+static const unsigned kFieldSize_Effec = 5;

 

-static const int kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating;

-static const int kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec;

+static const unsigned kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating;

+static const unsigned kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec;

 

 

-static void PrintRating(IBenchPrintCallback &f, UInt64 rating, int size)

+static void PrintRating(IBenchPrintCallback &f, UInt64 rating, unsigned size)

 {

   PrintNumber(f, (rating + 500000) / 1000000, size);

 }

 

 

-static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, int size)

+static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, unsigned size)

 {

   PrintNumber(f, (val * 100 + divider / 2) / divider, size);

 }

 

-static void PrintChars(IBenchPrintCallback &f, char c, int size)

+static void PrintChars(IBenchPrintCallback &f, char c, unsigned size)

 {

   char s[256];

   memset(s, (Byte)c, size);

@@ -1588,7 +1793,7 @@
   f.Print(s);

 }

 

-static void PrintSpaces(IBenchPrintCallback &f, int size)

+static void PrintSpaces(IBenchPrintCallback &f, unsigned size)

 {

   PrintChars(f, ' ', size);

 }

@@ -1613,7 +1818,12 @@
   }

 }

 

-static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res)

+static void PrintResults(IBenchPrintCallback *f,

+    const CBenchInfo &info,

+    unsigned weight,

+    UInt64 rating,

+    bool showFreq, UInt64 cpuFreq,

+    CTotalBenchRes *res)

 {

   UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations);

   if (f)

@@ -1632,27 +1842,31 @@
 

   if (res)

   {

-    res->NumIterations++;

-    res->RPU += rpu;

-    res->Rating += rating;

-    res->Usage += usage;

+    // res->NumIterations1++;

+    res->NumIterations2 += weight;

+    res->RPU += (rpu * weight);

+    res->Rating += (rating * weight);

+    res->Usage += (usage * weight);

   }

 }

 

 static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, const CTotalBenchRes &res)

 {

   PrintSpaces(f, 1 + kFieldSize_Speed);

-  UInt64 numIterations = res.NumIterations;

-  if (numIterations == 0)

-    numIterations = 1;

-  PrintResults(f, res.Usage / numIterations, res.RPU / numIterations, res.Rating / numIterations, showFreq, cpuFreq);

+  // UInt64 numIterations1 = res.NumIterations1; if (numIterations1 == 0) numIterations1 = 1;

+  UInt64 numIterations2 = res.NumIterations2; if (numIterations2 == 0) numIterations2 = 1;

+  PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq);

 }

 

-static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)

+static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString,

+    bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads)

 {

   f.Print("RAM ");

   f.Print(sizeString);

-  PrintNumber(f, (size >> 20), 6);

+  if (size_Defined)

+    PrintNumber(f, (size >> 20), 6);

+  else

+    f.Print("      ?");

   f.Print(" MB,  # ");

   f.Print(threadsString);

   PrintNumber(f, numThreads, 3);

@@ -1668,12 +1882,22 @@
   UInt32 DictSize;

 

   bool Use2Columns;

-  int NameFieldSize;

+  unsigned NameFieldSize;

 

   bool ShowFreq;

   UInt64 CpuFreq;

 

-  CBenchCallbackToPrint(): Use2Columns(false), NameFieldSize(0), ShowFreq(false), CpuFreq(0) {}

+  unsigned EncodeWeight;

+  unsigned DecodeWeight;

+

+  CBenchCallbackToPrint():

+      Use2Columns(false),

+      NameFieldSize(0),

+      ShowFreq(false),

+      CpuFreq(0),

+      EncodeWeight(1),

+      DecodeWeight(1)

+      {}

 

   void Init() { EncodeRes.Init(); DecodeRes.Init(); }

   void Print(const char *s);

@@ -1697,7 +1921,11 @@
   if (final)

   {

     UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations);

-    PrintResults(_file, info, rating, ShowFreq, CpuFreq, &EncodeRes);

+    PrintResults(_file, info,

+        EncodeWeight, rating,

+        ShowFreq, CpuFreq, &EncodeRes);

+    if (!Use2Columns)

+      _file->NewLine();

   }

   return S_OK;

 }

@@ -1713,15 +1941,14 @@
     if (Use2Columns)

       _file->Print(kSep);

     else

-    {

-      _file->NewLine();

       PrintSpaces(*_file, NameFieldSize);

-    }

     CBenchInfo info2 = info;

     info2.UnpackSize *= info2.NumIterations;

     info2.PackSize *= info2.NumIterations;

     info2.NumIterations = 1;

-    PrintResults(_file, info2, rating, ShowFreq, CpuFreq, &DecodeRes);

+    PrintResults(_file, info2,

+        DecodeWeight, rating,

+        ShowFreq, CpuFreq, &DecodeRes);

   }

   return S_OK;

 }

@@ -1755,29 +1982,40 @@
 static HRESULT TotalBench(

     DECL_EXTERNAL_CODECS_LOC_VARS

     UInt64 complexInCommands,

-    UInt32 numThreads, bool forceUnpackSize, UInt32 unpackSize, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback)

+    UInt32 numThreads,

+    bool forceUnpackSize,

+    size_t unpackSize,

+    const Byte *fileData,

+    IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback)

 {

   for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)

   {

-    CBenchMethod bench = g_Bench[i];

+    const CBenchMethod &bench = g_Bench[i];

     PrintLeft(*callback->_file, bench.Name, kFieldSize_Name);

     callback->BenchProps.DecComplexUnc = bench.DecComplexUnc;

     callback->BenchProps.DecComplexCompr = bench.DecComplexCompr;

     callback->BenchProps.EncComplex = bench.EncComplex;

+    

     COneMethodInfo method;

     NCOM::CPropVariant propVariant;

     propVariant = bench.Name;

-    RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant));

+    RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));

 

-    UInt32 unpackSize2 = unpackSize;

+    size_t unpackSize2 = unpackSize;

     if (!forceUnpackSize && bench.DictBits == 0)

       unpackSize2 = kFilterUnpackSize;

 

+    callback->EncodeWeight = bench.Weight;

+    callback->DecodeWeight = bench.Weight;

+

     HRESULT res = MethodBench(

         EXTERNAL_CODECS_LOC_VARS

         complexInCommands,

-        false, numThreads, method, unpackSize2, bench.DictBits,

+        false, numThreads, method,

+        unpackSize2, fileData,

+        bench.DictBits,

         printCallback, callback, &callback->BenchProps);

+    

     if (res == E_NOTIMPL)

     {

       // callback->Print(" ---");

@@ -1789,6 +2027,7 @@
     {

       RINOK(res);

     }

+    

     callback->NewLine();

   }

   return S_OK;

@@ -1800,6 +2039,7 @@
     UInt32 numThreads,

     IBenchPrintCallback *_file,

     bool showFreq,

+    UInt64 specifiedFreq,

     UInt64 &cpuFreq,

     UInt32 &res)

 {

@@ -1861,6 +2101,7 @@
     }

     res += sum;

   }

+  

   CBenchInfo info;

   progressInfoSpec.SetFinishTime(info);

 

@@ -1874,7 +2115,10 @@
       UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity;

       UInt64 rating = info.GetSpeed(numCommands);

       cpuFreq = rating / numThreads;

-      PrintResults(_file, info, rating, showFreq, showFreq ? cpuFreq : 0, NULL);

+      PrintResults(_file, info,

+          0, // weight

+          rating,

+          showFreq, showFreq ? (specifiedFreq != 0 ? specifiedFreq : cpuFreq) : 0, NULL);

     }

     RINOK(_file->CheckBreak());

   }

@@ -1889,7 +2133,7 @@
     UInt64 complexInCommands,

     UInt32 numThreads, UInt32 bufferSize,

     UInt64 &speed,

-    UInt32 complexity,

+    UInt32 complexity, unsigned benchWeight,

     const UInt32 *checkSum,

     const COneMethodInfo &method,

     IBenchPrintCallback *_file,

@@ -1903,7 +2147,7 @@
   numThreads = 1;

   #endif

 

-  UString methodName = method.MethodName;

+  AString methodName = method.MethodName;

   // methodName.RemoveChar(L'-');

   CMethodId hashID;

   if (!FindHashMethod(

@@ -1932,11 +2176,12 @@
   if (numThreads > 1)

   {

     threads.Items = new CCrcInfo[numThreads];

+    

     UInt32 i;

     for (i = 0; i < numThreads; i++)

     {

       CCrcInfo &info = threads.Items[i];

-      UString name;

+      AString name;

       RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher));

       if (!info.Hasher)

         return E_NOTIMPL;

@@ -1960,8 +2205,14 @@
         info.CheckSum = *checkSum;

         info.CheckSumDefined = (checkSum && (i == 0));

       }

+

+      #ifdef USE_ALLOCA

+      info.AllocaSize = (i * 16 * 21) & 0x7FF;

+      #endif

     }

+

     progressInfoSpec.SetStartTime();

+    

     for (i = 0; i < numThreads; i++)

     {

       CCrcInfo &info = threads.Items[i];

@@ -1980,7 +2231,7 @@
     /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG);

     progressInfoSpec.SetStartTime();

     CMyComPtr<IHasher> hasher;

-    UString name;

+    AString name;

     RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher));

     if (!hasher)

       return E_NOTIMPL;

@@ -1993,6 +2244,7 @@
     }

     RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file));

   }

+

   CBenchInfo info;

   progressInfoSpec.SetFinishTime(info);

 

@@ -2007,7 +2259,9 @@
     {

       UInt64 numCommands = unpSizeThreads * complexity / 256;

       UInt64 rating = info.GetSpeed(numCommands);

-      PrintResults(_file, info, rating, showFreq, cpuFreq, encodeRes);

+      PrintResults(_file, info,

+          benchWeight, rating,

+          showFreq, cpuFreq, encodeRes);

     }

     RINOK(_file->CheckBreak());

   }

@@ -2036,7 +2290,7 @@
     COneMethodInfo method;

     NCOM::CPropVariant propVariant;

     propVariant = bench.Name;

-    RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant));

+    RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));

 

     UInt64 speed;

     HRESULT res = CrcBench(

@@ -2044,7 +2298,8 @@
         complexInCommands,

         numThreads, bufSize,

         speed,

-        bench.Complex, &bench.CheckSum, method,

+        bench.Complex, bench.Weight,

+        &bench.CheckSum, method,

         printCallback, encodeRes, showFreq, cpuFreq);

     if (res == E_NOTIMPL)

     {

@@ -2087,19 +2342,104 @@
   return (num <= numThreads) ? num : numThreads;

 }

 

-static bool AreSameMethodNames(const char *fullName, const wchar_t *shortName)

+static bool AreSameMethodNames(const char *fullName, const char *shortName)

 {

   for (;;)

   {

-    wchar_t c2 = *shortName++;

+    char c2 = *shortName++;

     if (c2 == 0)

       return true;

     char c1 = *fullName++;

-    if ((unsigned char)MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))

+    if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))

       return false;

   }

 }

 

+

+#ifdef MY_CPU_X86_OR_AMD64

+

+static void PrintCpuChars(AString &s, UInt32 v)

+{

+  for (int j = 0; j < 4; j++)

+  {

+    Byte b = (Byte)(v & 0xFF);

+    v >>= 8;

+    if (b == 0)

+      break;

+    s += (char)b;

+  }

+}

+

+static void x86cpuid_to_String(const Cx86cpuid &c, AString &s)

+{

+  s.Empty();

+

+  UInt32 maxFunc2 = 0;

+  UInt32 t[3];

+

+  MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]);

+

+  bool fullNameIsAvail = (maxFunc2 >= 0x80000004);

+  

+  if (!fullNameIsAvail)

+  {

+    for (int i = 0; i < 3; i++)

+      PrintCpuChars(s, c.vendor[i]);

+  }

+  else

+  {

+    for (int i = 0; i < 3; i++)

+    {

+      UInt32 d[4] = { 0 };

+      MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]);

+      for (int j = 0; j < 4; j++)

+        PrintCpuChars(s, d[j]);

+    }

+  }

+

+  s.Add_Space_if_NotEmpty();

+  {

+    char temp[32];

+    ConvertUInt32ToHex(c.ver, temp);

+    s += '(';

+    s += temp;

+    s += ')';

+  }

+}

+

+#endif

+

+

+void GetCpuName(AString &s)

+{

+  s.Empty();

+

+  #ifdef MY_CPU_X86_OR_AMD64

+  {

+    Cx86cpuid cpuid;

+    if (x86cpuid_CheckAndRead(&cpuid))

+    {

+      x86cpuid_to_String(cpuid, s);

+      return;

+    }

+    #ifdef MY_CPU_AMD64

+    s = "x64";

+    #else

+    s = "x86";

+    #endif

+  }

+  #else

+  

+    #ifdef MY_CPU_LE

+      s = "LE";

+    #elif defined(MY_CPU_BE)

+      s = "BE";

+    #endif

+

+  #endif

+}

+

+

 HRESULT Bench(

     DECL_EXTERNAL_CODECS_LOC_VARS

     IBenchPrintCallback *printCallback,

@@ -2112,41 +2452,132 @@
     return S_FALSE;

 

   UInt32 numCPUs = 1;

-  UInt64 ramSize = (UInt64)512 << 20;

+  UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29;

+

   #ifndef _7ZIP_ST

   numCPUs = NSystem::GetNumberOfProcessors();

   #endif

-  #if !defined(_7ZIP_ST) || defined(_WIN32)

-  ramSize = NSystem::GetRamSize();

-  #endif

-  UInt32 numThreads = numCPUs;

+  

+  bool ramSize_Defined = NSystem::GetRamSize(ramSize);

+

+  UInt32 numThreadsSpecified = numCPUs;

 

   UInt32 testTime = kComplexInSeconds;

 

+  UInt64 specifiedFreq = 0;

+

+  bool multiThreadTests = false;

+

   COneMethodInfo method;

+

+  CBenchBuffer fileDataBuffer;

+

+  {

   unsigned i;

   for (i = 0; i < props.Size(); i++)

   {

     const CProperty &property = props[i];

-    NCOM::CPropVariant propVariant;

     UString name = property.Name;

     name.MakeLower_Ascii();

+

+    if (name.IsEqualTo("file"))

+    {

+      if (property.Value.IsEmpty())

+        return E_INVALIDARG;

+

+      #ifdef USE_WIN_FILE

+      

+      NFile::NIO::CInFile file;

+      if (!file.Open(us2fs(property.Value)))

+        return E_INVALIDARG;

+      UInt64 len;

+      if (!file.GetLength(len))

+        return E_FAIL;

+      if (len >= ((UInt32)1 << 31) || len == 0)

+        return E_INVALIDARG;

+      if (!fileDataBuffer.Alloc((size_t)len))

+        return E_OUTOFMEMORY;

+      UInt32 processedSize;

+      file.Read(fileDataBuffer.Buffer, (UInt32)len, processedSize);

+      if (processedSize != len)

+        return E_FAIL;

+      if (printCallback)

+      {

+        printCallback->Print("file size =");

+        // printCallback->Print(GetOemString(property.Value));

+        PrintNumber(*printCallback, len, 0);

+        printCallback->NewLine();

+      }

+      continue;

+

+      #else

+

+      return E_NOTIMPL;

+      

+      #endif

+    }

+

+    NCOM::CPropVariant propVariant;

     if (!property.Value.IsEmpty())

       ParseNumberString(property.Value, propVariant);

-    if (name.IsEqualTo("testtime"))

+    

+    if (name.IsEqualTo("time"))

     {

       RINOK(ParsePropToUInt32(L"", propVariant, testTime));

       continue;

     }

-    if (name.IsPrefixedBy(L"mt"))

+    

+    if (name.IsEqualTo("freq"))

     {

+      UInt32 freq32 = 0;

+      RINOK(ParsePropToUInt32(L"", propVariant, freq32));

+      if (freq32 == 0)

+        return E_INVALIDARG;

+      specifiedFreq = (UInt64)freq32 * 1000000;

+

+      if (printCallback)

+      {

+        printCallback->Print("freq=");

+        PrintNumber(*printCallback, freq32, 0);

+        printCallback->NewLine();

+      }

+

+      continue;

+    }

+

+    if (name.IsPrefixedBy_Ascii_NoCase("mt"))

+    {

+      UString s = name.Ptr(2);

+      if (s == L"*")

+      {

+        multiThreadTests = true;

+        continue;

+      }

+      if (s.IsEmpty() && propVariant.vt == VT_BSTR)

+      {

+        if (wcscmp(propVariant.bstrVal, L"*") == 0)

+        {

+          multiThreadTests = true;

+          continue;

+        }

+      }

       #ifndef _7ZIP_ST

-      RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads));

+      RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified));

       #endif

       continue;

     }

+    

     RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));

   }

+  }

+

+  if (printCallback)

+  {

+    AString s;

+    GetCpuName(s);

+    printCallback->Print(s);

+    printCallback->NewLine();

+  }

 

   if (printCallback)

   {

@@ -2155,25 +2586,50 @@
 

   UInt64 complexInCommands = kComplexInCommands;

 

-  if (printCallback)

+  if (printCallback /* || benchCallback */)

   {

-    UInt64 numMilCommands = (1 << 6);

+    UInt64 numMilCommands = 1 << 6;

+    if (specifiedFreq != 0)

+    {

+      while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000))

+        numMilCommands >>= 1;

+    }

 

     for (int jj = 0;; jj++)

     {

+      if (printCallback)

+        RINOK(printCallback->CheckBreak());

+

       UInt64 start = ::GetTimeCount();

       UInt32 sum = (UInt32)start;

       sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp);

-      start = ::GetTimeCount() - start;

+      const UInt64 realDelta = ::GetTimeCount() - start;

+      start = realDelta;

       if (start == 0)

         start = 1;

       UInt64 freq = GetFreq();

-      UInt64 mipsVal = numMilCommands * freq / start;

+      // mips is constant in some compilers

+      const UInt64 mipsVal = numMilCommands * freq / start;

       if (printCallback)

-        PrintNumber(*printCallback, mipsVal, 5 + ((sum >> 31) & 1));

+      {

+        if (realDelta == 0)

+        {

+          printCallback->Print(" -");

+        }

+        else

+        {

+          // PrintNumber(*printCallback, start, 0);

+          PrintNumber(*printCallback, mipsVal, 5 + ((sum == 0xF1541213) ? 1 : 0));

+        }

+      }

+      /*

+      if (benchCallback)

+        benchCallback->AddCpuFreq(mipsVal);

+      */

+

       if (jj >= 3)

       {

-        SetComplexCommands(testTime, mipsVal * 1000000, complexInCommands);

+        SetComplexCommands(testTime, false, mipsVal * 1000000, complexInCommands);

         if (jj >= 8 || start >= freq)

           break;

         // break; // change it

@@ -2181,21 +2637,22 @@
       }

     }

   }

+

   if (printCallback)

   {

     printCallback->NewLine();

     printCallback->NewLine();

-    PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs);

+    PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs);

   }

 

-  if (numThreads < 1 || numThreads > kNumThreadsMax)

+  if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax)

     return E_INVALIDARG;

 

   UInt32 dict;

   bool dictIsDefined = method.Get_DicSize(dict);

 

   if (method.MethodName.IsEmpty())

-    method.MethodName = L"LZMA";

+    method.MethodName = "LZMA";

 

   if (benchCallback)

   {

@@ -2206,16 +2663,18 @@
     return MethodBench(

         EXTERNAL_CODECS_LOC_VARS

         complexInCommands,

-        true, numThreads,

-        method, uncompressedDataSize,

+        true, numThreadsSpecified,

+        method,

+        uncompressedDataSize, fileDataBuffer.Buffer,

         kOldLzmaDictBits, printCallback, benchCallback, &benchProps);

   }

 

-  UString methodName = method.MethodName;

-  if (methodName.IsEqualToNoCase(L"CRC"))

-    methodName = L"crc32";

+  AString methodName = method.MethodName;

+  if (methodName.IsEqualTo_Ascii_NoCase("CRC"))

+    methodName = "crc32";

   method.MethodName = methodName;

   CMethodId hashID;

+  

   if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID))

   {

     if (!printCallback)

@@ -2232,11 +2691,20 @@
       for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)

       {

         const CBenchHash &h = g_Hash[i];

-        if (AreSameMethodNames(h.Name, methodName))

+        AString s = h.Name;

+        AString hProp;

+        int propPos = s.Find(':');

+        if (propPos >= 0)

+        {

+          hProp = s.Ptr(propPos + 1);

+          s.DeleteFrom(propPos);

+        }

+

+        if (AreSameMethodNames(s, methodName))

         {

           complexity = h.Complex;

           checkSum = &h.CheckSum;

-          if (strcmp(h.Name, "CRC32:4") != 0)

+          if (method.PropsString.IsEqualTo_Ascii_NoCase(hProp))

             break;

         }

       }

@@ -2244,14 +2712,14 @@
 

     f.NewLine();

     f.Print("Size");

-    const int kFieldSize_CrcSpeed = 6;

+    const unsigned kFieldSize_CrcSpeed = 6;

     unsigned numThreadsTests = 0;

     for (;;)

     {

-      UInt32 t = GetNumThreadsNext(numThreadsTests, numThreads);

+      UInt32 t = GetNumThreadsNext(numThreadsTests, numThreadsSpecified);

       PrintNumber(f, t, kFieldSize_CrcSpeed);

       numThreadsTests++;

-      if (t >= numThreads)

+      if (t >= numThreadsSpecified)

         break;

     }

     f.NewLine();

@@ -2272,7 +2740,7 @@
           break;

         char s[16];

         ConvertUInt32ToString(pow, s);

-        int pos = MyStringLen(s);

+        unsigned pos = MyStringLen(s);

         s[pos++] = ':';

         s[pos++] = ' ';

         s[pos] = 0;

@@ -2281,10 +2749,12 @@
         for (unsigned ti = 0; ti < numThreadsTests; ti++)

         {

           RINOK(f.CheckBreak());

-          UInt32 t = GetNumThreadsNext(ti, numThreads);

+          UInt32 t = GetNumThreadsNext(ti, numThreadsSpecified);

           UInt64 speed = 0;

           RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands,

-              t, bufSize, speed, complexity,

+              t, bufSize, speed,

+              complexity,

+              1, // benchWeight,

               (pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0));

           PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed);

           speedTotals.Values[ti] += speed;

@@ -2308,23 +2778,81 @@
 

   bool use2Columns = false;

 

+  bool totalBenchMode = (method.MethodName.IsEqualTo_Ascii_NoCase("*"));

+  bool onlyHashBench = false;

+  if (method.MethodName.IsEqualTo_Ascii_NoCase("hash"))

+  {

+    onlyHashBench = true;

+    totalBenchMode = true;

+  }

+

+  // ---------- Threads loop ----------

+  for (unsigned threadsPassIndex = 0; threadsPassIndex < 3; threadsPassIndex++)

+  {

+

+  UInt32 numThreads = numThreadsSpecified;

+    

+  if (!multiThreadTests)

+  {

+    if (threadsPassIndex != 0)

+      break;

+  }

+  else

+  {

+    numThreads = 1;

+    if (threadsPassIndex != 0)

+    {

+      if (numCPUs < 2)

+        break;

+      numThreads = numCPUs;

+      if (threadsPassIndex == 1)

+      {

+        if (numCPUs >= 4)

+          numThreads = numCPUs / 2;

+      }

+      else if (numCPUs < 4)

+        break;

+    }

+  }

+ 

   CBenchCallbackToPrint callback;

   callback.Init();

   callback._file = printCallback;

+  

+  IBenchPrintCallback &f = *printCallback;

+

+  if (threadsPassIndex > 0)

+  {

+    f.NewLine();

+    f.NewLine();

+  }

 

   if (!dictIsDefined)

   {

-    int dicSizeLog;

-    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)

-      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)

+    const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25);

+    unsigned dicSizeLog = dicSizeLog_Main;

+    

+    #ifdef UNDER_CE

+    dicSizeLog = (UInt64)1 << 20;

+    #endif

+

+    if (ramSize_Defined)

+    for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)

+      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog), totalBenchMode) + (8 << 20) <= ramSize)

         break;

-    dict = (1 << dicSizeLog);

+

+    dict = (UInt32)1 << dicSizeLog;

+

+    if (totalBenchMode && dicSizeLog != dicSizeLog_Main)

+    {

+      f.Print("Dictionary reduced to: ");

+      PrintNumber(f, dicSizeLog, 1);

+      f.NewLine();

+    }

   }

 

-  IBenchPrintCallback &f = *printCallback;

-  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dict), "Benchmark threads:   ", numThreads);

+  PrintRequirements(f, "usage:", true, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), "Benchmark threads:   ", numThreads);

 

-  bool totalBenchMode = (method.MethodName == L"*");

   f.NewLine();

 

   if (totalBenchMode)

@@ -2347,7 +2875,7 @@
     showFreq = true;

   }

 

-  int fileldSize = kFieldSize_TotalSize;

+  unsigned fileldSize = kFieldSize_TotalSize;

   if (showFreq)

     fileldSize += kFieldSize_EUAndEffec;

 

@@ -2385,7 +2913,7 @@
   

   for (j = 0; j < 2; j++)

   {

-    PrintRight(f, "KB/s", kFieldSize_Speed + 1);

+    PrintRight(f, "KiB/s", kFieldSize_Speed + 1);

     PrintRight(f, "%", kFieldSize_Usage + 1);

     PrintRight(f, "MIPS", kFieldSize_RU + 1);

     PrintRight(f, "MIPS", kFieldSize_Rating + 1);

@@ -2403,38 +2931,49 @@
   f.NewLine();

   f.NewLine();

 

+  if (specifiedFreq != 0)

+    cpuFreq = specifiedFreq;

+

+

   if (totalBenchMode)

   {

-    if (!dictIsDefined)

-      dict =

-        #ifdef UNDER_CE

-          (UInt64)1 << 20;

-        #else

-          (UInt64)1 << 24;

-        #endif

     for (UInt32 i = 0; i < numIterations; i++)

     {

       if (i != 0)

         printCallback->NewLine();

       HRESULT res;

 

-      int freqTest;

-      const int kNumCpuTests = 3;

-      for (freqTest = 0; freqTest < kNumCpuTests; freqTest++)

+      const unsigned kNumCpuTests = 3;

+      for (unsigned freqTest = 0; freqTest < kNumCpuTests; freqTest++)

       {

         PrintLeft(f, "CPU", kFieldSize_Name);

         UInt32 resVal;

-        RINOK(FreqBench(complexInCommands, numThreads, printCallback, freqTest == kNumCpuTests - 1, cpuFreq, resVal));

+        RINOK(FreqBench(complexInCommands, numThreads, printCallback,

+            (freqTest == kNumCpuTests - 1 || specifiedFreq != 0), // showFreq

+            specifiedFreq,

+            cpuFreq, resVal));

         callback.NewLine();

 

+        if (specifiedFreq != 0)

+          cpuFreq = specifiedFreq;

+

         if (freqTest == kNumCpuTests - 1)

-          SetComplexCommands(testTime, cpuFreq, complexInCommands);

+          SetComplexCommands(testTime, specifiedFreq != 0, cpuFreq, complexInCommands);

       }

       callback.NewLine();

 

       callback.SetFreq(true, cpuFreq);

-      res = TotalBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, dictIsDefined, dict, printCallback, &callback);

-      RINOK(res);

+

+      if (!onlyHashBench)

+      {

+        res = TotalBench(EXTERNAL_CODECS_LOC_VARS

+            complexInCommands, numThreads,

+            dictIsDefined || fileDataBuffer.Buffer, // forceUnpackSize

+            fileDataBuffer.Buffer ? fileDataBuffer.BufferSize : dict,

+            fileDataBuffer.Buffer,

+            printCallback, &callback);

+        RINOK(res);

+      }

 

       res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads,

           1 << kNumHashDictBits, printCallback, &callback, &callback.EncodeRes, true, cpuFreq);

@@ -2445,7 +2984,10 @@
         PrintLeft(f, "CPU", kFieldSize_Name);

         UInt32 resVal;

         UInt64 cpuFreqLastTemp = cpuFreq;

-        RINOK(FreqBench(complexInCommands, numThreads, printCallback, false, cpuFreqLastTemp, resVal));

+        RINOK(FreqBench(complexInCommands, numThreads, printCallback,

+            specifiedFreq != 0, // showFreq

+            specifiedFreq,

+            cpuFreqLastTemp, resVal));

         callback.NewLine();

       }

     }

@@ -2453,7 +2995,7 @@
   else

   {

     bool needSetComplexity = true;

-    if (!methodName.IsEqualToNoCase(L"LZMA"))

+    if (!methodName.IsEqualTo_Ascii_NoCase("LZMA"))

     {

       for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)

       {

@@ -2472,7 +3014,7 @@
     if (needSetComplexity)

       callback.BenchProps.SetLzmaCompexity();

 

-  for (i = 0; i < numIterations; i++)

+  for (unsigned i = 0; i < numIterations; i++)

   {

     const unsigned kStartDicLog = 22;

     unsigned pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;

@@ -2492,7 +3034,7 @@
 

       COneMethodInfo method2 = method;

 

-      if (StringsAreEqualNoCase_Ascii(method2.MethodName, L"LZMA"))

+      if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA"))

       {

         // We add dictionary size property.

         // method2 can have two different dictionary size properties.

@@ -2501,15 +3043,24 @@
         RINOK(method2.ParseMethodFromPROPVARIANT(L"d", propVariant));

       }

 

-      UInt32 uncompressedDataSize = callback.DictSize;

-      if (uncompressedDataSize >= (1 << 18))

-        uncompressedDataSize += kAdditionalSize;

+      size_t uncompressedDataSize;

+      if (fileDataBuffer.Buffer)

+      {

+        uncompressedDataSize = fileDataBuffer.BufferSize;

+      }

+      else

+      {

+        uncompressedDataSize = callback.DictSize;

+        if (uncompressedDataSize >= (1 << 18))

+          uncompressedDataSize += kAdditionalSize;

+      }

 

       HRESULT res = MethodBench(

           EXTERNAL_CODECS_LOC_VARS

           complexInCommands,

           true, numThreads,

-          method2, uncompressedDataSize,

+          method2,

+          uncompressedDataSize, fileDataBuffer.Buffer,

           kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps);

       f.NewLine();

       RINOK(res);

@@ -2526,7 +3077,9 @@
     f.Print(kSep);

     PrintChars(f, '-', fileldSize);

   }

+

   f.NewLine();

+  

   if (use2Columns)

   {

     PrintLeft(f, "Avr:", callback.NameFieldSize);

@@ -2535,10 +3088,13 @@
     PrintTotals(f, showFreq, cpuFreq, callback.DecodeRes);

     f.NewLine();

   }

+  

   PrintLeft(f, "Tot:", callback.NameFieldSize);

   CTotalBenchRes midRes;

   midRes.SetSum(callback.EncodeRes, callback.DecodeRes);

   PrintTotals(f, showFreq, cpuFreq, midRes);

   f.NewLine();

+

+  }

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h
index 6af2942..7f9e05c 100644
--- a/CPP/7zip/UI/Common/Bench.h
+++ b/CPP/7zip/UI/Common/Bench.h
@@ -32,9 +32,9 @@
 UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size);

 UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations);

 

-const int kBenchMinDicLogSize = 18;

+const unsigned kBenchMinDicLogSize = 18;

 

-UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);

+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench = false);

 

 struct IBenchPrintCallback

 {

diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
index b568c06..0c13e9e 100644
--- a/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/CPP/7zip/UI/Common/DefaultName.cpp
@@ -7,21 +7,23 @@
 static UString GetDefaultName3(const UString &fileName,

     const UString &extension, const UString &addSubExtension)

 {

-  int extLength = extension.Len();

-  int fileNameLength = fileName.Len();

-  if (fileNameLength > extLength + 1)

+  const unsigned extLen = extension.Len();

+  const unsigned fileNameLen = fileName.Len();

+  

+  if (fileNameLen > extLen + 1)

   {

-    int dotPos = fileNameLength - (extLength + 1);

+    const unsigned dotPos = fileNameLen - (extLen + 1);

     if (fileName[dotPos] == '.')

-      if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1)))

+      if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))

         return fileName.Left(dotPos) + addSubExtension;

   }

-  int dotPos = fileName.ReverseFind(L'.');

+  

+  int dotPos = fileName.ReverseFind_Dot();

   if (dotPos > 0)

     return fileName.Left(dotPos) + addSubExtension;

 

   if (addSubExtension.IsEmpty())

-    return fileName + L"~";

+    return fileName + L'~';

   else

     return fileName + addSubExtension;

 }

diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index 6a429ab..9e74cd1 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -11,6 +11,38 @@
 

 #include "../../Archive/IArchive.h"

 

+struct CDirItemsStat

+{

+  UInt64 NumDirs;

+  UInt64 NumFiles;

+  UInt64 NumAltStreams;

+  UInt64 FilesSize;

+  UInt64 AltStreamsSize;

+  

+  UInt64 NumErrors;

+  // UInt64 GetTotalItems() const { return NumDirs + NumFiles + NumAltStreams; }

+  

+  UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }

+  

+  CDirItemsStat():

+      NumDirs(0),

+      NumFiles(0),

+      NumAltStreams(0),

+      FilesSize(0),

+      AltStreamsSize(0),

+      NumErrors(0)

+    {}

+};

+

+#define INTERFACE_IDirItemsCallback(x) \

+  virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \

+  virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \

+

+struct IDirItemsCallback

+{

+  INTERFACE_IDirItemsCallback(=0)

+};

+

 struct CDirItem

 {

   UInt64 Size;

@@ -46,7 +78,7 @@
 

   UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;

 

-  void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);

+  HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);

 

 public:

   CObjectVector<CDirItem> Items;

@@ -54,26 +86,14 @@
   bool SymLinks;

 

   bool ScanAltStreams;

-  FStringVector ErrorPaths;

-  CRecordVector<DWORD> ErrorCodes;

-  UInt64 TotalSize;

-

+  

+  CDirItemsStat Stat;

 

   #ifndef UNDER_CE

-  void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,

+  HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,

       const FString &phyPrefix);

   #endif

 

-  void AddError(const FString &path, DWORD errorCode)

-  {

-    ErrorCodes.Add(errorCode);

-    ErrorPaths.Add(path);

-  }

-

-  void AddError(const FString &path)

-  {

-    AddError(path, ::GetLastError());

-  }

 

   #if defined(_WIN32) && !defined(UNDER_CE)

 

@@ -82,19 +102,30 @@
   bool _saclEnabled;

   bool ReadSecure;

   

-  void AddSecurityItem(const FString &path, int &secureIndex);

+  HRESULT AddSecurityItem(const FString &path, int &secureIndex);

 

   #endif

 

+  IDirItemsCallback *Callback;

+

   CDirItems();

 

-  int GetNumFolders() const { return Prefixes.Size(); }

-  UString GetPhyPath(unsigned index) const;

+  void AddDirFileInfo(int phyParent, int logParent, int secureIndex,

+      const NWindows::NFile::NFind::CFileInfo &fi);

+

+  HRESULT AddError(const FString &path, DWORD errorCode);

+  HRESULT AddError(const FString &path);

+

+  HRESULT ScanProgress(const FString &path);

+

+  // unsigned GetNumFolders() const { return Prefixes.Size(); }

+  FString GetPhyPath(unsigned index) const;

   UString GetLogPath(unsigned index) const;

 

   unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);

   void DeleteLastPrefix();

-  void EnumerateItems2(

+  

+  HRESULT EnumerateItems2(

     const FString &phyPrefix,

     const UString &logPrefix,

     const FStringVector &filePaths,

diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index 198a6ae..c7dec1d 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -2,6 +2,8 @@
 

 #include "StdAfx.h"

 

+#include <wchar.h>

+

 #include "../../../Common/Wildcard.h"

 

 #include "../../../Windows/FileDir.h"

@@ -19,8 +21,8 @@
 using namespace NFile;

 using namespace NName;

 

-void AddDirFileInfo(int phyParent, int logParent, int secureIndex,

-    const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems)

+void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,

+    const NFind::CFileInfo &fi)

 {

   CDirItem di;

   di.Size = fi.Size;

@@ -36,35 +38,72 @@
   #if defined(_WIN32) && !defined(UNDER_CE)

   // di.ShortName = fs2us(fi.ShortName);

   #endif

-  dirItems.Add(di);

+  Items.Add(di);

+  

+  if (fi.IsDir())

+    Stat.NumDirs++;

+  else if (fi.IsAltStream)

+  {

+    Stat.NumAltStreams++;

+    Stat.AltStreamsSize += fi.Size;

+  }

+  else

+  {

+    Stat.NumFiles++;

+    Stat.FilesSize += fi.Size;

+  }

+}

+

+HRESULT CDirItems::AddError(const FString &path, DWORD errorCode)

+{

+  Stat.NumErrors++;

+  if (Callback)

+    return Callback->ScanError(path, errorCode);

+  return S_OK;

+}

+

+HRESULT CDirItems::AddError(const FString &path)

+{

+  return AddError(path, ::GetLastError());

+}

+

+static const unsigned kScanProgressStepMask = (1 << 12) - 1;

+

+HRESULT CDirItems::ScanProgress(const FString &dirPath)

+{

+  if (Callback)

+    return Callback->ScanProgress(Stat, dirPath, true);

+  return S_OK;

 }

 

 UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const

 {

   UString path;

   unsigned len = name.Len();

+  

   int i;

   for (i = index; i >= 0; i = parents[i])

     len += Prefixes[i].Len();

-  unsigned totalLen = len;

-  wchar_t *p = path.GetBuffer(len);

-  p[len] = 0;

-  len -= name.Len();

-  memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t));

+  

+  wchar_t *p = path.GetBuf_SetEnd(len) + len;

+  

+  p -= name.Len();

+  wmemcpy(p, (const wchar_t *)name, name.Len());

+  

   for (i = index; i >= 0; i = parents[i])

   {

     const UString &s = Prefixes[i];

-    len -= s.Len();

-    memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t));

+    p -= s.Len();

+    wmemcpy(p, (const wchar_t *)s, s.Len());

   }

-  path.ReleaseBuffer(totalLen);

+  

   return path;

 }

 

-UString CDirItems::GetPhyPath(unsigned index) const

+FString CDirItems::GetPhyPath(unsigned index) const

 {

   const CDirItem &di = Items[index];

-  return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);

+  return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name));

 }

 

 UString CDirItems::GetLogPath(unsigned index) const

@@ -99,10 +138,11 @@
 

 CDirItems::CDirItems():

     SymLinks(false),

-    TotalSize(0)

+    ScanAltStreams(false)

     #ifdef _USE_SECURITY_CODE

     , ReadSecure(false)

     #endif

+    , Callback(NULL)

 {

   #ifdef _USE_SECURITY_CODE

   _saclEnabled = InitLocalPrivileges();

@@ -111,7 +151,7 @@
 

 #ifdef _USE_SECURITY_CODE

 

-void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)

+HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex)

 {

   secureIndex = -1;

 

@@ -124,11 +164,13 @@
 

   DWORD errorCode = 0;

   DWORD secureSize;

+  

   BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);

+  

   if (res)

   {

     if (secureSize == 0)

-      return;

+      return S_OK;

     if (secureSize > TempSecureBuf.Size())

       errorCode = ERROR_INVALID_FUNCTION;

   }

@@ -153,51 +195,61 @@
       }

     }

   }

+  

   if (res)

   {

     secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize);

-    return;

+    return S_OK;

   }

+  

   if (errorCode == 0)

     errorCode = ERROR_INVALID_FUNCTION;

-  AddError(path, errorCode);

+  return AddError(path, errorCode);

 }

 

 #endif

 

-void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)

+HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)

 {

+  RINOK(ScanProgress(phyPrefix));

+

   NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);

-  for (;;)

+  for (unsigned ttt = 0; ; ttt++)

   {

     NFind::CFileInfo fi;

     bool found;

     if (!enumerator.Next(fi, found))

     {

-      AddError(phyPrefix);

-      return;

+      return AddError(phyPrefix);

     }

     if (!found)

-      break;

+      return S_OK;

 

     int secureIndex = -1;

     #ifdef _USE_SECURITY_CODE

     if (ReadSecure)

-      AddSecurityItem(phyPrefix + fi.Name, secureIndex);

+    {

+      RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex));

+    }

     #endif

     

-    AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items);

+    AddDirFileInfo(phyParent, logParent, secureIndex, fi);

     

+    if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)

+    {

+      RINOK(ScanProgress(phyPrefix));

+    }

+

     if (fi.IsDir())

     {

       const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;

       unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2));

-      EnumerateDir(parent, parent, phyPrefix + name2);

+      RINOK(EnumerateDir(parent, parent, phyPrefix + name2));

     }

   }

 }

 

-void CDirItems::EnumerateItems2(

+HRESULT CDirItems::EnumerateItems2(

     const FString &phyPrefix,

     const UString &logPrefix,

     const FStringVector &filePaths,

@@ -213,13 +265,13 @@
     const FString phyPath = phyPrefix + filePath;

     if (!fi.Find(phyPath))

     {

-      AddError(phyPath);

+      RINOK(AddError(phyPath));

       continue;

     }

     if (requestedPaths)

       requestedPaths->Add(phyPath);

 

-    int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR);

+    int delimiter = filePath.ReverseFind_PathSepar();

     FString phyPrefixCur;

     int phyParentCur = phyParent;

     if (delimiter >= 0)

@@ -231,19 +283,23 @@
     int secureIndex = -1;

     #ifdef _USE_SECURITY_CODE

     if (ReadSecure)

-      AddSecurityItem(phyPath, secureIndex);

+    {

+      RINOK(AddSecurityItem(phyPath, secureIndex));

+    }

     #endif

 

-    AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items);

+    AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);

     

     if (fi.IsDir())

     {

       const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;

       unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));

-      EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2);

+      RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2));

     }

   }

+  

   ReserveDown();

+  return S_OK;

 }

 

 

@@ -256,8 +312,7 @@
     int phyParent, int logParent, const FString &phyPrefix,

     const UStringVector &addArchivePrefix,

     CDirItems &dirItems,

-    bool enterToSubFolders,

-    IEnumDirItemCallback *callback);

+    bool enterToSubFolders);

 

 static HRESULT EnumerateDirItems_Spec(

     const NWildcard::CCensorNode &curNode,

@@ -265,15 +320,14 @@
     const FString &phyPrefix,

     const UStringVector &addArchivePrefix,

     CDirItems &dirItems,

-    bool enterToSubFolders,

-    IEnumDirItemCallback *callback)

+    bool enterToSubFolders)

 {

   const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR;

   unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2));

   unsigned numItems = dirItems.Items.Size();

   HRESULT res = EnumerateDirItems(

       curNode, parent, parent, phyPrefix + name2,

-      addArchivePrefix, dirItems, enterToSubFolders, callback);

+      addArchivePrefix, dirItems, enterToSubFolders);

   if (numItems == dirItems.Items.Size())

     dirItems.DeleteLastPrefix();

   return res;

@@ -281,14 +335,15 @@
 

 #ifndef UNDER_CE

 

-static void EnumerateAltStreams(

+#ifdef _WIN32

+

+static HRESULT EnumerateAltStreams(

     const NFind::CFileInfo &fi,

     const NWildcard::CCensorNode &curNode,

-    int phyParent, int logParent, const FString &phyPrefix,

+    int phyParent, int logParent, const FString &fullPath,

     const UStringVector &addArchivePrefix,  // prefix from curNode

     CDirItems &dirItems)

 {

-  const FString fullPath = phyPrefix + fi.Name;

   NFind::CStreamEnumerator enumerator(fullPath);

   for (;;)

   {

@@ -296,11 +351,10 @@
     bool found;

     if (!enumerator.Next(si, found))

     {

-      dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL);

-      break;

+      return dirItems.AddError(fullPath + FTEXT(":*")); // , (DWORD)E_FAIL

     }

     if (!found)

-      break;

+      return S_OK;

     if (si.IsMainStream())

       continue;

     UStringVector addArchivePrefixNew = addArchivePrefix;

@@ -313,26 +367,28 @@
     fi2.Size = si.Size;

     fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;

     fi2.IsAltStream = true;

-    AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items);

-    dirItems.TotalSize += fi2.Size;

+    dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2);

   }

 }

 

-void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,

+#endif

+

+HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,

     const FString &phyPrefix)

 {

   if (!SymLinks || !fi.HasReparsePoint())

-    return;

+    return S_OK;

   const FString path = phyPrefix + fi.Name;

   CByteBuffer &buf = dirItem.ReparseData;

   if (NIO::GetReparseData(path, buf))

   {

     CReparseAttr attr;

     if (attr.Parse(buf, buf.Size()))

-      return;

+      return S_OK;

   }

-  AddError(path);

+  DWORD res = ::GetLastError();

   buf.Free();

+  return AddError(path , res);

 }

 

 #endif

@@ -343,8 +399,7 @@
     int phyParent, int logParent, const FString &phyPrefix,

     const UStringVector &addArchivePrefix,  // prefix from curNode

     CDirItems &dirItems,

-    bool enterToSubFolders,

-    IEnumDirItemCallback *callback)

+    bool enterToSubFolders)

 {

   const UString name = fs2us(fi.Name);

   bool enterToSubFolders2 = enterToSubFolders;

@@ -362,12 +417,13 @@
     int secureIndex = -1;

     #ifdef _USE_SECURITY_CODE

     if (dirItems.ReadSecure)

-      dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex);

+    {

+      RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));

+    }

     #endif

     

     dirItemIndex = dirItems.Items.Size();

-    AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);

-    dirItems.TotalSize += fi.Size;

+    dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);

     if (fi.IsDir())

       enterToSubFolders2 = true;

   }

@@ -375,14 +431,15 @@
   #ifndef UNDER_CE

   if (dirItems.ScanAltStreams)

   {

-    EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,

-        addArchivePrefixNew, dirItems);

+    RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,

+        phyPrefix + fi.Name,

+        addArchivePrefixNew, dirItems));

   }

 

   if (dirItemIndex >= 0)

   {

     CDirItem &dirItem = dirItems.Items[dirItemIndex];

-    dirItems.SetLinkInfo(dirItem, fi, phyPrefix);

+    RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix));

     if (dirItem.ReparseData.Size() != 0)

       return S_OK;

   }

@@ -412,7 +469,7 @@
       *nextNode, phyParent, logParent, fi.Name, phyPrefix,

       addArchivePrefixNew,

       dirItems,

-      enterToSubFolders2, callback);

+      enterToSubFolders2);

 }

 

 

@@ -424,11 +481,13 @@
     if (item.Recursive || item.PathParts.Size() != 1)

       return false;

     const UString &name = item.PathParts.Front();

+    /*

     if (name.IsEmpty())

       return false;

+    */

     

-    /* Windows doesn't support file name with wildcard.

-       but if another system supports file name with wildcard,

+    /* Windows doesn't support file name with wildcard

+       But if another system supports file name with wildcard,

        and wildcard mode is disabled, we can ignore wildcard in name */

     /*

     if (!item.WildcardParsing)

@@ -441,19 +500,30 @@
 }

 

 

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+static bool IsVirtualFsFolder(const FString &prefix, const UString &name)

+{

+  UString s = fs2us(prefix);

+  s += name;

+  s.Add_PathSepar();

+  return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0;

+}

+

+#endif

+

 static HRESULT EnumerateDirItems(

     const NWildcard::CCensorNode &curNode,

     int phyParent, int logParent, const FString &phyPrefix,

     const UStringVector &addArchivePrefix,  // prefix from curNode

     CDirItems &dirItems,

-    bool enterToSubFolders,

-    IEnumDirItemCallback *callback)

+    bool enterToSubFolders)

 {

   if (!enterToSubFolders)

     if (curNode.NeedCheckSubDirs())

       enterToSubFolders = true;

-  if (callback)

-    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));

+  

+  RINOK(dirItems.ScanProgress(phyPrefix));

 

   // try direct_names case at first

   if (addArchivePrefix.IsEmpty() && !enterToSubFolders)

@@ -469,25 +539,68 @@
       {

         const NWildcard::CItem &item = curNode.IncludeItems[i];

         const UString &name = item.PathParts.Front();

-        const FString fullPath = phyPrefix + us2fs(name);

+        FString fullPath = phyPrefix + us2fs(name);

+

+        #if defined(_WIN32) && !defined(UNDER_CE)

+        bool needAltStreams = true;

+        #endif

+

+        #ifdef _USE_SECURITY_CODE

+        bool needSecurity = true;

+        #endif

+        

+        if (phyPrefix.IsEmpty())

+        {

+          if (!item.ForFile)

+          {

+            /* we don't like some names for alt streams inside archive:

+               ":sname"     for "\"

+               "c:::sname"  for "C:\"

+               So we ignore alt streams for these cases */

+            if (name.IsEmpty())

+            {

+              #if defined(_WIN32) && !defined(UNDER_CE)

+              needAltStreams = false;

+              #endif

+

+              /*

+              // do we need to ignore security info for "\\" folder ?

+              #ifdef _USE_SECURITY_CODE

+              needSecurity = false;

+              #endif

+              */

+

+              fullPath = FCHAR_PATH_SEPARATOR;

+            }

+            #if defined(_WIN32) && !defined(UNDER_CE)

+            else if (item.IsDriveItem())

+            {

+              needAltStreams = false;

+              fullPath.Add_PathSepar();

+            }

+            #endif

+          }

+        }

+

         NFind::CFileInfo fi;

-        #ifdef _WIN32

-        if (phyPrefix.IsEmpty() && item.IsDriveItem())

+        #if defined(_WIN32) && !defined(UNDER_CE)

+        if (IsVirtualFsFolder(phyPrefix, name))

         {

           fi.SetAsDir();

-          fi.Name = fullPath;

+          fi.Name = us2fs(name);

         }

         else

         #endif

         if (!fi.Find(fullPath))

         {

-          dirItems.AddError(fullPath);

+          RINOK(dirItems.AddError(fullPath));

           continue;

         }

+

         bool isDir = fi.IsDir();

         if (isDir && !item.ForDir || !isDir && !item.ForFile)

         {

-          dirItems.AddError(fullPath, (DWORD)E_FAIL);

+          RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));

           continue;

         }

         {

@@ -499,30 +612,37 @@
         

         int secureIndex = -1;

         #ifdef _USE_SECURITY_CODE

-        if (dirItems.ReadSecure)

-          dirItems.AddSecurityItem(fullPath, secureIndex);

+        if (needSecurity && dirItems.ReadSecure)

+        {

+          RINOK(dirItems.AddSecurityItem(fullPath, secureIndex));

+        }

         #endif

 

-        AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);

+        dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);

 

         #ifndef UNDER_CE

         {

           CDirItem &dirItem = dirItems.Items.Back();

-          dirItems.SetLinkInfo(dirItem, fi, phyPrefix);

+          RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix));

           if (dirItem.ReparseData.Size() != 0)

+          {

+            if (fi.IsAltStream)

+              dirItems.Stat.AltStreamsSize -= fi.Size;

+            else

+              dirItems.Stat.FilesSize -= fi.Size;

             continue;

+          }

         }

         #endif

 

-        dirItems.TotalSize += fi.Size;

 

         #ifndef UNDER_CE

-        if (dirItems.ScanAltStreams)

+        if (needAltStreams && dirItems.ScanAltStreams)

         {

           UStringVector pathParts;

           pathParts.Add(fs2us(fi.Name));

-          EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,

-              pathParts, dirItems);

+          RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,

+              fullPath, pathParts, dirItems));

         }

         #endif

 

@@ -546,7 +666,7 @@
         }

 

         RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,

-            addArchivePrefixNew, dirItems, true, callback));

+            addArchivePrefixNew, dirItems, true));

       }

       

       for (i = 0; i < curNode.SubNodes.Size(); i++)

@@ -555,31 +675,50 @@
           if (!needEnterVector[i])

             continue;

         const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];

-        const FString fullPath = phyPrefix + us2fs(nextNode.Name);

+        FString fullPath = phyPrefix + us2fs(nextNode.Name);

         NFind::CFileInfo fi;

-        #ifdef _WIN32

-        if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name))

+        

+        if (phyPrefix.IsEmpty())

+        {

+          {

+            if (nextNode.Name.IsEmpty())

+              fullPath = FCHAR_PATH_SEPARATOR;

+            #ifdef _WIN32

+            else if (NWildcard::IsDriveColonName(nextNode.Name))

+              fullPath.Add_PathSepar();

+            #endif

+          }

+        }

+

+        // we don't want to call fi.Find() for root folder or virtual folder

+        if (phyPrefix.IsEmpty() && nextNode.Name.IsEmpty()

+            #if defined(_WIN32) && !defined(UNDER_CE)

+            || IsVirtualFsFolder(phyPrefix, nextNode.Name)

+            #endif

+            )

         {

           fi.SetAsDir();

-          fi.Name = fullPath;

+          fi.Name = us2fs(nextNode.Name);

         }

         else

-        #endif

-        if (!fi.Find(fullPath))

         {

-          if (!nextNode.AreThereIncludeItems())

+          if (!fi.Find(fullPath))

+          {

+            if (!nextNode.AreThereIncludeItems())

+              continue;

+            RINOK(dirItems.AddError(fullPath));

             continue;

-          dirItems.AddError(fullPath);

-          continue;

-        }

-        if (!fi.IsDir())

-        {

-          dirItems.AddError(fullPath, (DWORD)E_FAIL);

-          continue;

+          }

+        

+          if (!fi.IsDir())

+          {

+            RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));

+            continue;

+          }

         }

 

         RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,

-            UStringVector(), dirItems, false, callback));

+            UStringVector(), dirItems, false));

       }

 

       return S_OK;

@@ -625,7 +764,7 @@
         fi.Name = driveName;

 

         RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,

-            addArchivePrefix, dirItems, enterToSubFolders, callback));

+            addArchivePrefix, dirItems, enterToSubFolders));

       }

       return S_OK;

     }

@@ -641,18 +780,21 @@
     bool found;

     if (!enumerator.Next(fi, found))

     {

-      dirItems.AddError(phyPrefix);

+      RINOK(dirItems.AddError(phyPrefix));

       break;

     }

     if (!found)

       break;

 

-    if (callback && (ttt & 0xFF) == 0xFF)

-      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));

+    if (dirItems.Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)

+    {

+      RINOK(dirItems.ScanProgress(phyPrefix));

+    }

 

     RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,

-          addArchivePrefix, dirItems, enterToSubFolders, callback));

+          addArchivePrefix, dirItems, enterToSubFolders));

   }

+

   return S_OK;

 }

 

@@ -660,8 +802,7 @@
     const NWildcard::CCensor &censor,

     const NWildcard::ECensorPathMode pathMode,

     const UString &addPathPrefix,

-    CDirItems &dirItems,

-    IEnumDirItemCallback *callback)

+    CDirItems &dirItems)

 {

   FOR_VECTOR (i, censor.Pairs)

   {

@@ -679,8 +820,8 @@
     

     RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),

         dirItems,

-        false, // enterToSubFolders

-        callback));

+        false // enterToSubFolders

+        ));

   }

   dirItems.ReserveDown();

 

@@ -719,7 +860,7 @@
     // maybe we need to support networks paths also ?

 

     FString fullPathF;

-    if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF))

+    if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF))

       continue;

     UString fullPath = fs2us(fullPathF);

     const UString logPath = GetLogPath(i);

@@ -729,7 +870,7 @@
       continue;

     

     const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());

-    if (prefix.Back() != WCHAR_PATH_SEPARATOR)

+    if (!IsPathSepar(prefix.Back()))

       continue;

 

     unsigned rootPrefixSize = GetRootPrefixSize(prefix);

diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
index 1739716..15de340 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -12,16 +12,10 @@
 void AddDirFileInfo(int phyParent, int logParent, int secureIndex,

     const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems);

 

-struct IEnumDirItemCallback

-{

-  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0;

-};

-

 HRESULT EnumerateItems(

     const NWildcard::CCensor &censor,

     NWildcard::ECensorPathMode pathMode,

     const UString &addPathPrefix,

-    CDirItems &dirItems,

-    IEnumDirItemCallback *callback);

+    CDirItems &dirItems);

 

 #endif

diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index 4bbf2b3..a0d109e 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -51,19 +51,19 @@
       replaceName = arc0.DefaultName;

   }

 

-  outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName)));

+  outDir.Replace(FSTRING_ANY_MASK, us2fs(Get_Correct_FsFile_Name(replaceName)));

 

   bool elimIsPossible = false;

   UString elimPrefix; // only pure name without dir delimiter

   FString outDirReduced = outDir;

   

-  if (options.ElimDup.Val)

+  if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)

   {

     UString dirPrefix;

     SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);

     if (!elimPrefix.IsEmpty())

     {

-      if (IsCharDirLimiter(elimPrefix.Back()))

+      if (IsPathSepar(elimPrefix.Back()))

         elimPrefix.DeleteBack();

       if (!elimPrefix.IsEmpty())

       {

@@ -73,37 +73,66 @@
     }

   }

 

+  bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();

+

   if (!options.StdInMode)

   {

     UInt32 numItems;

     RINOK(archive->GetNumberOfItems(&numItems));

     

-    UString filePath;

+    CReadArcItem item;

 

     for (UInt32 i = 0; i < numItems; i++)

     {

-      RINOK(arc.GetItemPath(i, filePath));

-

-      if (elimIsPossible && options.ElimDup.Val)

+      if (elimIsPossible || !allFilesAreAllowed)

       {

-        if (!IsPath1PrefixedByPath2(filePath, elimPrefix))

+        RINOK(arc.GetItem(i, item));

+      }

+      else

+      {

+        #ifdef SUPPORT_ALT_STREAMS

+        item.IsAltStream = false;

+        if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)

+        {

+          RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream));

+        }

+        #endif

+      }

+

+      #ifdef SUPPORT_ALT_STREAMS

+      if (!options.NtOptions.AltStreams.Val && item.IsAltStream)

+        continue;

+      #endif

+      

+      if (elimIsPossible)

+      {

+        const UString &s =

+          #ifdef SUPPORT_ALT_STREAMS

+            item.MainPath;

+          #else

+            item.Path;

+          #endif

+        if (!IsPath1PrefixedByPath2(s, elimPrefix))

           elimIsPossible = false;

         else

         {

-          wchar_t c = filePath[elimPrefix.Len()];

-          if (c != 0 && !IsCharDirLimiter(c))

+          wchar_t c = s[elimPrefix.Len()];

+          if (c == 0)

+          {

+            if (!item.MainIsDir)

+              elimIsPossible = false;

+          }

+          else if (!IsPathSepar(c))

             elimIsPossible = false;

         }

       }

 

-      bool isFolder;

-      RINOK(Archive_IsItem_Folder(archive, i, isFolder));

-      bool isAltStream;

-      RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));

-      if (!options.NtOptions.AltStreams.Val && isAltStream)

-        continue;

-      if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder))

-        continue;

+      if (!allFilesAreAllowed)

+      {

+        if (!CensorNode_CheckPath(wildcardCensor, item))

+          continue;

+      }

+

       realIndices.Add(i);

     }

     

@@ -115,7 +144,10 @@
   }

 

   if (elimIsPossible)

-    outDir = outDirReduced;

+  {

+    removePathParts.Add(elimPrefix);

+    // outDir = outDirReduced;

+  }

 

   #ifdef _WIN32

   // GetCorrectFullFsPath doesn't like "..".

@@ -124,16 +156,21 @@
   #endif

 

   if (outDir.IsEmpty())

-    outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR);

-  else

-    if (!CreateComplexDir(outDir))

-    {

-      HRESULT res = ::GetLastError();

-      if (res == S_OK)

-        res = E_FAIL;

-      errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir);

-      return res;

-    }

+    outDir = FTEXT(".") FSTRING_PATH_SEPARATOR;

+  /*

+  #ifdef _WIN32

+  else if (NName::IsAltPathPrefix(outDir)) {}

+  #endif

+  */

+  else if (!CreateComplexDir(outDir))

+  {

+    HRESULT res = ::GetLastError();

+    if (res == S_OK)

+      res = E_FAIL;

+    errorMessage.SetFromAscii("Can not create output directory: ");

+    errorMessage += fs2us(outDir);

+    return res;

+  }

 

   ecs->Init(

       options.NtOptions,

@@ -142,7 +179,7 @@
       callback,

       options.StdOutMode, options.TestMode,

       outDir,

-      removePathParts,

+      removePathParts, false,

       packSize);

 

   

@@ -209,15 +246,16 @@
     IHashCalc *hash,

     #endif

     UString &errorMessage,

-    CDecompressStat &stat)

+    CDecompressStat &st)

 {

-  stat.Clear();

+  st.Clear();

   UInt64 totalPackSize = 0;

   CRecordVector<UInt64> arcSizes;

 

   unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();

 

   unsigned i;

+  

   for (i = 0; i < numArcs; i++)

   {

     NFind::CFileInfo fi;

@@ -272,11 +310,13 @@
         throw "there is no such archive";

     }

 

+    /*

     #ifndef _NO_CRYPTO

-    openCallback->Open_ClearPasswordWasAskedFlag();

+    openCallback->Open_Clear_PasswordWasAsked_Flag();

     #endif

+    */

 

-    RINOK(extractCallback->BeforeOpen(arcPath));

+    RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode));

     CArchiveLink arcLink;

 

     CObjectVector<COpenType> types2 = types;

@@ -318,46 +358,24 @@
     op.stdInMode = options.StdInMode;

     op.stream = NULL;

     op.filePath = arcPath;

-    HRESULT result = arcLink.Open2(op, openCallback);

+

+    HRESULT result = arcLink.Open_Strict(op, openCallback);

 

     if (result == E_ABORT)

       return result;

 

-    bool crypted = false;

-    #ifndef _NO_CRYPTO

-    crypted = openCallback->Open_WasPasswordAsked();

-    #endif

-

-    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

-      result = S_FALSE;

-

     // arcLink.Set_ErrorsText();

-    RINOK(extractCallback->OpenResult(arcPath, result, crypted));

-

-

-    {

-      FOR_VECTOR (r, arcLink.Arcs)

-      {

-        const CArc &arc = arcLink.Arcs[r];

-        const CArcErrorInfo &er = arc.ErrorInfo;

-        if (er.IsThereErrorOrWarning())

-        {

-          RINOK(extractCallback->SetError(r, arc.Path,

-              er.GetErrorFlags(), er.ErrorMessage,

-              er.GetWarningFlags(), er.WarningMessage));

-        }

-      }

-    }

+    RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result));

 

     if (result != S_OK)

     {

       thereAreNotOpenArcs = true;

       if (!options.StdInMode)

       {

-        NFind::CFileInfo fi;

-        if (fi.Find(us2fs(arcPath)))

-          if (!fi.IsDir())

-            totalPackProcessed += fi.Size;

+        NFind::CFileInfo fi2;

+        if (fi2.Find(us2fs(arcPath)))

+          if (!fi2.IsDir())

+            totalPackProcessed += fi2.Size;

       }

       continue;

     }

@@ -379,8 +397,8 @@
           {

             if ((unsigned)index > i)

             {

-              skipArcs[index] = true;

-              correctionSize -= arcSizes[index];

+              skipArcs[(unsigned)index] = true;

+              correctionSize -= arcSizes[(unsigned)index];

             }

           }

         }

@@ -395,6 +413,9 @@
       }

     }

 

+    /*

+    // Now openCallback and extractCallback use same object. So we don't need to send password.

+

     #ifndef _NO_CRYPTO

     bool passwordIsDefined;

     UString password;

@@ -404,31 +425,7 @@
       RINOK(extractCallback->SetPassword(password));

     }

     #endif

-

-    FOR_VECTOR (k, arcLink.Arcs)

-    {

-      const CArc &arc = arcLink.Arcs[k];

-      const CArcErrorInfo &er = arc.ErrorInfo;

-

-      if (er.ErrorFormatIndex >= 0)

-      {

-        RINOK(extractCallback->OpenTypeWarning(arc.Path,

-            codecs->GetFormatNamePtr(arc.FormatIndex),

-            codecs->GetFormatNamePtr(er.ErrorFormatIndex)))

-        /*

-        UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n";

-        s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive";

-        RINOK(extractCallback->MessageError(s));

-        */

-      }

-      {

-        const UString &s = er.ErrorMessage;

-        if (!s.IsEmpty())

-        {

-          RINOK(extractCallback->MessageError(s));

-        }

-      }

-    }

+    */

 

     CArc &arc = arcLink.Arcs.Back();

     arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);

@@ -450,6 +447,7 @@
         options,

         calcCrc,

         extractCallback, ecs, errorMessage, packProcessed));

+

     if (!options.StdInMode)

       packProcessed = fi.Size + arcLink.VolumesSize;

     totalPackProcessed += packProcessed;

@@ -464,12 +462,13 @@
     RINOK(extractCallback->SetTotal(totalPackSize));

     RINOK(extractCallback->SetCompleted(&totalPackProcessed));

   }

-  stat.NumFolders = ecs->NumFolders;

-  stat.NumFiles = ecs->NumFiles;

-  stat.NumAltStreams = ecs->NumAltStreams;

-  stat.UnpackSize = ecs->UnpackSize;

-  stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;

-  stat.NumArchives = arcPaths.Size();

-  stat.PackSize = ecs->LocalProgressSpec->InSize;

+

+  st.NumFolders = ecs->NumFolders;

+  st.NumFiles = ecs->NumFiles;

+  st.NumAltStreams = ecs->NumAltStreams;

+  st.UnpackSize = ecs->UnpackSize;

+  st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;

+  st.NumArchives = arcPaths.Size();

+  st.PackSize = ecs->LocalProgressSpec->InSize;

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
index d42514d..9c806be 100644
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -89,6 +89,6 @@
     IHashCalc *hash,

     #endif

     UString &errorMessage,

-    CDecompressStat &stat);

+    CDecompressStat &st);

 

 #endif

diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
index 719aaad..c28b7cc 100644
--- a/CPP/7zip/UI/Common/ExtractMode.h
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -12,7 +12,8 @@
     kFullPaths,

     kCurPaths,

     kNoPaths,

-    kAbsPaths

+    kAbsPaths,

+    kNoPathsAlt // alt streams must be extracted without name of base file

   };

 }

 

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index e6947f2..d395232 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -8,183 +8,230 @@
 

 #include "ExtractingFilePath.h"

 

-static UString ReplaceIncorrectChars(const UString &s, bool repaceColon)

+static void ReplaceIncorrectChars(UString &s)

 {

-  #ifdef _WIN32

-  UString res;

-  bool beforeColon = true;

   {

     for (unsigned i = 0; i < s.Len(); i++)

     {

       wchar_t c = s[i];

-      if (beforeColon)

-        if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"')

-          c = '_';

-      if (c == ':')

-      {

-        if (repaceColon)

-          c = '_';

-        else

-          beforeColon = false;

-      }

-      res += c;

+      if (

+          #ifdef _WIN32

+          c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'

+          || c == '/'

+          // || c == 0x202E // RLO

+          ||

+          #endif

+          c == WCHAR_PATH_SEPARATOR)

+        s.ReplaceOneCharAtPos(i, '_');

     }

   }

-  if (beforeColon)

+  

+  #ifdef _WIN32

   {

-    for (int i = res.Len() - 1; i >= 0; i--)

+    for (unsigned i = s.Len(); i != 0;)

     {

-      wchar_t c = res[i];

+      wchar_t c = s[--i];

       if (c != '.' && c != ' ')

         break;

-      res.ReplaceOneCharAtPos(i, '_');

+      s.ReplaceOneCharAtPos(i, '_');

     }

   }

-  return res;

-  #else

-  return s;

   #endif

 }

 

 #ifdef _WIN32

 

-static const wchar_t *g_ReservedNames[] =

+/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.

+   But colon in postfix ":$DATA" is allowed.

+   WIN32 functions don't allow empty alt stream name "name:" */

+

+void Correct_AltStream_Name(UString &s)

 {

-  L"CON", L"PRN", L"AUX", L"NUL"

+  unsigned len = s.Len();

+  const unsigned kPostfixSize = 6;

+  if (s.Len() >= kPostfixSize

+      && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))

+    len -= kPostfixSize;

+  for (unsigned i = 0; i < len; i++)

+  {

+    wchar_t c = s[i];

+    if (c == ':' || c == '\\' || c == '/'

+        || c == 0x202E // RLO

+        )

+      s.ReplaceOneCharAtPos(i, '_');

+  }

+  if (s.IsEmpty())

+    s = L'_';

+}

+

+static const unsigned g_ReservedWithNum_Index = 4;

+

+static const char * const g_ReservedNames[] =

+{

+  "CON", "PRN", "AUX", "NUL",

+  "COM", "LPT"

 };

 

-static bool CheckTail(const UString &name, unsigned len)

-{

-  int dotPos = name.Find(L'.');

-  if (dotPos < 0)

-    dotPos = name.Len();

-  UString s = name.Left(dotPos);

-  s.TrimRight();

-  return s.Len() != len;

-}

-

-static bool CheckNameNum(const UString &name, const wchar_t *reservedName)

-{

-  unsigned len = MyStringLen(reservedName);

-  if (name.Len() <= len)

-    return true;

-  if (MyStringCompareNoCase_N(name, reservedName, len) != 0)

-    return true;

-  wchar_t c = name[len];

-  if (c < L'0' || c > L'9')

-    return true;

-  return CheckTail(name, len + 1);

-}

-

 static bool IsSupportedName(const UString &name)

 {

   for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)

   {

-    const wchar_t *reservedName = g_ReservedNames[i];

+    const char *reservedName = g_ReservedNames[i];

     unsigned len = MyStringLen(reservedName);

     if (name.Len() < len)

       continue;

-    if (MyStringCompareNoCase_N(name, reservedName, len) != 0)

+    if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))

       continue;

-    if (!CheckTail(name, len))

-      return false;

+    if (i >= g_ReservedWithNum_Index)

+    {

+      wchar_t c = name[len];

+      if (c < L'0' || c > L'9')

+        continue;

+      len++;

+    }

+    for (;;)

+    {

+      wchar_t c = name[len++];

+      if (c == 0 || c == '.')

+        return false;

+      if (c != ' ')

+        break;

+    }

   }

-  if (!CheckNameNum(name, L"COM"))

-    return false;

-  return CheckNameNum(name, L"LPT");

+  return true;

+}

+

+static void CorrectUnsupportedName(UString &name)

+{

+  if (!IsSupportedName(name))

+    name.InsertAtFront(L'_');

 }

 

 #endif

 

-static UString GetCorrectFileName(const UString &path, bool repaceColon)

+static void Correct_PathPart(UString &s)

 {

-  if (path == L".." || path == L".")

-    return UString();

-  return ReplaceIncorrectChars(path, repaceColon);

-}

-

-void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon)

-{

-  for (unsigned i = 0; i < pathParts.Size();)

-  {

-    UString &s = pathParts[i];

-    #ifdef _WIN32

-    bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1);

-    if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s))

-    {

-      UString s2 = s[0];

-      s2 += L'_';

-      s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon);

-      s = s2;

-    }

-    else

-      s = GetCorrectFileName(s, needReplaceColon);

-    #endif

-

-    if (s.IsEmpty())

-      pathParts.Delete(i);

-    else

-    {

-      #ifdef _WIN32

-      if (!IsSupportedName(s))

-        s = (UString)L"_" + s;

-      #endif

-      i++;

-    }

-  }

-}

-

-UString MakePathNameFromParts(const UStringVector &parts)

-{

-  UString result;

-  FOR_VECTOR (i, parts)

-  {

-    if (i != 0)

-      result += WCHAR_PATH_SEPARATOR;

-    result += parts[i];

-  }

-  return result;

-}

-

-static const wchar_t *k_EmptyReplaceName = L"[]";

-

-void Correct_IfEmptyLastPart(UStringVector &parts)

-{

-  if (parts.IsEmpty())

-    parts.Add(k_EmptyReplaceName);

-  else

-  {

-    UString &s = parts.Back();

-    if (s.IsEmpty())

-      s = k_EmptyReplaceName;

-  }

-}

-

-UString GetCorrectFsPath(const UString &path)

-{

-  UString res = GetCorrectFileName(path, true);

+  // "." and ".."

+  if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))

+    s.Empty();

   #ifdef _WIN32

-  if (!IsSupportedName(res))

-    res = (UString)L"_" + res;

+  else

+    ReplaceIncorrectChars(s);

   #endif

+}

+

+// static const wchar_t *k_EmptyReplaceName = L"[]";

+static const wchar_t k_EmptyReplaceName = L'_';

+

+UString Get_Correct_FsFile_Name(const UString &name)

+{

+  UString res = name;

+  Correct_PathPart(res);

+  

+  #ifdef _WIN32

+  CorrectUnsupportedName(res);

+  #endif

+  

   if (res.IsEmpty())

     res = k_EmptyReplaceName;

   return res;

 }

-  

-UString GetCorrectFullFsPath(const UString &path)

+

+

+void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)

 {

-  UStringVector parts;

-  SplitPathToParts(path, parts);

-  FOR_VECTOR (i, parts)

+  unsigned i = 0;

+

+  if (absIsAllowed)

   {

-    UString &s = parts[i];

-    #ifdef _WIN32

-    while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' '))

-      s.DeleteBack();

-    if (!IsSupportedName(s))

-      s.InsertAtFront(L'_');

+    #if defined(_WIN32) && !defined(UNDER_CE)

+    bool isDrive = false;

+    #endif

+    if (parts[0].IsEmpty())

+    {

+      i = 1;

+      #if defined(_WIN32) && !defined(UNDER_CE)

+      if (parts.Size() > 1 && parts[1].IsEmpty())

+      {

+        i = 2;

+        if (parts.Size() > 2 && parts[2] == L"?")

+        {

+          i = 3;

+          if (parts.Size() > 3  && NWindows::NFile::NName::IsDrivePath2(parts[3]))

+          {

+            isDrive = true;

+            i = 4;

+          }

+        }

+      }

+      #endif

+    }

+    #if defined(_WIN32) && !defined(UNDER_CE)

+    else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))

+    {

+      isDrive = true;

+      i = 1;

+    }

+

+    if (isDrive)

+    {

+      // we convert "c:name" to "c:\name", if absIsAllowed path.

+      const UString &ds = parts[i - 1];

+      if (ds.Len() != 2)

+      {

+        UString s = ds.Ptr(2);

+        parts.Insert(i, s);

+      }

+    }

     #endif

   }

-  return MakePathNameFromParts(parts);

+

+  for (; i < parts.Size();)

+  {

+    UString &s = parts[i];

+

+    Correct_PathPart(s);

+

+    if (s.IsEmpty())

+    {

+      if (isDir || i != parts.Size() - 1)

+      {

+        parts.Delete(i);

+        continue;

+      }

+      s = k_EmptyReplaceName;

+    }

+    else

+    {

+      #ifdef _WIN32

+      CorrectUnsupportedName(s);

+      #endif

+    }

+    

+    i++;

+  }

+

+  if (!isDir)

+  {

+    if (parts.IsEmpty())

+      parts.Add(k_EmptyReplaceName);

+    else

+    {

+      UString &s = parts.Back();

+      if (s.IsEmpty())

+        s = k_EmptyReplaceName;

+    }

+  }

+}

+

+UString MakePathFromParts(const UStringVector &parts)

+{

+  UString s;

+  FOR_VECTOR (i, parts)

+  {

+    if (i != 0)

+      s.Add_PathSepar();

+    s += parts[i];

+  }

+  return s;

 }

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
index 8d36312..ce200b8 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -5,17 +5,15 @@
 

 #include "../../../Common/MyString.h"

 

-UString MakePathNameFromParts(const UStringVector &parts);

+#ifdef _WIN32

+void Correct_AltStream_Name(UString &s);

+#endif

 

-/* for WIN32:

-  if (isRoot == true), and  pathParts[0] contains path like "c:name",

-  it thinks that "c:" is drive prefix (it's not ":name alt stream) and

-  the function changes part to c_name */

-void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon);

+// replaces unsuported characters, and replaces "." , ".." and "" to "[]"

+UString Get_Correct_FsFile_Name(const UString &name);

 

-UString GetCorrectFsPath(const UString &path);

-UString GetCorrectFullFsPath(const UString &path);

+void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir);

 

-void Correct_IfEmptyLastPart(UStringVector &parts);

+UString MakePathFromParts(const UStringVector &parts);

 

 #endif

diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index 4ecf6a3..9d4747b 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -30,23 +30,17 @@
   ~CHashMidBuf() { ::MidFree(_data); }

 };

 

-struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback

-{

-  IHashCallbackUI *Callback;

-  

-  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)

-  {

-    return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);

-  }

-};

-

-static const wchar_t *k_DefaultHashMethod = L"CRC32";

+static const char *k_DefaultHashMethod = "CRC32";

 

 HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)

 {

   UStringVector names = hashMethods;

   if (names.IsEmpty())

-    names.Add(k_DefaultHashMethod);

+  {

+    UString s;

+    s.SetFromAscii(k_DefaultHashMethod);

+    names.Add(s);

+  }

 

   CRecordVector<CMethodId> ids;

   CObjectVector<COneMethodInfo> methods;

@@ -60,7 +54,7 @@
     if (m.MethodName.IsEmpty())

       m.MethodName = k_DefaultHashMethod;

     

-    if (m.MethodName == L"*")

+    if (m.MethodName == "*")

     {

       CRecordVector<CMethodId> tempMethods;

       GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);

@@ -68,7 +62,7 @@
       ids.Clear();

       FOR_VECTOR (t, tempMethods)

       {

-        int index = ids.AddToUniqueSorted(tempMethods[t]);

+        unsigned index = ids.AddToUniqueSorted(tempMethods[t]);

         if (ids.Size() != methods.Size())

           methods.Insert(index, m);

       }

@@ -80,7 +74,7 @@
       CMethodId id;

       if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))

         return E_NOTIMPL;

-      int index = ids.AddToUniqueSorted(id);

+      unsigned index = ids.AddToUniqueSorted(id);

       if (ids.Size() != methods.Size())

         methods.Insert(index, m);

     }

@@ -89,7 +83,7 @@
   for (i = 0; i < ids.Size(); i++)

   {

     CMyComPtr<IHasher> hasher;

-    UString name;

+    AString name;

     RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));

     if (!hasher)

       throw "Can't create hasher";

@@ -98,9 +92,7 @@
       CMyComPtr<ICompressSetCoderProperties> scp;

       hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);

       if (scp)

-      {

         RINOK(m.SetCoderProps(scp, NULL));

-      }

     }

     UInt32 digestSize = hasher->GetDigestSize();

     if (digestSize > k_HashCalc_DigestSize_Max)

@@ -109,9 +101,10 @@
     h.Hasher = hasher;

     h.Name = name;

     h.DigestSize = digestSize;

-    for (int i = 0; i < k_HashCalc_NumGroups; i++)

-      memset(h.Digests[i], 0, digestSize);

+    for (unsigned k = 0; k < k_HashCalc_NumGroups; k++)

+      memset(h.Digests[k], 0, digestSize);

   }

+

   return S_OK;

 }

 

@@ -203,13 +196,12 @@
     DECL_EXTERNAL_CODECS_LOC_VARS

     const NWildcard::CCensor &censor,

     const CHashOptions &options,

-    UString &errorInfo,

+    AString &errorInfo,

     IHashCallbackUI *callback)

 {

   CDirItems dirItems;

+  dirItems.Callback = callback;

 

-  UInt64 numErrors = 0;

-  UInt64 totalBytes = 0;

   if (options.StdInMode)

   {

     CDirItem di;

@@ -222,34 +214,29 @@
   }

   else

   {

-    CEnumDirItemCallback_Hash enumCallback;

-    enumCallback.Callback = callback;

     RINOK(callback->StartScanning());

     dirItems.ScanAltStreams = options.AltStreamsMode;

+

     HRESULT res = EnumerateItems(censor,

         options.PathMode,

         UString(),

-        dirItems, &enumCallback);

-    totalBytes = dirItems.TotalSize;

-    FOR_VECTOR (i, dirItems.ErrorPaths)

-    {

-      RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));

-    }

-    numErrors = dirItems.ErrorPaths.Size();

+        dirItems);

+    

     if (res != S_OK)

     {

       if (res != E_ABORT)

-        errorInfo = L"Scanning error";

+        errorInfo = "Scanning error";

       return res;

     }

-    RINOK(callback->FinishScanning());

+    RINOK(callback->FinishScanning(dirItems.Stat));

   }

 

   unsigned i;

   CHashBundle hb;

   RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));

   hb.Init();

-  hb.NumErrors = numErrors;

+

+  hb.NumErrors = dirItems.Stat.NumErrors;

   

   if (options.StdInMode)

   {

@@ -257,7 +244,7 @@
   }

   else

   {

-    RINOK(callback->SetTotal(totalBytes));

+    RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));

   }

 

   const UInt32 kBufSize = 1 << 15;

@@ -289,8 +276,8 @@
       path = dirItems.GetLogPath(i);

       if (!isDir)

       {

-        UString phyPath = dirItems.GetPhyPath(i);

-        if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite))

+        FString phyPath = dirItems.GetPhyPath(i);

+        if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))

         {

           HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());

           hb.NumErrors++;

@@ -327,14 +314,15 @@
 }

 

 

-static inline char GetHex(Byte value)

+static inline char GetHex(unsigned v)

 {

-  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+  return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));

 }

 

 void AddHashHexToString(char *dest, const Byte *data, UInt32 size)

 {

   dest[size * 2] = 0;

+  

   if (!data)

   {

     for (UInt32 i = 0; i < size; i++)

@@ -345,17 +333,19 @@
     }

     return;

   }

+  

   int step = 2;

   if (size <= 8)

   {

     step = -2;

     dest += size * 2 - 2;

   }

+  

   for (UInt32 i = 0; i < size; i++)

   {

-    Byte b = data[i];

-    dest[0] = GetHex((Byte)((b >> 4) & 0xF));

-    dest[1] = GetHex((Byte)(b & 0xF));

+    unsigned b = data[i];

+    dest[0] = GetHex((b >> 4) & 0xF);

+    dest[1] = GetHex(b & 0xF);

     dest += step;

   }

 }

diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index 01ee2ce..d98c577 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -8,6 +8,7 @@
 #include "../../Common/CreateCoder.h"

 #include "../../Common/MethodProps.h"

 

+#include "DirItem.h"

 #include "Property.h"

 

 const unsigned k_HashCalc_DigestSize_Max = 64;

@@ -25,7 +26,7 @@
 struct CHasherState

 {

   CMyComPtr<IHasher> Hasher;

-  UString Name;

+  AString Name;

   UInt32 DigestSize;

   Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];

 };

@@ -42,8 +43,8 @@
 {

   CObjectVector<CHasherState> Hashers;

 

-  UInt64 NumFiles;

   UInt64 NumDirs;

+  UInt64 NumFiles;

   UInt64 NumAltStreams;

   UInt64 FilesSize;

   UInt64 AltStreamsSize;

@@ -55,7 +56,7 @@
   

   void Init()

   {

-    NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;

+    NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;

   }

 

   void InitForNewFile();

@@ -65,21 +66,20 @@
 };

 

 #define INTERFACE_IHashCallbackUI(x) \

+  INTERFACE_IDirItemsCallback(x) \

   virtual HRESULT StartScanning() x; \

-  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \

-  virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \

-  virtual HRESULT FinishScanning() x; \

+  virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \

   virtual HRESULT SetNumFiles(UInt64 numFiles) x; \

   virtual HRESULT SetTotal(UInt64 size) x; \

   virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \

   virtual HRESULT CheckBreak() x; \

   virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \

   virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \

-  virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \

+  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \

   virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \

   virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \

 

-struct IHashCallbackUI

+struct IHashCallbackUI: public IDirItemsCallback

 {

   INTERFACE_IHashCallbackUI(=0)

 };

@@ -99,7 +99,7 @@
     DECL_EXTERNAL_CODECS_LOC_VARS

     const NWildcard::CCensor &censor,

     const CHashOptions &options,

-    UString &errorInfo,

+    AString &errorInfo,

     IHashCallbackUI *callback);

 

 void AddHashHexToString(char *dest, const Byte *data, UInt32 size);

diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
index debfc08..3f554ef 100644
--- a/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -7,6 +7,9 @@
 

 #include "../../IDecl.h"

 

+#include "LoadCodecs.h"

+#include "OpenArchive.h"

+

 namespace NOverwriteAnswer

 {

   enum EEnum

@@ -20,35 +23,74 @@
   };

 }

 

+

+/* ---------- IFolderArchiveExtractCallback ----------

+is implemented by

+  Console/ExtractCallbackConsole.h  CExtractCallbackConsole

+  FileManager/ExtractCallback.h     CExtractCallbackImp

+  FAR/ExtractEngine.cpp             CExtractCallBackImp: (QueryInterface is not supported)

+

+IID_IFolderArchiveExtractCallback is requested by:

+  - Agent/ArchiveFolder.cpp

+      CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback)

+      is sent to IArchiveFolder::Extract()

+

+  - FileManager/PanelCopy.cpp

+      CPanel::CopyTo(), if (options->testMode)

+      is sent to IArchiveFolder::Extract()

+

+ IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp

+*/

+

+#define INTERFACE_IFolderArchiveExtractCallback(x) \

+  STDMETHOD(AskOverwrite)( \

+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \

+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \

+      Int32 *answer) x; \

+  STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \

+  STDMETHOD(MessageError)(const wchar_t *message) x; \

+  STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \

+

 DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)

 {

-public:

-  STDMETHOD(AskOverwrite)(

-      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

-      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

-      Int32 *answer) PURE;

-  STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE;

-  STDMETHOD(MessageError)(const wchar_t *message) PURE;

-  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;

+  INTERFACE_IFolderArchiveExtractCallback(PURE)

 };

 

+#define INTERFACE_IFolderArchiveExtractCallback2(x) \

+  STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \

+

+DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08)

+{

+  INTERFACE_IFolderArchiveExtractCallback2(PURE)

+};

+

+/* ---------- IExtractCallbackUI ----------

+is implemented by

+  Console/ExtractCallbackConsole.h  CExtractCallbackConsole

+  FileManager/ExtractCallback.h     CExtractCallbackImp

+*/

+

+#ifdef _NO_CRYPTO

+  #define INTERFACE_IExtractCallbackUI_Crypto(x)

+#else

+  #define INTERFACE_IExtractCallbackUI_Crypto(x) \

+  virtual HRESULT SetPassword(const UString &password) x;

+#endif

+

+#define INTERFACE_IExtractCallbackUI(x) \

+  virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \

+  virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \

+  virtual HRESULT ThereAreNoFiles() x; \

+  virtual HRESULT ExtractResult(HRESULT result) x; \

+  INTERFACE_IExtractCallbackUI_Crypto(x)

+

 struct IExtractCallbackUI: IFolderArchiveExtractCallback

 {

-  virtual HRESULT BeforeOpen(const wchar_t *name) = 0;

-  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;

-  virtual HRESULT SetError(int level, const wchar_t *name,

-      UInt32 errorFlags, const wchar_t *errors,

-      UInt32 warningFlags, const wchar_t *warnings) = 0;

-  virtual HRESULT ThereAreNoFiles() = 0;

-  virtual HRESULT ExtractResult(HRESULT result) = 0;

-  virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0;

-

-  #ifndef _NO_CRYPTO

-  virtual HRESULT SetPassword(const UString &password) = 0;

-  #endif

+  INTERFACE_IExtractCallbackUI(PURE)

 };

 

 

+

 #define INTERFACE_IGetProp(x) \

   STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \

 

@@ -61,7 +103,7 @@
   STDMETHOD(UseExtractToStream)(Int32 *res) x; \

   STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \

   STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \

-  STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \

+  STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \

 

 DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)

 {

diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index acbd7e8..9379152 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -1,5 +1,36 @@
 // LoadCodecs.cpp

 

+/*

+EXTERNAL_CODECS

+---------------

+  CCodecs::Load() tries to detect the directory with plugins.

+  It stops the checking, if it can find any of the following items:

+    - 7z.dll file

+    - "Formats" subdir

+    - "Codecs"  subdir

+  The order of check:

+    1) directory of client executable

+    2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**]

+       The order for HKEY_* : Path** :

+         - HKEY_CURRENT_USER  : PathXX

+         - HKEY_LOCAL_MACHINE : PathXX

+         - HKEY_CURRENT_USER  : Path

+         - HKEY_LOCAL_MACHINE : Path

+       PathXX is Path32 in 32-bit code

+       PathXX is Path64 in 64-bit code

+

+

+EXPORT_CODECS

+-------------

+  if (EXTERNAL_CODECS) is defined, then the code exports internal

+  codecs of client from CCodecs object to external plugins.

+  7-Zip doesn't use that feature. 7-Zip uses the scheme:

+    - client application without internal plugins.

+    - 7z.dll module contains all (or almost all) plugins.

+      7z.dll can use codecs from another plugins, if required.

+*/

+

+

 #include "StdAfx.h"

 

 #include "../../../../C/7zVersion.h"

@@ -23,13 +54,21 @@
 

 #ifdef EXTERNAL_CODECS

 

-#include "../../../Windows/FileFind.h"

-#include "../../../Windows/DLL.h"

+// #define EXPORT_CODECS

+

+#endif

+

 #ifdef NEW_FOLDER_INTERFACE

+extern HINSTANCE g_hInstance;

 #include "../../../Windows/ResourceString.h"

 static const UINT kIconTypesResId = 100;

 #endif

 

+#ifdef EXTERNAL_CODECS

+

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/DLL.h"

+

 #ifdef _WIN32

 #include "../../../Windows/FileName.h"

 #include "../../../Windows/Registry.h"

@@ -37,13 +76,18 @@
 

 using namespace NFile;

 

-#ifdef _WIN32

-extern HINSTANCE g_hInstance;

-#endif

 

 #define kCodecsFolderName FTEXT("Codecs")

 #define kFormatsFolderName FTEXT("Formats")

-static CFSTR kMainDll = FTEXT("7z.dll");

+

+

+static CFSTR kMainDll =

+  // #ifdef _WIN32

+    FTEXT("7z.dll");

+  // #else

+  // FTEXT("7z.so");

+  // #endif

+

 

 #ifdef _WIN32

 

@@ -77,7 +121,7 @@
 #endif // EXTERNAL_CODECS

 

 

-static const unsigned kNumArcsMax = 48;

+static const unsigned kNumArcsMax = 64;

 static unsigned g_NumArcs = 0;

 static const CArcInfo *g_Arcs[kNumArcsMax];

 

@@ -118,7 +162,7 @@
 int CArcInfoEx::FindExtension(const UString &ext) const

 {

   FOR_VECTOR (i, Exts)

-    if (ext.IsEqualToNoCase(Exts[i].Ext))

+    if (ext.IsEqualTo_NoCase(Exts[i].Ext))

       return i;

   return -1;

 }

@@ -182,6 +226,7 @@
   return moduleFolderPrefix;

 }

 

+

 static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,

     PROPID propId, CLSID &clsId, bool &isAssigned)

 {

@@ -203,14 +248,18 @@
 HRESULT CCodecs::LoadCodecs()

 {

   CCodecLib &lib = Libs.Back();

+

+  lib.CreateDecoder = (Func_CreateDecoder)lib.Lib.GetProc("CreateDecoder");

+  lib.CreateEncoder = (Func_CreateEncoder)lib.Lib.GetProc("CreateEncoder");

   lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty");

+

   if (lib.GetMethodProperty)

   {

     UInt32 numMethods = 1;

-    Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");

-    if (getNumberOfMethodsFunc)

+    Func_GetNumberOfMethods getNumberOfMethods = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");

+    if (getNumberOfMethods)

     {

-      RINOK(getNumberOfMethodsFunc(&numMethods));

+      RINOK(getNumberOfMethods(&numMethods));

     }

     for (UInt32 i = 0; i < numMethods; i++)

     {

@@ -226,10 +275,10 @@
   Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");

   if (getHashers)

   {

-    RINOK(getHashers(&lib.Hashers));

-    if (lib.Hashers)

+    RINOK(getHashers(&lib.ComHashers));

+    if (lib.ComHashers)

     {

-      UInt32 numMethods = lib.Hashers->GetNumHashers();

+      UInt32 numMethods = lib.ComHashers->GetNumHashers();

       for (UInt32 i = 0; i < numMethods; i++)

       {

         CDllHasherInfo info;

@@ -239,6 +288,7 @@
       }

     }

   }

+  

   return S_OK;

 }

 

@@ -295,7 +345,7 @@
   NCOM::CPropVariant prop;

   RINOK(GetProp(getProp, getProp2, index, propID, prop));

   if (prop.vt == VT_BSTR)

-    res = prop.bstrVal;

+    res.SetFromBstr(prop.bstrVal);

   else if (prop.vt != VT_EMPTY)

     return E_FAIL;

   return S_OK;

@@ -416,54 +466,6 @@
   return S_OK;

 }

 

-#ifdef NEW_FOLDER_INTERFACE

-void CCodecIcons::LoadIcons(HMODULE m)

-{

-  UString iconTypes;

-  MyLoadString(m, kIconTypesResId, iconTypes);

-  UStringVector pairs;

-  SplitString(iconTypes, pairs);

-  FOR_VECTOR (i, pairs)

-  {

-    const UString &s = pairs[i];

-    int pos = s.Find(L':');

-    CIconPair iconPair;

-    iconPair.IconIndex = -1;

-    if (pos < 0)

-      pos = s.Len();

-    else

-    {

-      UString num = s.Ptr(pos + 1);

-      if (!num.IsEmpty())

-      {

-        const wchar_t *end;

-        iconPair.IconIndex = ConvertStringToUInt32(num, &end);

-        if (*end != 0)

-          continue;

-      }

-    }

-    iconPair.Ext = s.Left(pos);

-    IconPairs.Add(iconPair);

-  }

-}

-

-bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const

-{

-  iconIndex = -1;

-  FOR_VECTOR (i, IconPairs)

-  {

-    const CIconPair &pair = IconPairs[i];

-    if (ext.IsEqualToNoCase(pair.Ext))

-    {

-      iconIndex = pair.IconIndex;

-      return true;

-    }

-  }

-  return false;

-}

-

-#endif // EXTERNAL_CODECS

-

 #ifdef _7ZIP_LARGE_PAGES

 extern "C"

 {

@@ -471,21 +473,28 @@
 }

 #endif

 

-HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)

+HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)

 {

+  if (loadedOK)

+    *loadedOK = false;

+

   if (needCheckDll)

   {

-    NDLL::CLibrary library;

-    if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))

+    NDLL::CLibrary lib;

+    if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))

       return S_OK;

   }

-  Libs.Add(CCodecLib());

+  

+  Libs.AddNew();

   CCodecLib &lib = Libs.Back();

   lib.Path = dllPath;

   bool used = false;

   HRESULT res = S_OK;

+  

   if (lib.Lib.Load(dllPath))

   {

+    if (loadedOK)

+      *loadedOK = true;

     #ifdef NEW_FOLDER_INTERFACE

     lib.LoadIcons();

     #endif

@@ -521,8 +530,10 @@
       }

     }

   }

+  

   if (!used)

     Libs.DeleteBack();

+

   return res;

 }

 

@@ -539,17 +550,42 @@
   return S_OK;

 }

 

-#endif

+void CCodecs::CloseLibs()

+{

+  // OutputDebugStringA("~CloseLibs start");

+  /*

+  WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,

+  if it's called from another FreeLibrary() call.

+  So we need to call FreeLibrary() before global destructors.

+  

+  Also we free global links from DLLs to object of this module before CLibrary::Free() call.

+  */

+  

+  FOR_VECTOR(i, Libs)

+  {

+    const CCodecLib &lib = Libs[i];

+    if (lib.SetCodecs)

+      lib.SetCodecs(NULL);

+  }

+  

+  // OutputDebugStringA("~CloseLibs after SetCodecs");

+  Libs.Clear();

+  // OutputDebugStringA("~CloseLibs end");

+}

+

+#endif // EXTERNAL_CODECS

+

 

 HRESULT CCodecs::Load()

 {

   #ifdef NEW_FOLDER_INTERFACE

-    InternalIcons.LoadIcons(g_hInstance);

+  InternalIcons.LoadIcons(g_hInstance);

   #endif

 

   Formats.Clear();

   

   #ifdef EXTERNAL_CODECS

+    MainDll_ErrorPath.Empty();

     Codecs.Clear();

     Hashers.Clear();

   #endif

@@ -593,11 +629,46 @@
   

   #ifdef EXTERNAL_CODECS

     const FString baseFolder = GetBaseFolderPrefixFromRegistry();

-    RINOK(LoadDll(baseFolder + kMainDll, false));

+    {

+      bool loadedOK;

+      RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK));

+      if (!loadedOK)

+        MainDll_ErrorPath = kMainDll;

+    }

     RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));

     RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));

+

+  NeedSetLibCodecs = true;

+    

+  if (Libs.Size() == 0)

+    NeedSetLibCodecs = false;

+  else if (Libs.Size() == 1)

+  {

+    // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.

+    #ifndef EXPORT_CODECS

+    if (g_NumArcs == 0)

+      NeedSetLibCodecs = false;

+    #endif

+  }

+

+  if (NeedSetLibCodecs)

+  {

+    /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)

+       old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */

+

+    FOR_VECTOR(i, Libs)

+    {

+      CCodecLib &lib = Libs[i];

+      lib.SetCodecs = (Func_SetCodecs)lib.Lib.GetProc("SetCodecs");

+      if (lib.SetCodecs)

+      {

+        RINOK(lib.SetCodecs(this));

+      }

+    }

+  }

+

   #endif

-  

+

   return S_OK;

 }

 

@@ -605,14 +676,13 @@
 

 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const

 {

-  int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);

-  int dotPos = arcPath.ReverseFind(L'.');

-  if (dotPos < 0 || dotPos < slashPos)

+  int dotPos = arcPath.ReverseFind_Dot();

+  if (dotPos <= arcPath.ReverseFind_PathSepar())

     return -1;

   const UString ext = arcPath.Ptr(dotPos + 1);

   if (ext.IsEmpty())

     return -1;

-  if (ext.IsEqualToNoCase(L"exe"))

+  if (ext.IsEqualTo_Ascii_NoCase("exe"))

     return -1;

   FOR_VECTOR (i, Formats)

   {

@@ -640,7 +710,7 @@
 int CCodecs::FindFormatForArchiveType(const UString &arcType) const

 {

   FOR_VECTOR (i, Formats)

-    if (Formats[i].Name.IsEqualToNoCase(arcType))

+    if (Formats[i].Name.IsEqualTo_NoCase(arcType))

       return i;

   return -1;

 }

@@ -650,7 +720,7 @@
   formatIndices.Clear();

   for (unsigned pos = 0; pos < arcType.Len();)

   {

-    int pos2 = arcType.Find('.', pos);

+    int pos2 = arcType.Find(L'.', pos);

     if (pos2 < 0)

       pos2 = arcType.Len();

     const UString name = arcType.Mid(pos, pos2 - pos);

@@ -671,6 +741,56 @@
 #endif // _SFX

 

 

+#ifdef NEW_FOLDER_INTERFACE

+

+void CCodecIcons::LoadIcons(HMODULE m)

+{

+  UString iconTypes;

+  MyLoadString(m, kIconTypesResId, iconTypes);

+  UStringVector pairs;

+  SplitString(iconTypes, pairs);

+  FOR_VECTOR (i, pairs)

+  {

+    const UString &s = pairs[i];

+    int pos = s.Find(L':');

+    CIconPair iconPair;

+    iconPair.IconIndex = -1;

+    if (pos < 0)

+      pos = s.Len();

+    else

+    {

+      UString num = s.Ptr(pos + 1);

+      if (!num.IsEmpty())

+      {

+        const wchar_t *end;

+        iconPair.IconIndex = ConvertStringToUInt32(num, &end);

+        if (*end != 0)

+          continue;

+      }

+    }

+    iconPair.Ext = s.Left(pos);

+    IconPairs.Add(iconPair);

+  }

+}

+

+bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const

+{

+  iconIndex = -1;

+  FOR_VECTOR (i, IconPairs)

+  {

+    const CIconPair &pair = IconPairs[i];

+    if (ext.IsEqualTo_NoCase(pair.Ext))

+    {

+      iconIndex = pair.IconIndex;

+      return true;

+    }

+  }

+  return false;

+}

+

+#endif // NEW_FOLDER_INTERFACE

+

+

 #ifdef EXTERNAL_CODECS

 

 // #define EXPORT_CODECS

@@ -678,7 +798,8 @@
 #ifdef EXPORT_CODECS

 

 extern unsigned g_NumCodecs;

-STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);

+STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);

+STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);

 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);

 #define NUM_EXPORT_CODECS g_NumCodecs

 

@@ -694,7 +815,7 @@
 

 #endif // EXPORT_CODECS

 

-STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)

+STDMETHODIMP CCodecs::GetNumMethods(UInt32 *numMethods)

 {

   *numMethods = NUM_EXPORT_CODECS

     #ifdef EXTERNAL_CODECS

@@ -718,13 +839,14 @@
       propID == NMethodPropID::kEncoderIsAssigned)

   {

     NCOM::CPropVariant prop;

-    prop = (propID == NMethodPropID::kDecoderIsAssigned) ?

+    prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?

         ci.DecoderIsAssigned :

-        ci.EncoderIsAssigned;

+        ci.EncoderIsAssigned);

     prop.Detach(value);

     return S_OK;

   }

-  return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);

+  const CCodecLib &lib = Libs[ci.LibIndex];

+  return lib.GetMethodProperty(ci.CodecIndex, propID, value);

   #else

   return E_FAIL;

   #endif

@@ -734,12 +856,18 @@
 {

   #ifdef EXPORT_CODECS

   if (index < g_NumCodecs)

-    return CreateCoder2(false, index, iid, coder);

+    return CreateDecoder(index, iid, coder);

   #endif

+  

   #ifdef EXTERNAL_CODECS

   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

   if (ci.DecoderIsAssigned)

-    return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);

+  {

+    const CCodecLib &lib = Libs[ci.LibIndex];

+    if (lib.CreateDecoder)

+      return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);

+    return lib.CreateObject(&ci.Decoder, iid, (void **)coder);

+  }

   return S_OK;

   #else

   return E_FAIL;

@@ -750,12 +878,18 @@
 {

   #ifdef EXPORT_CODECS

   if (index < g_NumCodecs)

-    return CreateCoder2(true, index, iid, coder);

+    return CreateEncoder(index, iid, coder);

   #endif

+

   #ifdef EXTERNAL_CODECS

   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

   if (ci.EncoderIsAssigned)

-    return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);

+  {

+    const CCodecLib &lib = Libs[ci.LibIndex];

+    if (lib.CreateEncoder)

+      return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);

+    return lib.CreateObject(&ci.Encoder, iid, (void **)coder);

+  }

   return S_OK;

   #else

   return E_FAIL;

@@ -781,7 +915,7 @@
 

   #ifdef EXTERNAL_CODECS

   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

-  return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value);

+  return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);

   #else

   return E_FAIL;

   #endif

@@ -795,18 +929,19 @@
   #endif

   #ifdef EXTERNAL_CODECS

   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

-  return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher);

+  return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);

   #else

   return E_FAIL;

   #endif

 }

 

-int CCodecs::GetCodecLibIndex(UInt32 index)

+int CCodecs::GetCodec_LibIndex(UInt32 index) const

 {

   #ifdef EXPORT_CODECS

   if (index < g_NumCodecs)

     return -1;

   #endif

+  

   #ifdef EXTERNAL_CODECS

   const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

   return ci.LibIndex;

@@ -821,6 +956,7 @@
   if (index < g_NumHashers)

     return -1;

   #endif

+  

   #ifdef EXTERNAL_CODECS

   const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

   return ci.LibIndex;

@@ -829,27 +965,62 @@
   #endif

 }

 

-bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)

+bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const

 {

   #ifdef EXPORT_CODECS

   if (index < g_NumCodecs)

   {

     NCOM::CPropVariant prop;

-    if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)

-      if (prop.vt != VT_EMPTY)

-        return true;

+    if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)

+    {

+      if (prop.vt == VT_BOOL)

+        return VARIANT_BOOLToBool(prop.boolVal);

+    }

     return false;

   }

   #endif

+  

   #ifdef EXTERNAL_CODECS

-  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

-  return ci.EncoderIsAssigned;

+  return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;

   #else

   return false;

   #endif

 }

 

-HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)

+bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+  {

+    NCOM::CPropVariant prop;

+    if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)

+    {

+      if (prop.vt == VT_BOOL)

+        return VARIANT_BOOLToBool(prop.boolVal);

+    }

+    return false;

+  }

+  #endif

+  

+  #ifdef EXTERNAL_CODECS

+  return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;

+  #else

+  return false;

+  #endif

+}

+

+UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)

+{

+  NCOM::CPropVariant prop;

+  RINOK(GetProperty(index, NMethodPropID::kPackStreams, &prop));

+  if (prop.vt == VT_UI4)

+    return (UInt32)prop.ulVal;

+  if (prop.vt == VT_EMPTY)

+    return 1;

+  return 0;

+}

+

+HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)

 {

   NCOM::CPropVariant prop;

   RINOK(GetProperty(index, NMethodPropID::kID, &prop));

@@ -859,32 +1030,33 @@
   return S_OK;

 }

 

-UString CCodecs::GetCodecName(UInt32 index)

+AString CCodecs::GetCodec_Name(UInt32 index)

 {

-  UString s;

+  AString s;

   NCOM::CPropVariant prop;

   if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)

     if (prop.vt == VT_BSTR)

-      s = prop.bstrVal;

+      s.SetFromWStr_if_Ascii(prop.bstrVal);

   return s;

 }

 

 UInt64 CCodecs::GetHasherId(UInt32 index)

 {

   NCOM::CPropVariant prop;

-  RINOK(GetHasherProp(index, NMethodPropID::kID, &prop));

+  if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)

+    return 0;

   if (prop.vt != VT_UI8)

     return 0;

   return prop.uhVal.QuadPart;

 }

 

-UString CCodecs::GetHasherName(UInt32 index)

+AString CCodecs::GetHasherName(UInt32 index)

 {

-  UString s;

+  AString s;

   NCOM::CPropVariant prop;

   if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)

     if (prop.vt == VT_BSTR)

-      s = prop.bstrVal;

+      s.SetFromWStr_if_Ascii(prop.bstrVal);

   return s;

 }

 

diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
index eebb177..9ba36d3 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -3,34 +3,82 @@
 #ifndef __LOAD_CODECS_H

 #define __LOAD_CODECS_H

 

+/*

+Client application uses LoadCodecs.* to load plugins to

+CCodecs object, that contains 3 lists of plugins:

+  1) Formats - internal and external archive handlers

+  2) Codecs  - external codecs

+  3) Hashers - external hashers

+

+EXTERNAL_CODECS

+---------------

+

+  if EXTERNAL_CODECS is defined, then the code tries to load external

+  plugins from DLL files (shared libraries).

+

+  There are two types of executables in 7-Zip:

+  

+  1) Executable that uses external plugins must be compiled

+     with EXTERNAL_CODECS defined:

+       - 7z.exe, 7zG.exe, 7zFM.exe

+    

+     Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h

+           that code is used in plugin module (7z.dll).

+  

+  2) Standalone modules are compiled without EXTERNAL_CODECS:

+    - SFX modules: 7z.sfx, 7zCon.sfx

+    - standalone versions of console 7-Zip: 7za.exe, 7zr.exe

+

+  if EXTERNAL_CODECS is defined, CCodecs class implements interfaces:

+    - ICompressCodecsInfo : for Codecs

+    - IHashers            : for Hashers

+  

+  The client application can send CCodecs object to each plugin module.

+  And plugin module can use ICompressCodecsInfo or IHashers interface to access

+  another plugins.

+

+  There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin

+    1) for old versions:

+        a) request ISetCompressCodecsInfo from created archive handler.

+        b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)

+    2) for new versions:

+        a) request "SetCodecs" function from DLL file

+        b) call SetCodecs(compressCodecsInfo) function from DLL file

+*/

+

 #include "../../../Common/MyBuffer.h"

 #include "../../../Common/MyCom.h"

 #include "../../../Common/MyString.h"

 #include "../../../Common/ComTry.h"

 

-#include "../../ICoder.h"

-

 #ifdef EXTERNAL_CODECS

 #include "../../../Windows/DLL.h"

 #endif

 

+#include "../../ICoder.h"

+

+#include "../../Archive/IArchive.h"

+

+

+#ifdef EXTERNAL_CODECS

+

 struct CDllCodecInfo

 {

-  CLSID Encoder;

-  CLSID Decoder;

+  unsigned LibIndex;

+  UInt32 CodecIndex;

   bool EncoderIsAssigned;

   bool DecoderIsAssigned;

-  int LibIndex;

-  UInt32 CodecIndex;

+  CLSID Encoder;

+  CLSID Decoder;

 };

 

 struct CDllHasherInfo

 {

-  int LibIndex;

+  unsigned LibIndex;

   UInt32 HasherIndex;

 };

 

-#include "../../Archive/IArchive.h"

+#endif

 

 struct CArcExtInfo

 {

@@ -129,9 +177,8 @@
   {}

 };

 

-#ifdef EXTERNAL_CODECS

-

 #ifdef NEW_FOLDER_INTERFACE

+

 struct CCodecIcons

 {

   struct CIconPair

@@ -140,11 +187,15 @@
     int IconIndex;

   };

   CObjectVector<CIconPair> IconPairs;

+

   void LoadIcons(HMODULE m);

   bool FindIconIndex(const UString &ext, int &iconIndex) const;

 };

+

 #endif

 

+#ifdef EXTERNAL_CODECS

+

 struct CCodecLib

   #ifdef NEW_FOLDER_INTERFACE

     : public CCodecIcons

@@ -152,56 +203,108 @@
 {

   NWindows::NDLL::CLibrary Lib;

   FString Path;

-  Func_GetMethodProperty GetMethodProperty;

+  

   Func_CreateObject CreateObject;

-  CMyComPtr<IHashers> Hashers;

+  Func_GetMethodProperty GetMethodProperty;

+  Func_CreateDecoder CreateDecoder;

+  Func_CreateEncoder CreateEncoder;

+  Func_SetCodecs SetCodecs;

+

+  CMyComPtr<IHashers> ComHashers;

   

   #ifdef NEW_FOLDER_INTERFACE

   void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }

   #endif

   

-  CCodecLib(): GetMethodProperty(NULL) {}

+  CCodecLib():

+      CreateObject(NULL),

+      GetMethodProperty(NULL),

+      CreateDecoder(NULL),

+      CreateEncoder(NULL),

+      SetCodecs(NULL)

+      {}

 };

+

 #endif

 

+

 class CCodecs:

   #ifdef EXTERNAL_CODECS

-  public ICompressCodecsInfo,

-  public IHashers,

+    public ICompressCodecsInfo,

+    public IHashers,

   #else

-  public IUnknown,

+    public IUnknown,

   #endif

   public CMyUnknownImp

 {

+  CLASS_NO_COPY(CCodecs);

 public:

   #ifdef EXTERNAL_CODECS

+  

   CObjectVector<CCodecLib> Libs;

-  CRecordVector<CDllCodecInfo> Codecs;

-  CRecordVector<CDllHasherInfo> Hashers;

+  FString MainDll_ErrorPath;

+

+  void CloseLibs();

+

+  class CReleaser

+  {

+    CLASS_NO_COPY(CReleaser);

+

+    /* CCodecsReleaser object releases CCodecs links.

+         1) CCodecs is COM object that is deleted when all links to that object will be released/

+         2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.

+       To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */

+

+    CCodecs *_codecs;

+      

+    public:

+    CReleaser(): _codecs(NULL) {}

+    void Set(CCodecs *codecs) { _codecs = codecs; }

+    ~CReleaser() { if (_codecs) _codecs->CloseLibs(); }

+  };

+

+  bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo

+

+  HRESULT LoadCodecs();

+  HRESULT LoadFormats();

+  HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);

+  HRESULT LoadDllsFromFolder(const FString &folderPrefix);

+

+  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const

+  {

+    return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);

+  }

+  

+  #endif

 

   #ifdef NEW_FOLDER_INTERFACE

   CCodecIcons InternalIcons;

   #endif

 

-  HRESULT LoadCodecs();

-  HRESULT LoadFormats();

-  HRESULT LoadDll(const FString &path, bool needCheckDll);

-  HRESULT LoadDllsFromFolder(const FString &folderPrefix);

-

-  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const

-  {

-    return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);

-  }

+  CObjectVector<CArcInfoEx> Formats;

+  

+  #ifdef EXTERNAL_CODECS

+  CRecordVector<CDllCodecInfo> Codecs;

+  CRecordVector<CDllHasherInfo> Hashers;

   #endif

 

-public:

-  CObjectVector<CArcInfoEx> Formats;

   bool CaseSensitiveChange;

   bool CaseSensitive;

 

-  CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {}

+  CCodecs():

+      #ifdef EXTERNAL_CODECS

+      NeedSetLibCodecs(true),

+      #endif

+      CaseSensitiveChange(false),

+      CaseSensitive(false)

+      {}

+

+  ~CCodecs()

+  {

+    // OutputDebugStringA("~CCodecs");

+  }

  

-  const wchar_t *GetFormatNamePtr(int formatIndex)

+  const wchar_t *GetFormatNamePtr(int formatIndex) const

   {

     return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;

   }

@@ -219,10 +322,10 @@
 

   MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)

     

-  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods);

+  STDMETHOD(GetNumMethods)(UInt32 *numMethods);

   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

-  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder);

-  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder);

+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);

+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);

 

   STDMETHOD_(UInt32, GetNumHashers)();

   STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);

@@ -234,16 +337,19 @@
 

   #endif // EXTERNAL_CODECS

 

+  

   #ifdef EXTERNAL_CODECS

 

-  int GetCodecLibIndex(UInt32 index);

-  bool GetCodecEncoderIsAssigned(UInt32 index);

-  HRESULT GetCodecId(UInt32 index, UInt64 &id);

-  UString GetCodecName(UInt32 index);

+  int GetCodec_LibIndex(UInt32 index) const;

+  bool GetCodec_DecoderIsAssigned(UInt32 index) const;

+  bool GetCodec_EncoderIsAssigned(UInt32 index) const;

+  UInt32 GetCodec_NumStreams(UInt32 index);

+  HRESULT GetCodec_Id(UInt32 index, UInt64 &id);

+  AString GetCodec_Name(UInt32 index);

 

   int GetHasherLibIndex(UInt32 index);

   UInt64 GetHasherId(UInt32 index);

-  UString GetHasherName(UInt32 index);

+  AString GetHasherName(UInt32 index);

   UInt32 GetHasherDigestSize(UInt32 index);

 

   #endif

@@ -261,7 +367,7 @@
       COM_TRY_END

     }

     #ifdef EXTERNAL_CODECS

-    return CreateArchiveHandler(ai, (void **)&archive, false);

+    return CreateArchiveHandler(ai, false, (void **)&archive);

     #endif

   }

   

@@ -279,8 +385,9 @@
       return S_OK;

       COM_TRY_END

     }

+    

     #ifdef EXTERNAL_CODECS

-    return CreateArchiveHandler(ai, (void **)&archive, true);

+    return CreateArchiveHandler(ai, true, (void **)&archive);

     #endif

   }

   

@@ -291,7 +398,7 @@
       const CArcInfoEx &arc = Formats[i];

       if (!arc.UpdateEnabled)

         continue;

-      if (arc.Name.IsEqualToNoCase(name))

+      if (arc.Name.IsEqualTo_NoCase(name))

         return i;

     }

     return -1;

@@ -300,4 +407,18 @@
   #endif // _SFX

 };

 

+#ifdef EXTERNAL_CODECS

+  #define CREATE_CODECS_OBJECT \

+    CCodecs *codecs = new CCodecs; \

+    CExternalCodecs __externalCodecs; \

+    __externalCodecs.GetCodecs = codecs; \

+    __externalCodecs.GetHashers = codecs; \

+    CCodecs::CReleaser codecsReleaser; \

+    codecsReleaser.Set(codecs);

+#else

+  #define CREATE_CODECS_OBJECT \

+    CCodecs *codecs = new CCodecs; \

+    CMyComPtr<IUnknown> __codecsRef = codecs;

+#endif

+  

 #endif

diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 4632be8..968f0ca 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -39,7 +39,7 @@
 #endif

 

 // increase it, if you need to support larger SFX stubs

-static const UInt64 kMaxCheckStartPosition = 1 << 22;

+static const UInt64 kMaxCheckStartPosition = 1 << 23;

 

 /*

 Open:

@@ -195,17 +195,13 @@
   }

 

   void AddUnknownItem(UInt64 next);

-  int FindInsertPos(const CParseItem &item);

+  int FindInsertPos(const CParseItem &item) const;

   void AddItem(const CParseItem &item);

-  // void Init();

   

-  CHandler()

-  {

-    _maxEndOffset = 0;

-  }

+  CHandler(): _maxEndOffset(0) {}

 };

 

-int CHandler::FindInsertPos(const CParseItem &item)

+int CHandler::FindInsertPos(const CParseItem &item) const

 {

   unsigned left = 0, right = _items.Size();

   while (left != right)

@@ -272,7 +268,7 @@
 }

 

 /*

-static const STATPROPSTG kProps[] =

+static const CStatProp kProps[] =

 {

   { NULL, kpidPath, VT_BSTR},

   { NULL, kpidSize, VT_UI8},

@@ -368,6 +364,7 @@
     Int32 testMode, IArchiveExtractCallback *extractCallback)

 {

   COM_TRY_BEGIN

+  

   bool allFilesMode = (numItems == (UInt32)(Int32)-1);

   if (allFilesMode)

     numItems = _items.Size();

@@ -429,7 +426,9 @@
     outStreamSpec->ReleaseStream();

     RINOK(extractCallback->SetOperationResult(opRes));

   }

+  

   return S_OK;

+  

   COM_TRY_END

 }

 

@@ -458,7 +457,7 @@
   return S_OK;

 }

 

-HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw()

+HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw()

 {

   return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);

 }

@@ -478,7 +477,7 @@
   return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);

 }

 

-static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result)

+static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw()

 {

   NCOM::CPropVariant prop;

   result = false;

@@ -498,7 +497,7 @@
   switch (prop.vt)

   {

     case VT_UI4: result = prop.ulVal; defined = true; break;

-    case VT_I4: result = prop.lVal; defined = true; break;

+    case VT_I4: result = (Int64)prop.lVal; defined = true; break;

     case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break;

     case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break;

     case VT_EMPTY: break;

@@ -524,16 +523,22 @@
   return S_OK;

 }

 

+#ifndef _SFX

+

 HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const

 {

   if (!GetRawProps)

     return E_FAIL;

+  if (index == parent)

+    return S_OK;

   UInt32 curIndex = index;

+  

+  UString s;

+  

   bool prevWasAltStream = false;

+  

   for (;;)

   {

-    UString s;

-    

     #ifdef MY_CPU_LE

     const void *p;

     UInt32 size;

@@ -546,31 +551,59 @@
     {

       NCOM::CPropVariant prop;

       RINOK(Archive->GetProperty(curIndex, kpidName, &prop));

-      if (prop.vt == VT_BSTR)

-        s = prop.bstrVal;

+      if (prop.vt == VT_BSTR && prop.bstrVal)

+        s.SetFromBstr(prop.bstrVal);

       else if (prop.vt == VT_EMPTY)

-        s = L"[Content]";

+        s.Empty();

       else

         return E_FAIL;

     }

-    

-    if (prevWasAltStream)

-      parts[0] = s + L":" + parts[0];

-    else

-      parts.Insert(0, s);

 

     UInt32 curParent = (UInt32)(Int32)-1;

     UInt32 parentType = 0;

     RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType));

+

+    if (parentType != NParentType::kAltStream)

+    {

+      for (;;)

+      {

+        int pos = s.ReverseFind_PathSepar();

+        if (pos < 0)

+        {

+          break;

+        }

+        parts.Insert(0, s.Ptr(pos + 1));

+        s.DeleteFrom(pos);

+      }

+    }

+    

+    parts.Insert(0, s);

+

+    if (prevWasAltStream)

+    {

+      {

+        UString &s2 = parts[parts.Size() - 2];

+        s2 += L':';

+        s2 += parts.Back();

+      }

+      parts.DeleteBack();

+    }

+

     if (parent == curParent)

       return S_OK;

+    

+    prevWasAltStream = false;

+    if (parentType == NParentType::kAltStream)

+      prevWasAltStream = true;

+    

     if (curParent == (UInt32)(Int32)-1)

       return E_FAIL;

-    prevWasAltStream = (parentType == NParentType::kAltStream);

     curIndex = curParent;

   }

 }

 

+#endif

+

 HRESULT CArc::GetItemPath(UInt32 index, UString &result) const

 {

   #ifdef MY_CPU_LE

@@ -585,7 +618,7 @@
           propType == NPropDataType::kUtf16z)

       {

         unsigned len = size / 2 - 1;

-        wchar_t *s = result.GetBuffer(len);

+        wchar_t *s = result.GetBuf(len);

         for (unsigned i = 0; i < len; i++)

         {

           wchar_t c = GetUi16(p);

@@ -596,7 +629,8 @@
           #endif

           *s++ = c;

         }

-        result.ReleaseBuffer(len);

+        *s = 0;

+        result.ReleaseBuf_SetLen(len);

         if (len != 0)

           return S_OK;

       }

@@ -605,8 +639,10 @@
     else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&

         p && propType == NPropDataType::kUtf16z)

     {

+      size -= 2;

       UInt32 totalSize = size;

       bool isOK = false;

+      

       {

         UInt32 index2 = index;

         for (;;)

@@ -617,13 +653,16 @@
             break;

           if (parent == (UInt32)(Int32)-1)

           {

+            if (parentType != 0)

+              totalSize += 2;

             isOK = true;

             break;

           }

           index2 = parent;

           UInt32 size2;

           const void *p2;

-          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)

+          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK &&

+              p2 && propType == NPropDataType::kUtf16z)

             break;

           totalSize += size2;

         }

@@ -631,9 +670,9 @@
 

       if (isOK)

       {

-        wchar_t *sz = result.GetBuffer(totalSize / 2);

+        wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2);

         UInt32 pos = totalSize - size;

-        memcpy((Byte *)sz + pos, p, size - 2);

+        memcpy((Byte *)sz + pos, p, size);

         UInt32 index2 = index;

         for (;;)

         {

@@ -642,7 +681,11 @@
           if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)

             break;

           if (parent == (UInt32)(Int32)-1)

+          {

+            if (parentType != 0)

+              sz[pos / 2 - 1] = L':';

             break;

+          }

           index2 = parent;

           UInt32 size2;

           const void *p2;

@@ -652,7 +695,6 @@
           memcpy((Byte *)sz + pos, p2, size2);

           sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';

         }

-        result.ReleaseBuffer((totalSize - 2) / 2);

         #ifdef _WIN32

         // result.Replace(L'/', WCHAR_PATH_SEPARATOR);

         #endif

@@ -666,8 +708,8 @@
   {

     NCOM::CPropVariant prop;

     RINOK(Archive->GetProperty(index, kpidPath, &prop));

-    if (prop.vt == VT_BSTR)

-      result = prop.bstrVal;

+    if (prop.vt == VT_BSTR && prop.bstrVal)

+      result.SetFromBstr(prop.bstrVal);

     else if (prop.vt == VT_EMPTY)

       result.Empty();

     else

@@ -675,6 +717,16 @@
   }

   

   if (result.IsEmpty())

+    return GetDefaultItemPath(index, result);

+  return S_OK;

+}

+

+HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const

+{

+  result.Empty();

+  bool isDir;

+  RINOK(Archive_IsItem_Dir(Archive, index, isDir));

+  if (!isDir)

   {

     result = DefaultName;

     NCOM::CPropVariant prop;

@@ -703,6 +755,161 @@
   return S_OK;

 }

 

+#ifdef SUPPORT_ALT_STREAMS

+

+int FindAltStreamColon_in_Path(const wchar_t *path)

+{

+  unsigned i = 0;

+  int colonPos = -1;

+  for (;; i++)

+  {

+    wchar_t c = path[i];

+    if (c == 0)

+      return colonPos;

+    if (c == ':')

+    {

+      if (colonPos < 0)

+        colonPos = i;

+      continue;

+    }

+    if (c == WCHAR_PATH_SEPARATOR)

+      colonPos = -1;

+  }

+}

+

+#endif

+

+HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const

+{

+  #ifdef SUPPORT_ALT_STREAMS

+  item.IsAltStream = false;

+  item.AltStreamName.Empty();

+  item.MainPath.Empty();

+  #endif

+

+  item.IsDir = false;

+  item.Path.Empty();

+  item.ParentIndex = (UInt32)(Int32)-1;

+  

+  item.PathParts.Clear();

+

+  RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir));

+  item.MainIsDir = item.IsDir;

+

+  RINOK(GetItemPath2(index, item.Path));

+

+  #ifndef _SFX

+  UInt32 mainIndex = index;

+  #endif

+

+  #ifdef SUPPORT_ALT_STREAMS

+

+  item.MainPath = item.Path;

+  if (Ask_AltStream)

+  {

+    RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream));

+  }

+  

+  bool needFindAltStream = false;

+

+  if (item.IsAltStream)

+  {

+    needFindAltStream = true;

+    if (GetRawProps)

+    {

+      UInt32 parentType = 0;

+      UInt32 parentIndex;

+      RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType));

+      if (parentType == NParentType::kAltStream)

+      {

+        NCOM::CPropVariant prop;

+        RINOK(Archive->GetProperty(index, kpidName, &prop));

+        if (prop.vt == VT_BSTR && prop.bstrVal)

+          item.AltStreamName.SetFromBstr(prop.bstrVal);

+        else if (prop.vt != VT_EMPTY)

+          return E_FAIL;

+        else

+        {

+          // item.IsAltStream = false;

+        }

+        /*

+        if (item.AltStreamName.IsEmpty())

+          item.IsAltStream = false;

+        */

+

+        needFindAltStream = false;

+        item.ParentIndex = parentIndex;

+        mainIndex = parentIndex;

+

+        if (parentIndex == (UInt32)(Int32)-1)

+        {

+          item.MainPath.Empty();

+          item.MainIsDir = true;

+        }

+        else

+        {

+          RINOK(GetItemPath2(parentIndex, item.MainPath));

+          RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir));

+        }

+      }

+    }

+  }

+

+  if (item.WriteToAltStreamIfColon || needFindAltStream)

+  {

+    /* Good handler must support GetRawProps::GetParent for alt streams./

+       So the following code currently is not used */

+    int colon = FindAltStreamColon_in_Path(item.Path);

+    if (colon >= 0)

+    {

+      item.MainPath.DeleteFrom(colon);

+      item.AltStreamName = item.Path.Ptr(colon + 1);

+      item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1]));

+      item.IsAltStream = true;

+    }

+  }

+

+  #endif

+  

+  #ifndef _SFX

+  if (item._use_baseParentFolder_mode)

+  {

+    RINOK(GetItemPathToParent(mainIndex, item._baseParentFolder, item.PathParts));

+    

+    #ifdef SUPPORT_ALT_STREAMS

+    if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())

+    {

+      int colon;

+      {

+        UString &s = item.PathParts.Back();

+        colon = FindAltStreamColon_in_Path(s);

+        if (colon >= 0)

+        {

+          item.AltStreamName = s.Ptr(colon + 1);

+          item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1]));

+          item.IsAltStream = true;

+          s.DeleteFrom(colon);

+        }

+      }

+      if (colon == 0)

+        item.PathParts.DeleteBack();

+    }

+    #endif

+    

+  }

+  else

+  #endif

+    SplitPathToParts(

+          #ifdef SUPPORT_ALT_STREAMS

+            item.MainPath

+          #else

+            item.Path

+          #endif

+      , item.PathParts);

+

+  return S_OK;

+}

+

 #ifndef _SFX

 

 static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)

@@ -824,10 +1031,10 @@
 

 static bool IsExeExt(const UString &ext)

 {

-  return ext.IsEqualToNoCase(L"exe");

+  return ext.IsEqualTo_Ascii_NoCase("exe");

 }

 

-static const char *k_PreArcFormats[] =

+static const char * const k_PreArcFormats[] =

 {

     "pe"

   , "elf"

@@ -836,7 +1043,7 @@
   , "te"

 };

 

-static bool IsNameFromList(const UString &s, const char *names[], size_t num)

+static bool IsNameFromList(const UString &s, const char * const names[], size_t num)

 {

   for (unsigned i = 0; i < num; i++)

     if (StringsAreEqualNoCase_Ascii(s, names[i]))

@@ -852,7 +1059,7 @@
   return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats));

 }

 

-static const char *k_Formats_with_simple_signuature[] =

+static const char * const k_Formats_with_simple_signuature[] =

 {

     "7z"

   , "xz"

@@ -876,6 +1083,7 @@
 

 class CArchiveOpenCallback_Offset:

   public IArchiveOpenCallback,

+  public IArchiveOpenVolumeCallback,

   #ifndef _NO_CRYPTO

   public ICryptoGetTextPassword,

   #endif

@@ -883,19 +1091,24 @@
 {

 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

@@ -912,12 +1125,12 @@
 }

 #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;

@@ -927,8 +1140,25 @@
   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)

@@ -984,14 +1214,14 @@
     NCOM::CPropVariant prop;

     RINOK(archive->GetArchiveProperty(kpidError, &prop));

     if (prop.vt != VT_EMPTY)

-      ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";

+      ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error");

   }

   

   {

     NCOM::CPropVariant prop;

     RINOK(archive->GetArchiveProperty(kpidWarning, &prop));

     if (prop.vt != VT_EMPTY)

-      ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning";

+      ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning");

   }

   

   if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())

@@ -1039,30 +1269,40 @@
 

 HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)

 {

-  // OutputDebugStringW(L"a1");

+  // OutputDebugStringA("a1");

   // PrintNumber("formatIndex", formatIndex);

     

   RINOK(op.codecs->CreateInArchive(formatIndex, archive));

-  // OutputDebugStringW(L"a2");

+  // OutputDebugStringA("a2");

   if (!archive)

     return S_OK;

 

   #ifdef EXTERNAL_CODECS

+  if (op.codecs->NeedSetLibCodecs)

   {

-    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

-    archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

-    if (setCompressCodecsInfo)

+    const CArcInfoEx &ai = op.codecs->Formats[formatIndex];

+    if (ai.LibIndex >= 0 ?

+        !op.codecs->Libs[ai.LibIndex].SetCodecs :

+        !op.codecs->Libs.IsEmpty())

     {

-      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));

+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

+      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

+      if (setCompressCodecsInfo)

+      {

+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));

+      }

     }

   }

   #endif

   

-  // OutputDebugStringW(ai.Name);

-  // OutputDebugStringW(L"a3");

   

   #ifndef _SFX

+

   const CArcInfoEx &ai = op.codecs->Formats[formatIndex];

+ 

+  // OutputDebugStringW(ai.Name);

+  // OutputDebugStringA("a3");

+

   if (ai.Flags_PreArc())

   {

     /* we notify parsers that extract executables, that they don't need

@@ -1072,6 +1312,7 @@
     if (allowTail)

       allowTail->AllowTail(BoolToInt(true));

   }

+

   if (op.props)

   {

     /*

@@ -1087,6 +1328,7 @@
     */

     RINOK(SetProperties(archive, *op.props));

   }

+  

   #endif

   return S_OK;

 }

@@ -1130,14 +1372,14 @@
     RINOK(archive->GetArchiveProperty(kpidName, &prop));

     if (prop.vt == VT_BSTR)

     {

-      pi.Name = prop.bstrVal;

+      pi.Name.SetFromBstr(prop.bstrVal);

       pi.Extension.Empty();

     }

     else

     {

       RINOK(archive->GetArchiveProperty(kpidExtension, &prop));

       if (prop.vt == VT_BSTR)

-        pi.Extension = prop.bstrVal;

+        pi.Extension.SetFromBstr(prop.bstrVal);

     }

   }

   

@@ -1145,7 +1387,7 @@
     NCOM::CPropVariant prop;

     RINOK(archive->GetArchiveProperty(kpidShortComment, &prop));

     if (prop.vt == VT_BSTR)

-      pi.Comment = prop.bstrVal;

+      pi.Comment.SetFromBstr(prop.bstrVal);

   }

 

 

@@ -1171,7 +1413,7 @@
       }

 

       bool isDir = false;

-      Archive_IsItem_Folder(archive, i, isDir);

+      Archive_IsItem_Dir(archive, i, isDir);

       if (isDir)

         pi.NumSubDirs++;

       else

@@ -1336,13 +1578,13 @@
   IsParseArc = false;

   ArcStreamOffset = 0;

   

-  // OutputDebugStringW(L"1");

+  // OutputDebugStringA("1");

   // OutputDebugStringW(Path);

 

   const UString fileName = ExtractFileNameFromPath(Path);

   UString extension;

   {

-    int dotPos = fileName.ReverseFind(L'.');

+    int dotPos = fileName.ReverseFind_Dot();

     if (dotPos >= 0)

       extension = fileName.Ptr(dotPos + 1);

   }

@@ -1378,7 +1620,7 @@
     isForced = true;

     orderIndices.Add(formatIndex);

     numMainTypes = 1;

-    isMainFormatArr[formatIndex] = true;

+    isMainFormatArr[(unsigned)formatIndex] = true;

 

     searchMarkerInHandler = true;

   }

@@ -1390,6 +1632,36 @@
     #endif

     

     {

+      #ifndef _SFX

+      

+      bool isZip = false;

+      bool isRar = false;

+      

+      const wchar_t c = extension[0];

+      if (c == 'z' || c == 'Z' || c == 'r' || c == 'R')

+      {

+        bool isNumber = false;

+        for (unsigned k = 1;; k++)

+        {

+          const wchar_t d = extension[k];

+          if (d == 0)

+            break;

+          if (d < '0' || d > '9')

+          {

+            isNumber = false;

+            break;

+          }

+          isNumber = true;

+        }

+        if (isNumber)

+          if (c == 'z' || c == 'Z')

+            isZip = true;

+          else

+            isRar = true;

+      }

+      

+      #endif

+

       FOR_VECTOR (i, op.codecs->Formats)

       {

         const CArcInfoEx &ai = op.codecs->Formats[i];

@@ -1405,7 +1677,12 @@
           isPrearcExt = true;

         #endif

 

-        if (ai.FindExtension(extension) >= 0)

+        if (ai.FindExtension(extension) >= 0

+            #ifndef _SFX

+            || isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")

+            || isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")

+            #endif

+            )

         {

           // PrintNumber("orderIndices.Insert", i);

           orderIndices.Insert(numFinded++, i);

@@ -1443,7 +1720,7 @@
         {

           // signature search was here

         }

-        else if (extension == L"000" || extension == L"001")

+        else if (extension.IsEqualTo("000") || extension.IsEqualTo("001"))

         {

           int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");

           if (i >= 0)

@@ -1517,6 +1794,10 @@
     #else // _SFX

 

       numMainTypes = orderIndices.Size();

+

+      // we need correct numMainTypes for mutlivolume SFX (if some volume is missing)

+      if (numFinded != 0)

+        numMainTypes = numFinded;

     

     #endif

   }

@@ -1557,10 +1838,13 @@
     for (unsigned i = 0; i < numCheckTypes; i++)

     {

       FormatIndex = orderIndices[i];

-      const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

-      // OutputDebugStringW(ai.Name);

       

       bool exactOnly = false;

+

+      #ifndef _SFX

+    

+      const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

+      // OutputDebugStringW(ai.Name);

       if (i >= numMainTypes)

       {

         if (!ai.Flags_BackwardOpen()

@@ -1569,9 +1853,13 @@
           continue;

         exactOnly = true;

       }

+

+      #endif

       

       // Some handlers do not set total bytes. So we set it here

-      RINOK(op.callback->SetTotal(NULL, &fileSize));

+      if (op.callback)

+        RINOK(op.callback->SetTotal(NULL, &fileSize));

+

       if (op.stream)

       {

         RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

@@ -1607,7 +1895,7 @@
         #ifndef _SFX

         // if it's archive, we allow another open attempt for parser

         if (!mode.CanReturnParser || !isArc)

-          skipFrontalFormat[FormatIndex] = true;

+          skipFrontalFormat[(unsigned)FormatIndex] = true;

         #endif

         

         if (exactOnly)

@@ -1650,7 +1938,7 @@
       

       #ifndef _SFX

 

-      bool isMainFormat = isMainFormatArr[FormatIndex];

+      bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];

       const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);

 

       bool thereIsTail = ErrorInfo.ThereIsTail;

@@ -1727,7 +2015,6 @@
       const CArcInfoEx &ai = op.codecs->Formats[formatIndex];

       if (ai.FindExtension(extension) >= 0)

       {

-        const CArcInfoEx &ai = op.codecs->Formats[formatIndex];

         if (ai.Flags_FindSignature() && searchMarkerInHandler)

           return S_FALSE;

       }

@@ -1834,7 +2121,9 @@
       FormatIndex = sortedFormats[i];

       const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

 

-      RINOK(op.callback->SetTotal(NULL, &fileSize));

+      if (op.callback)

+        RINOK(op.callback->SetTotal(NULL, &fileSize));

+

       RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

 

       CMyComPtr<IInArchive> archive;

@@ -1856,7 +2145,7 @@
       

       if (result == S_FALSE)

       {

-        skipFrontalFormat[FormatIndex] = true;

+        skipFrontalFormat[(unsigned)FormatIndex] = true;

         // FIXME: maybe we must use LenIsUnknown.

         // printf("  OpenForSize Error");

         continue;

@@ -1900,7 +2189,7 @@
 

       if (mode.CanReturnArc)

       {

-        bool isMainFormat = isMainFormatArr[FormatIndex];

+        bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];

         const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);

         bool openCur = false;

 

@@ -1938,7 +2227,7 @@
         }

       }

         

-      skipFrontalFormat[FormatIndex] = true;

+      skipFrontalFormat[(unsigned)FormatIndex] = true;

 

 

       // if (!mode.CanReturnArc)

@@ -1976,9 +2265,6 @@
   }

   

   {

-    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

@@ -2032,7 +2318,7 @@
           }

           thereAreHandlersForSearch = true;

           UInt32 v = HASH_VAL(sig, 0);

-          unsigned sigIndex = arc2sig[index] + k;

+          unsigned sigIndex = arc2sig[(unsigned)index] + k;

           prevs[sigIndex] = hash[v];

           hash[v] = (Byte)sigIndex;

         }

@@ -2056,16 +2342,22 @@
     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

 

-    RINOK(op.callback->SetTotal(NULL, &fileSize));

+    if (op.callback)

+      RINOK(op.callback->SetTotal(NULL, &fileSize));

+  

     CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;

     byteBuffer.Alloc(kBufSize);

 

@@ -2148,12 +2440,19 @@
         }

       }

 

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

+        }

       }

 

       {

@@ -2323,14 +2622,21 @@
         }

         

         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;

@@ -2607,11 +2913,12 @@
     RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));

     RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));

     RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));

+    RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly));

 

     const UString fileName = ExtractFileNameFromPath(Path);

     UString extension;

     {

-      int dotPos = fileName.ReverseFind(L'.');

+      int dotPos = fileName.ReverseFind_Dot();

       if (dotPos >= 0)

         extension = fileName.Ptr(dotPos + 1);

     }

@@ -2621,7 +2928,7 @@
     {

       const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

       if (ai.Exts.Size() == 0)

-        DefaultName = GetDefaultName2(fileName, L"", L"");

+        DefaultName = GetDefaultName2(fileName, UString(), UString());

       else

       {

         int subExtIndex = ai.FindExtension(extension);

@@ -2639,10 +2946,10 @@
 #ifdef _SFX

 

 #ifdef _WIN32

-  static const wchar_t *k_ExeExt = L".exe";

+  static const char *k_ExeExt = ".exe";

   static const unsigned k_ExeExt_Len = 4;

 #else

-  static const wchar_t *k_ExeExt = L"";

+  static const char *k_ExeExt = "";

   static const unsigned k_ExeExt_Len = 0;

 #endif

 

@@ -2653,6 +2960,7 @@
   CMyComPtr<IInStream> fileStream;

   CMyComPtr<ISequentialInStream> seqStream;

   CInFileStream *fileStreamSpec = NULL;

+  

   if (op.stdInMode)

   {

     seqStream = new CStdInFileStream;

@@ -2692,9 +3000,10 @@
       || !op.callbackSpec

       || NonOpen_ErrorInfo.IsArc_After_NonOpen())

     return res;

+  

   {

     if (filePath.Len() > k_ExeExt_Len

-        && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0)

+        && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt))

     {

       const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);

       FOR_VECTOR (i, op.codecs->Formats)

@@ -2703,9 +3012,10 @@
         if (ai.IsSplit())

           continue;

         UString path3 = path2;

-        path3 += L".";

+        path3 += L'.';

         path3 += ai.GetMainExt(); // "7z"  for SFX.

-        Path = path3 + L".001";

+        Path = path3;

+        Path.AddAscii(".001");

         bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));

         if (!isOk)

         {

@@ -2733,8 +3043,9 @@
 

 void CArchiveLink::KeepModeForNextOpen()

 {

-  for (int i = Arcs.Size() - 1; i >= 0; i--)

+  for (unsigned i = Arcs.Size(); i != 0;)

   {

+    i--;

     CMyComPtr<IArchiveKeepModeForNextOpen> keep;

     Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);

     if (keep)

@@ -2744,8 +3055,9 @@
 

 HRESULT CArchiveLink::Close()

 {

-  for (int i = Arcs.Size() - 1; i >= 0; i--)

+  for (unsigned i = Arcs.Size(); i != 0;)

   {

+    i--;

     RINOK(Arcs[i].Close());

   }

   IsOpen = false;

@@ -2771,20 +3083,20 @@
     if (!arc.ErrorFlagsText.IsEmpty())

     {

       if (!ErrorsText.IsEmpty())

-        ErrorsText += L'\n';

+        ErrorsText.Add_LF();

       ErrorsText += GetUnicodeString(arc.ErrorFlagsText);

     }

     if (!arc.ErrorMessage.IsEmpty())

     {

       if (!ErrorsText.IsEmpty())

-        ErrorsText += L'\n';

+        ErrorsText.Add_LF();

       ErrorsText += arc.ErrorMessage;

     }

 

     if (!arc.WarningMessage.IsEmpty())

     {

       if (!ErrorsText.IsEmpty())

-        ErrorsText += L'\n';

+        ErrorsText.Add_LF();

       ErrorsText += arc.WarningMessage;

     }

   }

@@ -2909,10 +3221,14 @@
     bool zerosTailIsAllowed;

     RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));

 

-    CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;

-    op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);

-    if (setSubArchiveName)

-      setSubArchiveName->SetSubArchiveName(arc2.Path);

+

+    if (op.callback)

+    {

+      CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;

+      op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);

+      if (setSubArchiveName)

+        setSubArchiveName->SetSubArchiveName(arc2.Path);

+    }

     

     arc2.SubfileIndex = mainSubfile;

 

@@ -2951,23 +3267,7 @@
   return resSpec;

 }

 

-static void SetCallback(const FString &filePath,

-    IOpenCallbackUI *callbackUI,

-    IArchiveOpenCallback *reOpenCallback,

-    CMyComPtr<IArchiveOpenCallback> &callback)

-{

-  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;

-  callback = openCallbackSpec;

-  openCallbackSpec->Callback = callbackUI;

-  openCallbackSpec->ReOpenCallback = reOpenCallback;

-

-  FString dirPrefix, fileName;

-  NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName);

-  openCallbackSpec->Init(dirPrefix, fileName);

-}

-

-HRESULT CArchiveLink::Open2(COpenOptions &op,

-    IOpenCallbackUI *callbackUI)

+HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)

 {

   VolumesSize = 0;

   COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;

@@ -2975,6 +3275,7 @@
   openCallbackSpec->Callback = callbackUI;

 

   FString prefix, name;

+  

   if (!op.stream && !op.stdInMode)

   {

     NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);

@@ -2987,7 +3288,13 @@
 

   op.callback = callback;

   op.callbackSpec = openCallbackSpec;

-  RINOK(Open(op));

+  

+  HRESULT res = Open(op);

+

+  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;

+  // Password = openCallbackSpec->Password;

+

+  RINOK(res);

   // VolumePaths.Add(fs2us(prefix + name));

 

   FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)

@@ -3044,6 +3351,15 @@
   return res;

 }

 

+HRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI)

+{

+  HRESULT res = Open2(op, callbackUI);

+  if (callbackUI)

+  {

+    RINOK(callbackUI->Open_Finished());

+  }

+  return res;

+}

 

 HRESULT CArchiveLink::ReOpen(COpenOptions &op)

 {

@@ -3060,8 +3376,17 @@
   if (Arcs.Size() == 0) // ???

     return Open2(op, NULL);

 

-  CMyComPtr<IArchiveOpenCallback> openCallbackNew;

-  SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew);

+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;

+  CMyComPtr<IArchiveOpenCallback> openCallbackNew = openCallbackSpec;

+

+  openCallbackSpec->Callback = NULL;

+  openCallbackSpec->ReOpenCallback = op.callback;

+  {

+    FString dirPrefix, fileName;

+    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName);

+    openCallbackSpec->Init(dirPrefix, fileName);

+  }

+

 

   CInFileStream *fileStreamSpec = new CInFileStream;

   CMyComPtr<IInStream> stream(fileStreamSpec);

@@ -3071,6 +3396,10 @@
 

   CArc &arc = Arcs[0];

   HRESULT res = arc.ReOpen(op);

+  

+  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;

+  // Password = openCallbackSpec->Password;

+  

   IsOpen = (res == S_OK);

   return res;

 }

@@ -3136,7 +3465,9 @@
 

 bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)

 {

-  int pos2 = s.Find(':');

+  int pos2 = s.Find(L':');

+

+  {

   UString name;

   if (pos2 < 0)

   {

@@ -3171,13 +3502,15 @@
   }

   

   type.FormatIndex = index;

+

+  }

  

   for (unsigned i = pos2; i < s.Len();)

   {

-    int next = s.Find(':', i);

+    int next = s.Find(L':', i);

     if (next < 0)

       next = s.Len();

-    UString name = s.Mid(i, next - i);

+    const UString name = s.Mid(i, next - i);

     if (name.IsEmpty())

       return false;

     if (!ParseTypeParams(name, type))

@@ -3193,7 +3526,7 @@
   types.Clear();

   for (unsigned pos = 0; pos < s.Len();)

   {

-    int pos2 = s.Find('.', pos);

+    int pos2 = s.Find(L'.', pos);

     if (pos2 < 0)

       pos2 = s.Len();

     UString name = s.Mid(pos, pos2 - pos);

diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index 6f07323..0395987 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -9,12 +9,22 @@
 #include "LoadCodecs.h"

 #include "Property.h"

 

+#ifndef _SFX

+

+#define SUPPORT_ALT_STREAMS

+

+#endif

+

 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();

-HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw();

+HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();

 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();

 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();

 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();

 

+#ifdef SUPPORT_ALT_STREAMS

+int FindAltStreamColon_in_Path(const wchar_t *path);

+#endif

+

 /*

 struct COptionalOpenProperties

 {

@@ -212,12 +222,53 @@
   }

 };

 

+struct CReadArcItem

+{

+  UString Path;            // Path from root (including alt stream name, if alt stream)

+  UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode

+

+  #ifdef SUPPORT_ALT_STREAMS

+  UString MainPath;

+                /* MainPath = Path for non-AltStream,

+                   MainPath = Path of parent, if there is parent for AltStream. */

+  UString AltStreamName;

+  bool IsAltStream;

+  bool WriteToAltStreamIfColon;

+  #endif

+

+  bool IsDir;

+  bool MainIsDir;

+  UInt32 ParentIndex; // use it, if IsAltStream

+

+  #ifndef _SFX

+  bool _use_baseParentFolder_mode;

+  int _baseParentFolder;

+  #endif

+

+  CReadArcItem()

+  {

+    #ifdef SUPPORT_ALT_STREAMS

+    WriteToAltStreamIfColon = false;

+    #endif

+

+    #ifndef _SFX

+    _use_baseParentFolder_mode = false;

+    _baseParentFolder = -1;

+    #endif

+  }

+};

+

 class CArc

 {

   HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);

   HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);

   HRESULT OpenStream2(const COpenOptions &options);

 

+  #ifndef _SFX

+  // parts.Back() can contain alt stream name "nams:AltName"

+  HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;

+  #endif

+

 public:

   CMyComPtr<IInArchive> Archive;

   CMyComPtr<IInStream> InStream;

@@ -248,6 +299,8 @@
   UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file

   // bool offsetDefined;

 

+  UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }

+

   UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler

   Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive

 

@@ -256,6 +309,7 @@
   bool IsParseArc;

 

   bool IsTree;

+  bool IsReadOnly;

   

   bool Ask_Deleted;

   bool Ask_AltStream;

@@ -269,6 +323,7 @@
   CArc():

     MTimeDefined(false),

     IsTree(false),

+    IsReadOnly(false),

     Ask_Deleted(false),

     Ask_AltStream(false),

     Ask_Aux(false),

@@ -286,13 +341,13 @@
     return Archive->Close();

   }

 

-  // AltStream's name is concatenated with base file name in one string in parts.Back()

-  HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;

-

   HRESULT GetItemPath(UInt32 index, UString &result) const;

+  HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;

   

   // GetItemPath2 adds [DELETED] dir prefix for deleted items.

   HRESULT GetItemPath2(UInt32 index, UString &result) const;

+

+  HRESULT GetItem(UInt32 index, CReadArcItem &item) const;

   

   HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;

   HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;

@@ -315,6 +370,9 @@
   UInt64 VolumesSize;

   bool IsOpen;

 

+  bool PasswordWasAsked;

+  // UString Password;

+

   // int NonOpenErrorFormatIndex; // - 1 means no Error.

   UString NonOpen_ArcPath;

 

@@ -323,7 +381,12 @@
   // UString ErrorsText;

   // void Set_ErrorsText();

 

-  CArchiveLink(): VolumesSize(0), IsOpen(false) {}

+  CArchiveLink():

+      VolumesSize(0),

+      IsOpen(false),

+      PasswordWasAsked(false)

+      {}

+

   void KeepModeForNextOpen();

   HRESULT Close();

   void Release();

@@ -335,8 +398,16 @@
   IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }

 

   HRESULT Open(COpenOptions &options);

-

   HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);

+  HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);

+

+  HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)

+  {

+    HRESULT result = Open3(options, callbackUI);

+    if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+      result = S_FALSE;

+    return result;

+  }

 

   HRESULT ReOpen(COpenOptions &options);

 };

diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index a9278cd..9633248 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -7,7 +7,6 @@
 #include "../../../Common/IntToString.h"

 #include "../../../Common/StringConvert.h"

 

-#include "../../../Windows/FileFind.h"

 #include "../../../Windows/FileIO.h"

 #include "../../../Windows/PropVariantConv.h"

 

@@ -41,20 +40,53 @@
 16 VIRTUAL

 */

 

-void ConvertWinAttribToString(char *s, UInt32 wa)

+static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };

+#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';

+

+static void ConvertPosixAttribToString(char *s, UInt32 a) throw()

+{

+  s[0] = kPosixTypes[(a >> 12) & 0xF];

+  for (int i = 6; i >= 0; i -= 3)

+  {

+    s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');

+    s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');

+    s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');

+  }

+  if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S');

+  if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S');

+  if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T');

+  s[10] = 0;

+  

+  a &= ~(UInt32)0xFFFF;

+  if (a != 0)

+  {

+    s[10] = ' ';

+    ConvertUInt32ToHex8Digits(a, s + 11);

+  }

+}

+

+void ConvertWinAttribToString(char *s, UInt32 wa) throw()

 {

   for (int i = 0; i < 16; i++)

     if ((wa & (1 << i)) && i != 7)

       *s++ = g_WinAttribChars[i];

   *s = 0;

-}

 

-static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };

-#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';

+  // we support p7zip trick that stores posix attributes in high 16 bits, and 0x8000 flag

+  // we also support ZIP archives created in Unix, that store posix attributes in high 16 bits without 0x8000 flag

+  

+  // if (wa & 0x8000)

+  if ((wa >> 16) != 0)

+  {

+    *s++ = ' ';

+    ConvertPosixAttribToString(s, wa >> 16);

+  }

+}

 

 void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()

 {

   *dest = 0;

+  

   if (prop.vt == VT_FILETIME)

   {

     FILETIME localFileTime;

@@ -65,6 +97,7 @@
     ConvertFileTimeToString(localFileTime, dest, true, full);

     return;

   }

+

   switch (propID)

   {

     case kpidCRC:

@@ -78,34 +111,21 @@
     {

       if (prop.vt != VT_UI4)

         break;

-      ConvertWinAttribToString(dest, prop.ulVal);

+      UInt32 a = prop.ulVal;

+

+      /*

+      if ((a & 0x8000) && (a & 0x7FFF) == 0)

+        ConvertPosixAttribToString(dest, a >> 16);

+      else

+      */

+      ConvertWinAttribToString(dest, a);

       return;

     }

     case kpidPosixAttrib:

     {

       if (prop.vt != VT_UI4)

         break;

-      UString res;

-      UInt32 a = prop.ulVal;

-

-      dest[0] = kPosixTypes[(a >> 12) & 0xF];

-      for (int i = 6; i >= 0; i -= 3)

-      {

-        dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');

-        dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');

-        dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');

-      }

-      if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S');

-      if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S');

-      if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T');

-      dest[10] = 0;

-

-      a &= ~(UInt32)0xFFFF;

-      if (a != 0)

-      {

-        dest[10] = ' ';

-        ConvertUInt32ToHex8Digits(a, dest + 11);

-      }

+      ConvertPosixAttribToString(dest, prop.ulVal);

       return;

     }

     case kpidINode:

@@ -122,16 +142,19 @@
     case kpidVa:

     {

       UInt64 v = 0;

-      if (ConvertPropVariantToUInt64(prop, v))

-      {

-        dest[0] = '0';

-        dest[1] = 'x';

-        ConvertUInt64ToHex(prop.ulVal, dest + 2);

-        return;

-      }

-      break;

+      if (prop.vt == VT_UI4)

+        v = prop.ulVal;

+      else if (prop.vt == VT_UI8)

+        v = (UInt64)prop.uhVal.QuadPart;

+      else

+        break;

+      dest[0] = '0';

+      dest[1] = 'x';

+      ConvertUInt64ToHex(v, dest + 2);

+      return;

     }

   }

+  

   ConvertPropVariantToShortString(prop, dest);

 }

 

@@ -139,29 +162,25 @@
 {

   if (prop.vt == VT_BSTR)

   {

-    dest = prop.bstrVal;

+    dest.SetFromBstr(prop.bstrVal);

     return;

   }

   char temp[64];

   ConvertPropertyToShortString(temp, prop, propID, full);

-  int len = MyStringLen(temp);

-  wchar_t *str = dest.GetBuffer(len);

-  for (int i = 0; i < len; i++)

-    str[i] = temp[i];

-  dest.ReleaseBuffer(len);

+  dest.SetFromAscii(temp);

 }

 

-static inline char GetHex(Byte value)

+static inline unsigned GetHex(unsigned v)

 {

-  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+  return (v < 10) ? ('0' + v) : ('A' + (v - 10));

 }

 

 #ifndef _SFX

 

-static inline void AddHexToString(AString &res, Byte value)

+static inline void AddHexToString(AString &res, unsigned v)

 {

-  res += GetHex((Byte)(value >> 4));

-  res += GetHex((Byte)(value & 0xF));

+  res += (char)GetHex(v >> 4);

+  res += (char)GetHex(v & 0xF);

   res += ' ';

 }

 

@@ -175,30 +194,30 @@
 }

 */

 

-static const char *sidNames[] =

+static const char * const sidNames[] =

 {

-  "0",

-  "Dialup",

-  "Network",

-  "Batch",

-  "Interactive",

-  "Logon",  // S-1-5-5-X-Y

-  "Service",

-  "Anonymous",

-  "Proxy",

-  "EnterpriseDC",

-  "Self",

-  "AuthenticatedUsers",

-  "RestrictedCode",

-  "TerminalServer",

-  "RemoteInteractiveLogon",

-  "ThisOrganization",

-  "16",

-  "IUserIIS",

-  "LocalSystem",

-  "LocalService",

-  "NetworkService",

-  "Domains"

+    "0"

+  , "Dialup"

+  , "Network"

+  , "Batch"

+  , "Interactive"

+  , "Logon"  // S-1-5-5-X-Y

+  , "Service"

+  , "Anonymous"

+  , "Proxy"

+  , "EnterpriseDC"

+  , "Self"

+  , "AuthenticatedUsers"

+  , "RestrictedCode"

+  , "TerminalServer"

+  , "RemoteInteractiveLogon"

+  , "ThisOrganization"

+  , "16"

+  , "IUserIIS"

+  , "LocalSystem"

+  , "LocalService"

+  , "NetworkService"

+  , "Domains"

 };

 

 struct CSecID2Name

@@ -207,7 +226,7 @@
   const char *sz;

 };

 

-const CSecID2Name sid_32_Names[] =

+static const CSecID2Name sid_32_Names[] =

 {

   { 544, "Administrators" },

   { 545, "Users" },

@@ -297,7 +316,7 @@
     if (v0 == 32 && num == 2)

     {

       UInt32 v1 = Get32(p + 12);

-      for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++)

+      for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++)

         if (sid_32_Names[i].n == v1)

         {

           s += sid_32_Names[i].sz;

@@ -307,7 +326,7 @@
     if (v0 == 21 && num == 5)

     {

       UInt32 v4 = Get32(p + 8 + 4 * 4);

-      for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++)

+      for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++)

         if (sid_21_Names[i].n == v4)

         {

           s += sid_21_Names[i].sz;

@@ -316,7 +335,7 @@
     }

     if (v0 == 80 && num == 6)

     {

-      for (int i = 0; i < ARRAY_SIZE(services_to_name); i++)

+      for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++)

       {

         const CServicesToName &sn = services_to_name[i];

         int j;

@@ -385,10 +404,11 @@
     return;

   if (Get16(p) != 2) // revision

     return;

-  // UInt32 aclSize = Get16(p + 2);

   UInt32 num = Get32(p + 4);

   AddUInt32ToString(s, num);

+  

   /*

+  UInt32 aclSize = Get16(p + 2);

   if (num >= (1 << 16))

     return;

   if (aclSize > size)

@@ -409,14 +429,15 @@
 

     UInt32 sidSize = 0;

     s += ' ';

-    s += ParseSid(p, size, sidSize);

+    ParseSid(s, p, size, sidSize);

     if (sidSize == 0)

       return;

     p += sidSize;

     size -= sidSize;

   }

-  if (size != 0)

-    s += " ERROR";

+

+  // the tail can contain zeros. So (size != 0) is not ERROR

+  // if (size != 0) s += " ERROR";

   */

 }

 

@@ -461,7 +482,7 @@
 

 #ifdef _WIN32

 

-static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)

+static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()

 {

   if (pos >= size)

     return false;

@@ -475,7 +496,7 @@
   return (8 + num * 4 <= size);

 }

 

-static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)

+static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw()

 {

   UInt32 control = Get16(p + 2);

   if ((flags & control) == 0)

@@ -491,7 +512,7 @@
   return (aclSize <= size);

 }

 

-bool CheckNtSecure(const Byte *data, UInt32 size)

+bool CheckNtSecure(const Byte *data, UInt32 size) throw()

 {

   if (size < 20)

     return false;

@@ -515,11 +536,11 @@
   if (attr.Parse(data, size))

   {

     if (!attr.IsSymLink())

-      s += L"Junction: ";

+      s.AddAscii("Junction: ");

     s += attr.GetPath();

     if (!attr.IsOkNamePair())

     {

-      s += L" : ";

+      s.AddAscii(" : ");

       s += attr.PrintName;

     }

     return true;

@@ -536,16 +557,16 @@
 

   char hex[16];

   ConvertUInt32ToHex8Digits(tag, hex);

-  s.AddAsciiStr(hex);

-  s += L' ';

+  s.AddAscii(hex);

+  s.Add_Space();

 

   data += 8;

 

   for (UInt32 i = 0; i < len; i++)

   {

-    Byte b = ((const Byte *)data)[i];

-    s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF));

-    s += (wchar_t)GetHex((Byte)(b & 0xF));

+    unsigned b = ((const Byte *)data)[i];

+    s += (wchar_t)GetHex((b >> 4) & 0xF);

+    s += (wchar_t)GetHex(b & 0xF);

   }

   return true;

 }

diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
index fcfbc8c..fef4b7d 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -11,7 +11,8 @@
 

 bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s);

 void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s);

-bool CheckNtSecure(const Byte *data, UInt32 size);

-void ConvertWinAttribToString(char *s, UInt32 wa);

+bool CheckNtSecure(const Byte *data, UInt32 size) throw();;

+

+void ConvertWinAttribToString(char *s, UInt32 wa) throw();

 

 #endif

diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
index 4510ffd..f73ece8 100644
--- a/CPP/7zip/UI/Common/SortUtils.cpp
+++ b/CPP/7zip/UI/Common/SortUtils.cpp
@@ -14,8 +14,10 @@
 

 void SortFileNames(const UStringVector &strings, CUIntVector &indices)

 {

-  unsigned numItems = strings.Size();

+  const unsigned numItems = strings.Size();

   indices.ClearAndSetSize(numItems);

+  if (numItems == 0)

+    return;

   unsigned *vals = &indices[0];

   for (unsigned i = 0; i < numItems; i++)

     vals[i] = i;

diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp
index cfbee1a..56bba9a 100644
--- a/CPP/7zip/UI/Common/TempFiles.cpp
+++ b/CPP/7zip/UI/Common/TempFiles.cpp
@@ -17,5 +17,3 @@
     Paths.DeleteBack();

   }

 }

-

-

diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index ee13311..57723e4 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -42,6 +42,19 @@
 static CFSTR kTempFolderPrefix = FTEXT("7zE");

 

 

+void CUpdateErrorInfo::SetFromLastError(const char *message)

+{

+  SystemError = ::GetLastError();

+  Message = message;

+}

+

+HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName)

+{

+  SetFromLastError(message);

+  FileNames.Add(fileName);

+  return Get_HRESULT_Error();

+}

+

 static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)

 {

   NFind::CFileInfo fileInfo;

@@ -101,6 +114,8 @@
   bool SetMTime(const FILETIME *mTime);

   HRESULT Close();

 

+  UInt64 GetSize() const { return _length; }

+

   MY_UNKNOWN_IMP1(IOutStream)

 

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

@@ -151,10 +166,10 @@
 

       FChar temp[16];

       ConvertUInt32ToString(_streamIndex + 1, temp);

-      FString res = temp;

-      while (res.Len() < 3)

-        res = FString(FTEXT('0')) + res;

-      FString name = Prefix + res;

+      FString name = temp;

+      while (name.Len() < 3)

+        name.InsertAtFront(FTEXT('0'));

+      name.Insert(0, Prefix);

       altStream.StreamSpec = new COutFileStream;

       altStream.Stream = altStream.StreamSpec;

       if (!altStream.StreamSpec->Create(name, false))

@@ -236,8 +251,6 @@
 

 STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)

 {

-  if (newSize < 0)

-    return E_INVALIDARG;

   unsigned i = 0;

   while (i < Streams.Size())

   {

@@ -279,7 +292,7 @@
     return;

   }

   

-  int dotPos = Name.ReverseFind(L'.');

+  int dotPos = Name.ReverseFind_Dot();

   if (dotPos < 0)

     return;

   if ((unsigned)dotPos == Name.Len() - 1)

@@ -289,7 +302,7 @@
     return;

   }

   const UString ext = Name.Ptr(dotPos + 1);

-  if (BaseExtension.IsEqualToNoCase(ext))

+  if (BaseExtension.IsEqualTo_NoCase(ext))

   {

     BaseExtension = ext;

     Name.DeleteFrom(dotPos);

@@ -302,7 +315,10 @@
 {

   UString path = GetPathWithoutExt();

   if (!BaseExtension.IsEmpty())

-    path += UString(L'.') + BaseExtension;

+  {

+    path += L'.';

+    path += BaseExtension;

+  }

   return path;

 }

 

@@ -310,27 +326,34 @@
 {

   UString path = GetPathWithoutExt();

   if (!BaseExtension.IsEmpty())

-    path += UString(L'.') + VolExtension;

+  {

+    path += L'.';

+    path += VolExtension;

+  }

   return path;

 }

 

 FString CArchivePath::GetTempPath() const

 {

-  FString path = TempPrefix + us2fs(Name);

+  FString path = TempPrefix;

+  path += us2fs(Name);

   if (!BaseExtension.IsEmpty())

-    path += FString(FTEXT('.')) + us2fs(BaseExtension);

-  path += FTEXT(".tmp");

+  {

+    path += FTEXT('.');

+    path += us2fs(BaseExtension);

+  }

+  path.AddAscii(".tmp");

   path += TempPostfix;

   return path;

 }

 

 static const wchar_t *kDefaultArcType = L"7z";

 static const wchar_t *kDefaultArcExt = L"7z";

-static const wchar_t *kSFXExtension =

+static const char *kSFXExtension =

   #ifdef _WIN32

-    L"exe";

+    "exe";

   #else

-    L"";

+    "";

   #endif

 

 bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,

@@ -375,7 +398,7 @@
   }

   UString ext = typeExt;

   if (SfxMode)

-    ext = kSFXExtension;

+    ext.SetFromAscii(kSFXExtension);

   ArchivePath.BaseExtension = ext;

   ArchivePath.VolExtension = typeExt;

   ArchivePath.ParseFromPath(arcPath, ArcNameMode);

@@ -389,7 +412,6 @@
   return true;

 }

 

-/*

 struct CUpdateProduceCallbackImp: public IUpdateProduceCallback

 {

   const CObjectVector<CArcItem> *_arcItems;

@@ -397,14 +419,14 @@
   

   CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,

       IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}

-  virtual HRESULT ShowDeleteFile(int arcIndex);

+  virtual HRESULT ShowDeleteFile(unsigned arcIndex);

 };

 

-HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)

+HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)

 {

-  return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);

+  const CArcItem &ai = (*_arcItems)[arcIndex];

+  return _callback->ShowDeleteFile(ai.Name, ai.IsDir);

 }

-*/

 

 bool CRenamePair::Prepare()

 {

@@ -417,9 +439,9 @@
 

 extern bool g_CaseSensitive;

 

-static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)

+static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2)

 {

-  for (int i = 0;; i++)

+  for (unsigned i = 0;; i++)

   {

     wchar_t c1 = s1[i];

     wchar_t c2 = s2[i];

@@ -429,7 +451,7 @@
       continue;

     if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))

       continue;

-    if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2))

+    if (IsPathSepar(c1) && IsPathSepar(c2))

       continue;

     return i;

   }

@@ -437,10 +459,10 @@
 

 bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const

 {

-  int num = CompareTwoNames(OldName, src);

+  unsigned num = CompareTwoNames(OldName, src);

   if (OldName[num] == 0)

   {

-    if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1]))

+    if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1]))

       return false;

   }

   else

@@ -449,28 +471,23 @@
     // OldName = "1\1a.txt"

     // src = "1"

 

-    if (!isFolder ||

-        src[num] != 0 ||

-        !IsCharDirLimiter(OldName[num]) ||

-        OldName[num + 1] != 0)

+    if (!isFolder

+        || src[num] != 0

+        || !IsPathSepar(OldName[num])

+        || OldName[num + 1] != 0)

       return false;

   }

   dest = NewName + src.Ptr(num);

   return true;

 }

 

-static int GetReverseSlashPos(const UString &name)

-{

-  int slashPos = name.ReverseFind(L'/');

-  #ifdef _WIN32

-  int slash1Pos = name.ReverseFind(L'\\');

-  slashPos = MyMax(slashPos, slash1Pos);

-  #endif

-  return slashPos;

-}

+#ifdef SUPPORT_ALT_STREAMS

+int FindAltStreamColon_in_Path(const wchar_t *path);

+#endif

 

 static HRESULT Compress(

     const CUpdateOptions &options,

+    bool isUpdatingItself,

     CCodecs *codecs,

     const CActionSet &actionSet,

     const CArc *arc,

@@ -481,10 +498,12 @@
     const CDirItem *parentDirItem,

     CTempFiles &tempFiles,

     CUpdateErrorInfo &errorInfo,

-    IUpdateCallbackUI *callback)

+    IUpdateCallbackUI *callback,

+    CFinishArchiveStat &st)

 {

   CMyComPtr<IOutArchive> outArchive;

   int formatIndex = options.MethodMode.Type.FormatIndex;

+  

   if (arc)

   {

     formatIndex = arc->FormatIndex;

@@ -510,22 +529,25 @@
     }

     #endif

   }

+  

   if (outArchive == 0)

     throw kUpdateIsNotSupoorted;

   

   NFileTimeType::EEnum fileTimeType;

-  UInt32 value;

-  RINOK(outArchive->GetFileTimeType(&value));

-

-  switch (value)

   {

-    case NFileTimeType::kWindows:

-    case NFileTimeType::kUnix:

-    case NFileTimeType::kDOS:

-      fileTimeType = (NFileTimeType::EEnum)value;

-      break;

-    default:

-      return E_FAIL;

+    UInt32 value;

+    RINOK(outArchive->GetFileTimeType(&value));

+    

+    switch (value)

+    {

+      case NFileTimeType::kWindows:

+      case NFileTimeType::kUnix:

+      case NFileTimeType::kDOS:

+        fileTimeType = (NFileTimeType::EEnum)value;

+        break;

+      default:

+        return E_FAIL;

+    }

   }

 

   {

@@ -547,6 +569,7 @@
       const CArcItem &ai = arcItems[i];

       bool needRename = false;

       UString dest;

+      

       if (ai.Censored)

       {

         FOR_VECTOR (j, options.RenamePairs)

@@ -557,11 +580,12 @@
             needRename = true;

             break;

           }

+          

+          #ifdef SUPPORT_ALT_STREAMS

           if (ai.IsAltStream)

           {

-            int colonPos = ai.Name.ReverseFind(':');

-            int slashPosPos = GetReverseSlashPos(ai.Name);

-            if (colonPos > slashPosPos)

+            int colonPos = FindAltStreamColon_in_Path(ai.Name);

+            if (colonPos >= 0)

             {

               UString mainName = ai.Name.Left(colonPos);

               /*

@@ -571,14 +595,16 @@
               if (rp.GetNewPath(false, mainName, dest))

               {

                 needRename = true;

-                dest += ':';

+                dest += L':';

                 dest += ai.Name.Ptr(colonPos + 1);

                 break;

               }

             }

           }

+          #endif

         }

       }

+      

       CUpdatePair2 up2;

       up2.SetAs_NoChangeArcItem(ai.IndexInServer);

       if (needRename)

@@ -594,16 +620,18 @@
   {

     CRecordVector<CUpdatePair> updatePairs;

     GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!

-    // CUpdateProduceCallbackImp upCallback(&arcItems, callback);

-    UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);

+    CUpdateProduceCallbackImp upCallback(&arcItems, callback);

+    

+    UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);

   }

 

-  UInt32 numFiles = 0;

-  FOR_VECTOR (i, updatePairs2)

-    if (updatePairs2[i].NewData)

-      numFiles++;

-  

-  RINOK(callback->SetNumFiles(numFiles));

+  {

+    UInt32 numItems = 0;

+    FOR_VECTOR (i, updatePairs2)

+      if (updatePairs2[i].NewData)

+        numItems++;

+    RINOK(callback->SetNumItems(numItems));

+  }

   

   CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;

   CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);

@@ -616,8 +644,6 @@
   {

     // we set Archive to allow to transfer GetProperty requests back to DLL.

     updateCallbackSpec->Archive = arc->Archive;

-    updateCallbackSpec->GetRawProps = arc->GetRawProps;

-    updateCallbackSpec->GetRootProps = arc->GetRootProps;

   }

   

   updateCallbackSpec->DirItems = &dirItems;

@@ -627,6 +653,7 @@
   updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;

   updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;

 

+  updateCallbackSpec->Arc = arc;

   updateCallbackSpec->ArcItems = &arcItems;

   updateCallbackSpec->UpdatePairs = &updatePairs2;

 

@@ -647,12 +674,16 @@
   }

 

   COutFileStream *outStreamSpec = NULL;

+  CStdOutFileStream *stdOutFileStreamSpec = NULL;

   COutMultiVolStream *volStreamSpec = NULL;

 

   if (options.VolumesSizes.Size() == 0)

   {

     if (options.StdOutMode)

-      outStream = new CStdOutFileStream;

+    {

+      stdOutFileStreamSpec = new CStdOutFileStream;

+      outStream = stdOutFileStreamSpec;

+    }

     else

     {

       outStreamSpec = new COutFileStream;

@@ -660,7 +691,8 @@
       outStream = outSeekStream;

       bool isOK = false;

       FString realPath;

-      for (int i = 0; i < (1 << 16); i++)

+      

+      for (unsigned i = 0; i < (1 << 16); i++)

       {

         if (archivePath.Temp)

         {

@@ -685,13 +717,9 @@
         if (!archivePath.Temp)

           break;

       }

+      

       if (!isOK)

-      {

-        errorInfo.SystemError = ::GetLastError();

-        errorInfo.FileName = realPath;

-        errorInfo.Message = L"7-Zip cannot open file";

-        return E_FAIL;

-      }

+        return errorInfo.SetFromLastError("cannot open file", realPath);

     }

   }

   else

@@ -705,7 +733,8 @@
     outSeekStream = volStreamSpec;

     outStream = outSeekStream;

     volStreamSpec->Sizes = options.VolumesSizes;

-    volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L".");

+    volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());

+    volStreamSpec->Prefix += FTEXT('.');

     volStreamSpec->TempFiles = &tempFiles;

     volStreamSpec->Init();

 

@@ -724,34 +753,32 @@
     CInFileStream *sfxStreamSpec = new CInFileStream;

     CMyComPtr<IInStream> sfxStream(sfxStreamSpec);

     if (!sfxStreamSpec->Open(options.SfxModule))

-    {

-      errorInfo.SystemError = ::GetLastError();

-      errorInfo.Message = L"7-Zip cannot open SFX module";

-      errorInfo.FileName = options.SfxModule;

-      return E_FAIL;

-    }

+      return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule);

 

     CMyComPtr<ISequentialOutStream> sfxOutStream;

-    COutFileStream *outStreamSpec = NULL;

+    COutFileStream *outStreamSpec2 = NULL;

     if (options.VolumesSizes.Size() == 0)

       sfxOutStream = outStream;

     else

     {

-      outStreamSpec = new COutFileStream;

-      sfxOutStream = outStreamSpec;

+      outStreamSpec2 = new COutFileStream;

+      sfxOutStream = outStreamSpec2;

       FString realPath = us2fs(archivePath.GetFinalPath());

-      if (!outStreamSpec->Create(realPath, false))

-      {

-        errorInfo.SystemError = ::GetLastError();

-        errorInfo.FileName = realPath;

-        errorInfo.Message = L"7-Zip cannot open file";

-        return E_FAIL;

-      }

+      if (!outStreamSpec2->Create(realPath, false))

+        return errorInfo.SetFromLastError("cannot open file", realPath);

     }

-    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));

-    if (outStreamSpec)

+

     {

-      RINOK(outStreamSpec->Close());

+      UInt64 sfxSize;

+      RINOK(sfxStreamSpec->GetSize(&sfxSize));

+      RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize));

+    }

+

+    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));

+    

+    if (outStreamSpec2)

+    {

+      RINOK(outStreamSpec2->Close());

     }

   }

 

@@ -778,9 +805,15 @@
 

 

   HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);

-  callback->Finilize();

+  // callback->Finalize();

   RINOK(result);

 

+  if (!updateCallbackSpec->AreAllFilesClosed())

+  {

+    errorInfo.Message = "There are unclosed input file:";

+    errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths;

+    return E_FAIL;

+  }

 

   if (options.SetArcMTime)

   {

@@ -810,6 +843,19 @@
     }

   }

 

+  if (callback)

+  {

+    UInt64 size = 0;

+    if (outStreamSpec)

+      outStreamSpec->GetSize(&size);

+    else if (stdOutFileStreamSpec)

+      size = stdOutFileStreamSpec->GetSize();

+    else

+      size = volStreamSpec->GetSize();

+

+    st.OutArcFileSize = size;

+  }

+

   if (outStreamSpec)

     result = outStreamSpec->Close();

   else if (volStreamSpec)

@@ -817,6 +863,24 @@
   return result;

 }

 

+bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);

+

+static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)

+{

+  bool finded = false;

+  FOR_VECTOR (i, censor.Pairs)

+  {

+    bool include;

+    if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include))

+    {

+      if (!include)

+        return false;

+      finded = true;

+    }

+  }

+  return finded;

+}

+

 static HRESULT EnumerateInArchiveItems(

     // bool storeStreamsMode,

     const NWildcard::CCensor &censor,

@@ -828,18 +892,29 @@
   IInArchive *archive = arc.Archive;

   RINOK(archive->GetNumberOfItems(&numItems));

   arcItems.ClearAndReserve(numItems);

+

+  CReadArcItem item;

+

   for (UInt32 i = 0; i < numItems; i++)

   {

     CArcItem ai;

 

-    RINOK(arc.GetItemPath(i, ai.Name));

-    RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir));

-    RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream));

+    RINOK(arc.GetItem(i, item));

+    ai.Name = item.Path;

+    ai.IsDir = item.IsDir;

+    ai.IsAltStream =

+        #ifdef SUPPORT_ALT_STREAMS

+          item.IsAltStream;

+        #else

+          false;

+        #endif

+

     /*

     if (!storeStreamsMode && ai.IsAltStream)

       continue;

     */

-    ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir);

+    ai.Censored = Censor_CheckPath(censor, item);

+

     RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));

     RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));

 

@@ -867,15 +942,6 @@
   return S_OK;

 }

 

-struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback

-{

-  IUpdateCallbackUI2 *Callback;

-  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)

-  {

-    return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);

-  }

-};

-

 #if defined(_WIN32) && !defined(UNDER_CE)

 

 #include <mapi.h>

@@ -884,8 +950,8 @@
 

 struct CRefSortPair

 {

-  int Len;

-  int Index;

+  unsigned Len;

+  unsigned Index;

 };

 

 #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

@@ -896,18 +962,14 @@
   return MyCompare(a1->Index, a2->Index);

 }

 

-static int GetNumSlashes(const FChar *s)

+static unsigned GetNumSlashes(const FChar *s)

 {

-  for (int numSlashes = 0;;)

+  for (unsigned numSlashes = 0;;)

   {

     FChar c = *s++;

     if (c == 0)

       return numSlashes;

-    if (

-        #ifdef _WIN32

-        c == FTEXT('\\') ||

-        #endif

-        c == FTEXT('/'))

+    if (IS_PATH_SEPAR(c))

       numSlashes++;

   }

 }

@@ -963,12 +1025,11 @@
   if (options.SfxMode)

   {

     CProperty property;

-    property.Name = L"rsfx";

-    property.Value = L"on";

+    property.Name.SetFromAscii("rsfx");

     options.MethodMode.Properties.Add(property);

     if (options.SfxModule.IsEmpty())

     {

-      errorInfo.Message = L"SFX file is not specified";

+      errorInfo.Message = "SFX file is not specified";

       return E_FAIL;

     }

     bool found = false;

@@ -984,12 +1045,7 @@
     if (!found)

     {

       if (!NFind::DoesFileExist(options.SfxModule))

-      {

-        errorInfo.SystemError = ::GetLastError();

-        errorInfo.Message = L"7-Zip cannot find specified SFX module";

-        errorInfo.FileName = options.SfxModule;

-        return E_FAIL;

-      }

+        return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);

     }

   }

 

@@ -1002,7 +1058,7 @@
         !options.SetArcPath(codecs, cmdArcPath2))

       return E_NOTIMPL;

   }

-  UString arcPath = options.ArchivePath.GetFinalPath();

+  const UString arcPath = options.ArchivePath.GetFinalPath();

 

   if (cmdArcPath2.IsEmpty())

   {

@@ -1030,10 +1086,10 @@
         return E_NOTIMPL;

       if (options.VolumesSizes.Size() > 0)

         return E_NOTIMPL;

-      CObjectVector<COpenType> types;

+      CObjectVector<COpenType> types2;

       // change it.

       if (options.MethodMode.Type_Defined)

-        types.Add(options.MethodMode.Type);

+        types2.Add(options.MethodMode.Type);

       // We need to set Properties to open archive only in some cases (WIM archives).

 

       CIntVector excl;

@@ -1042,30 +1098,31 @@
       op.props = &options.MethodMode.Properties;

       #endif

       op.codecs = codecs;

-      op.types = &types;

+      op.types = &types2;

       op.excludedFormats = &excl;

       op.stdInMode = false;

       op.stream = NULL;

       op.filePath = arcPath;

 

-      HRESULT result = arcLink.Open2(op, openCallback);

+      RINOK(callback->StartOpenArchive(arcPath));

+

+      HRESULT result = arcLink.Open_Strict(op, openCallback);

 

       if (result == E_ABORT)

         return result;

       

-      const wchar_t *errorArcType = NULL;

-      if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0)

-        errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;

-      RINOK(callback->OpenResult(arcPath, result, errorArcType));

+      HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result);

       /*

       if (result == S_FALSE)

         return E_FAIL;

       */

+      RINOK(res2);

       RINOK(result);

+

       if (arcLink.VolumePaths.Size() > 1)

       {

         errorInfo.SystemError = (DWORD)E_NOTIMPL;

-        errorInfo.Message = L"Updating for multivolume archives is not implemented";

+        errorInfo.Message = "Updating for multivolume archives is not implemented";

         return E_NOTIMPL;

       }

       

@@ -1076,7 +1133,7 @@
       if (arc.ErrorInfo.ThereIsTail)

       {

         errorInfo.SystemError = (DWORD)E_NOTIMPL;

-        errorInfo.Message = L"There is some data block after the end of the archive";

+        errorInfo.Message = "There is some data block after the end of the archive";

         return E_NOTIMPL;

       }

       if (options.MethodMode.Type.FormatIndex < 0)

@@ -1098,8 +1155,10 @@
   bool thereIsInArchive = arcLink.IsOpen;

   if (!thereIsInArchive && renameMode)

     return E_FAIL;

-

+  

   CDirItems dirItems;

+  dirItems.Callback = callback;

+

   CDirItem parentDirItem;

   CDirItem *parentDirItem_Ptr = NULL;

   

@@ -1123,14 +1182,14 @@
   else

   {

     bool needScanning = false;

+    

     if (!renameMode)

     FOR_VECTOR (i, options.Commands)

       if (options.Commands[i].ActionSet.NeedScanning())

         needScanning = true;

+

     if (needScanning)

     {

-      CEnumDirItemUpdateCallback enumCallback;

-      enumCallback.Callback = callback;

       RINOK(callback->StartScanning());

 

       dirItems.SymLinks = options.SymLinks.Val;

@@ -1140,26 +1199,26 @@
       #endif

 

       dirItems.ScanAltStreams = options.AltStreams.Val;

+

       HRESULT res = EnumerateItems(censor,

           options.PathMode,

           options.AddPathPrefix,

-          dirItems, &enumCallback);

-      FOR_VECTOR (i, dirItems.ErrorPaths)

-      {

-        RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));

-      }

+          dirItems);

+

       if (res != S_OK)

       {

         if (res != E_ABORT)

-          errorInfo.Message = L"Scanning error";

+          errorInfo.Message = "Scanning error";

         return res;

       }

-      RINOK(callback->FinishScanning());

+      

+      RINOK(callback->FinishScanning(dirItems.Stat));

 

       if (censor.Pairs.Size() == 1)

       {

         NFind::CFileInfo fi;

-        FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT(".");

+        FString prefix = us2fs(censor.Pairs[0].Prefix);

+        prefix += FTEXT('.');

         // UString prefix = censor.Pairs[0].Prefix;

         /*

         if (prefix.Back() == WCHAR_PATH_SEPARATOR)

@@ -1225,10 +1284,11 @@
     }

   }

 

-  unsigned i;

-  for (i = 0; i < options.Commands.Size(); i++)

+  unsigned ci;

+

+  for (ci = 0; ci < options.Commands.Size(); ci++)

   {

-    CArchivePath &ap = options.Commands[i].ArchivePath;

+    CArchivePath &ap = options.Commands[ci].ArchivePath;

     if (usesTempDir)

     {

       // Check it

@@ -1237,15 +1297,15 @@
       // ap.TempPrefix = tempDirPrefix;

     }

     if (!options.StdOutMode &&

-        (i > 0 || !createTempFile))

+        (ci > 0 || !createTempFile))

     {

       const FString path = us2fs(ap.GetFinalPath());

       if (NFind::DoesFileOrDirExist(path))

       {

-        errorInfo.SystemError = 0;

-        errorInfo.Message = L"The file already exists";

-        errorInfo.FileName = path;

-        return E_FAIL;

+        errorInfo.SystemError = ERROR_FILE_EXISTS;

+        errorInfo.Message = "The file already exists";

+        errorInfo.FileNames.Add(path);

+        return errorInfo.Get_HRESULT_Error();

       }

     }

   }

@@ -1270,31 +1330,44 @@
   {

     unsigned num = dirItems.Items.Size();

     processedItems.Alloc(num);

-    for (i = 0; i < num; i++)

+    for (unsigned i = 0; i < num; i++)

       processedItems[i] = 0;

   }

 

-  for (i = 0; i < options.Commands.Size(); i++)

+  /*

+  #ifndef _NO_CRYPTO

+  if (arcLink.PasswordWasAsked)

   {

-    const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0;

-    // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0;

-    // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0;

-    CUpdateArchiveCommand &command = options.Commands[i];

+    // We set password, if open have requested password

+    RINOK(callback->SetPassword(arcLink.Password));

+  }

+  #endif

+  */

+

+  for (ci = 0; ci < options.Commands.Size(); ci++)

+  {

+    const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL;

+    CUpdateArchiveCommand &command = options.Commands[ci];

     UString name;

     bool isUpdating;

+    

     if (options.StdOutMode)

     {

-      name = L"stdout";

-      isUpdating = arc != 0;

+      name.SetFromAscii("stdout");

+      isUpdating = thereIsInArchive;

     }

     else

     {

       name = command.ArchivePath.GetFinalPath();

-      isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0);

+      isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive);

     }

+    

     RINOK(callback->StartArchive(name, isUpdating))

 

+    CFinishArchiveStat st;

+

     RINOK(Compress(options,

+        isUpdating,

         codecs,

         command.ActionSet,

         arc,

@@ -1306,9 +1379,9 @@
         parentDirItem_Ptr,

 

         tempFiles,

-        errorInfo, callback));

+        errorInfo, callback, st));

 

-    RINOK(callback->FinishArchive());

+    RINOK(callback->FinishArchive(st));

   }

 

 

@@ -1325,21 +1398,16 @@
     {

       CArchivePath &ap = options.Commands[0].ArchivePath;

       const FString &tempPath = ap.GetTempPath();

+      

       if (thereIsInArchive)

         if (!DeleteFileAlways(us2fs(arcPath)))

-        {

-          errorInfo.SystemError = ::GetLastError();

-          errorInfo.Message = L"7-Zip cannot delete the file";

-          errorInfo.FileName = us2fs(arcPath);

-          return E_FAIL;

-        }

+          return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));

+      

       if (!MyMoveFile(tempPath, us2fs(arcPath)))

       {

-        errorInfo.SystemError = ::GetLastError();

-        errorInfo.Message = L"7-Zip cannot move the file";

-        errorInfo.FileName = tempPath;

-        errorInfo.FileName2 = us2fs(arcPath);

-        return E_FAIL;

+        errorInfo.SetFromLastError("cannot move the file", tempPath);

+        errorInfo.FileNames.Add(us2fs(arcPath));

+        return errorInfo.Get_HRESULT_Error();

       }

     }

     catch(...)

@@ -1350,53 +1418,52 @@
 

 

   #if defined(_WIN32) && !defined(UNDER_CE)

+  

   if (options.EMailMode)

   {

     NDLL::CLibrary mapiLib;

     if (!mapiLib.Load(FTEXT("Mapi32.dll")))

     {

-      errorInfo.SystemError = ::GetLastError();

-      errorInfo.Message = L"7-Zip cannot load Mapi32.dll";

-      return E_FAIL;

+      errorInfo.SetFromLastError("cannot load Mapi32.dll");

+      return errorInfo.Get_HRESULT_Error();

     }

 

     /*

     LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");

     if (fnSend == 0)

     {

-      errorInfo.SystemError = ::GetLastError();

-      errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";

-      return E_FAIL;

+      errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function");

+      return errorInfo.Get_HRESULT_Error();

     }

     */

+    

     LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");

     if (sendMail == 0)

     {

-      errorInfo.SystemError = ::GetLastError();

-      errorInfo.Message = L"7-Zip cannot find MAPISendMail function";

-      return E_FAIL;

+      errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");

+      return errorInfo.Get_HRESULT_Error();;

     }

 

     FStringVector fullPaths;

     unsigned i;

+    

     for (i = 0; i < options.Commands.Size(); i++)

     {

       CArchivePath &ap = options.Commands[i].ArchivePath;

-      FString arcPath;

-      if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath))

-      {

-        errorInfo.SystemError = ::GetLastError();

-        errorInfo.Message = L"GetFullPathName error";

-        return E_FAIL;

-      }

-      fullPaths.Add(arcPath);

+      FString finalPath = us2fs(ap.GetFinalPath());

+      FString arcPath2;

+      if (!MyGetFullPathName(finalPath, arcPath2))

+        return errorInfo.SetFromLastError("GetFullPathName error", finalPath);

+      fullPaths.Add(arcPath2);

     }

+

     CCurrentDirRestorer curDirRestorer;

+    

     for (i = 0; i < fullPaths.Size(); i++)

     {

-      UString arcPath = fs2us(fullPaths[i]);

-      UString fileName = ExtractFileNameFromPath(arcPath);

-      AString path = GetAnsiString(arcPath);

+      UString arcPath2 = fs2us(fullPaths[i]);

+      UString fileName = ExtractFileNameFromPath(arcPath2);

+      AString path = GetAnsiString(arcPath2);

       AString name = GetAnsiString(fileName);

       // Warning!!! MAPISendDocuments function changes Current directory

       // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);

@@ -1426,16 +1493,20 @@
       sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);

     }

   }

+  

   #endif

 

   if (options.DeleteAfterCompressing)

   {

     CRecordVector<CRefSortPair> pairs;

     FStringVector foldersNames;

+

+    unsigned i;

+

     for (i = 0; i < dirItems.Items.Size(); i++)

     {

       const CDirItem &dirItem = dirItems.Items[i];

-      FString phyPath = us2fs(dirItems.GetPhyPath(i));

+      FString phyPath = dirItems.GetPhyPath(i);

       if (dirItem.IsDir())

       {

         CRefSortPair pair;

@@ -1447,6 +1518,7 @@
       {

         if (processedItems[i] != 0 || dirItem.Size == 0)

         {

+          RINOK(callback->DeletingAfterArchiving(phyPath, false));

           DeleteFileAlways(phyPath);

         }

         else

@@ -1454,7 +1526,7 @@
           // file was skipped

           /*

           errorInfo.SystemError = 0;

-          errorInfo.Message = L"file was not processed";

+          errorInfo.Message = "file was not processed";

           errorInfo.FileName = phyPath;

           return E_FAIL;

           */

@@ -1463,15 +1535,19 @@
     }

 

     pairs.Sort(CompareRefSortPair, NULL);

+    

     for (i = 0; i < pairs.Size(); i++)

     {

-      FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index));

+      FString phyPath = dirItems.GetPhyPath(pairs[i].Index);

       if (NFind::DoesDirExist(phyPath))

       {

-        // printf("delete %S\n", phyPath);

+        RINOK(callback->DeletingAfterArchiving(phyPath, true));

         RemoveDir(phyPath);

       }

     }

+

+    RINOK(callback->FinishDeletingAfterArchiving());

   }

+

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
index 2d1d131..4e3fb2a 100644
--- a/CPP/7zip/UI/Common/Update.h
+++ b/CPP/7zip/UI/Common/Update.h
@@ -12,6 +12,8 @@
 #include "UpdateAction.h"

 #include "UpdateCallback.h"

 

+#include "DirItem.h"

+

 enum EArcNameMode

 {

   k_ArcNameMode_Smart,

@@ -144,32 +146,40 @@
   CRecordVector<UInt64> VolumesSizes;

 };

 

-struct CErrorInfo

+struct CUpdateErrorInfo

 {

   DWORD SystemError;

-  FString FileName;

-  FString FileName2;

-  UString Message;

-  // UStringVector ErrorPaths;

-  // CRecordVector<DWORD> ErrorCodes;

-  CErrorInfo(): SystemError(0) {};

+  AString Message;

+  FStringVector FileNames;

+

+  bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); }

+  HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); }

+  void SetFromLastError(const char *message);

+  HRESULT SetFromLastError(const char *message, const FString &fileName);

+

+  CUpdateErrorInfo(): SystemError(0) {};

 };

 

-struct CUpdateErrorInfo: public CErrorInfo

+struct CFinishArchiveStat

 {

+  UInt64 OutArcFileSize;

+

+  CFinishArchiveStat(): OutArcFileSize(0) {}

 };

 

 #define INTERFACE_IUpdateCallbackUI2(x) \

   INTERFACE_IUpdateCallbackUI(x) \

-  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \

+  INTERFACE_IDirItemsCallback(x) \

+  virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \

   virtual HRESULT StartScanning() x; \

-  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \

-  virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \

-  virtual HRESULT FinishScanning() x; \

+  virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \

+  virtual HRESULT StartOpenArchive(const wchar_t *name) x; \

   virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \

-  virtual HRESULT FinishArchive() x; \

+  virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \

+  virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \

+  virtual HRESULT FinishDeletingAfterArchiving() x; \

 

-struct IUpdateCallbackUI2: public IUpdateCallbackUI

+struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback

 {

   INTERFACE_IUpdateCallbackUI2(=0)

 };

diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
index 6e10b7d..8d6002f 100644
--- a/CPP/7zip/UI/Common/UpdateAction.h
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -35,7 +35,7 @@
   {

     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 8aaddfa..ab36f82 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -2,6 +2,10 @@
 

 #include "StdAfx.h"

 

+#ifndef _7ZIP_ST

+#include "../../../Windows/Synchronization.h"

+#endif

+

 #include "../../../Common/ComTry.h"

 #include "../../../Common/IntToString.h"

 #include "../../../Common/StringConvert.h"

@@ -10,9 +14,7 @@
 #include "../../../Windows/FileDir.h"

 #include "../../../Windows/FileName.h"

 #include "../../../Windows/PropVariant.h"

-#include "../../../Windows/Synchronization.h"

 

-#include "../../Common/FileStreams.h"

 #include "../../Common/StreamObjects.h"

 

 #include "UpdateCallback.h"

@@ -25,25 +27,40 @@
 using namespace NWindows;

 using namespace NFile;

 

+#ifndef _7ZIP_ST

+static NSynchronization::CCriticalSection g_CriticalSection;

+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);

+#else

+#define MT_LOCK

+#endif

+

+

 #ifdef _USE_SECURITY_CODE

 bool InitLocalPrivileges();

 #endif

 

 CArchiveUpdateCallback::CArchiveUpdateCallback():

-  Callback(0),

-  ShareForWrite(false),

-  StdInMode(false),

-  DirItems(0),

-  ArcItems(0),

-  UpdatePairs(0),

-  NewNames(0),

-  KeepOriginalItemNames(false),

-  ProcessedItemsStatuses(NULL),

-  ParentDirItem(NULL),

-  StoreNtSecurity(false),

-  StoreHardLinks(false),

-  StoreSymLinks(false),

-  _hardIndex_From((UInt32)(Int32)-1)

+    _hardIndex_From((UInt32)(Int32)-1),

+    

+    Callback(NULL),

+  

+    DirItems(NULL),

+    ParentDirItem(NULL),

+    

+    Arc(NULL),

+    ArcItems(NULL),

+    UpdatePairs(NULL),

+    NewNames(NULL),

+    

+    ShareForWrite(false),

+    StdInMode(false),

+    

+    KeepOriginalItemNames(false),

+    StoreNtSecurity(false),

+    StoreHardLinks(false),

+    StoreSymLinks(false),

+    

+    ProcessedItemsStatuses(NULL)

 {

   #ifdef _USE_SECURITY_CODE

   _saclEnabled = InitLocalPrivileges();

@@ -74,7 +91,7 @@
 

 

 /*

-static const STATPROPSTG kProps[] =

+static const CStatProp kProps[] =

 {

   { NULL, kpidPath, VT_BSTR},

   { NULL, kpidIsDir, VT_BOOL},

@@ -175,8 +192,8 @@
       return S_OK;

     }

 

-    if (GetRootProps)

-      return GetRootProps->GetRootRawProp(propID, data, dataSize, propType);

+    if (Arc && Arc->GetRootProps)

+      return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);

   }

   #endif

   return S_OK;

@@ -198,13 +215,11 @@
       return S_OK;

 

     const CUpdatePair2 &up = (*UpdatePairs)[index];

-    if (up.UseArcProps && up.ExistInArchive() && GetRawProps)

-      return GetRawProps->GetRawProp(

+    if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)

+      return Arc->GetRawProps->GetRawProp(

           ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,

           propID, data, dataSize, propType);

-

     {

-      const CUpdatePair2 &up = (*UpdatePairs)[index];

       /*

       if (!up.NewData)

         return E_FAIL;

@@ -290,7 +305,7 @@
   for (k = i; k < partsTo.Size(); k++)

   {

     if (k != i)

-      s += WCHAR_PATH_SEPARATOR;

+      s.Add_PathSepar();

     s += partsTo[k];

   }

 

@@ -336,9 +351,9 @@
               prop = simpleName;

             else

             {

-              const UString phyPath = DirItems->GetPhyPath(up.DirIndex);

+              const FString phyPath = DirItems->GetPhyPath(up.DirIndex);

               FString fullPath;

-              if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath))

+              if (NDir::MyGetFullPathName(phyPath, fullPath))

               {

                 prop = GetRelativePath(simpleName, fs2us(fullPath));

               }

@@ -385,8 +400,7 @@
   {

     // we can generate new ShortName here;

   }

-  else if ((up.UseArcProps

-      || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))

+  else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))

       && up.ExistInArchive() && Archive)

     return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value);

   else if (up.ExistOnDisk())

@@ -396,7 +410,7 @@
     {

       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;

@@ -412,9 +426,11 @@
   COM_TRY_END

 }

 

+#ifndef _7ZIP_ST

 static NSynchronization::CCriticalSection CS;

+#endif

 

-STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)

+STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)

 {

   COM_TRY_BEGIN

   *inStream = NULL;

@@ -423,7 +439,7 @@
     return E_FAIL;

   

   RINOK(Callback->CheckBreak());

-  RINOK(Callback->Finilize());

+  // RINOK(Callback->Finalize());

 

   bool isDir = IsDir(up);

 

@@ -434,7 +450,7 @@
       name = (*ArcItems)[up.ArcIndex].Name;

     else if (up.DirIndex >= 0)

       name = DirItems->GetLogPath(up.DirIndex);

-    RINOK(Callback->GetStream(name, true));

+    RINOK(Callback->GetStream(name, isDir, true, mode));

     

     /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.

        so we return empty stream */

@@ -449,13 +465,17 @@
     return S_OK;

   }

   

-  RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));

+  RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode));

  

   if (isDir)

     return S_OK;

 

   if (StdInMode)

   {

+    if (mode != NUpdateNotifyOp::kAdd &&

+        mode != NUpdateNotifyOp::kUpdate)

+      return S_OK;

+

     CStdInFileStream *inStreamSpec = new CStdInFileStream;

     CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

     *inStream = inStreamLoc.Detach();

@@ -466,20 +486,24 @@
     CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

 

     inStreamSpec->SupportHardLinks = StoreHardLinks;

+    inStreamSpec->Callback = this;

+    inStreamSpec->CallbackRef = index;

 

-    const UString path = DirItems->GetPhyPath(up.DirIndex);

+    const FString path = DirItems->GetPhyPath(up.DirIndex);

+    _openFiles_Indexes.Add(index);

+    _openFiles_Paths.Add(path);

 

     #if defined(_WIN32) && !defined(UNDER_CE)

     if (DirItems->Items[up.DirIndex].AreReparseData())

     {

-      if (!inStreamSpec->File.OpenReparse(us2fs(path)))

+      if (!inStreamSpec->File.OpenReparse(path))

       {

         return Callback->OpenFileError(path, ::GetLastError());

       }

     }

     else

     #endif

-    if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite))

+    if (!inStreamSpec->OpenShared(path, ShareForWrite))

     {

       return Callback->OpenFileError(path, ::GetLastError());

     }

@@ -511,8 +535,10 @@
 

     if (ProcessedItemsStatuses)

     {

+      #ifndef _7ZIP_ST

       NSynchronization::CCriticalSectionLock lock(CS);

-      ProcessedItemsStatuses[up.DirIndex] = 1;

+      #endif

+      ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;

     }

     *inStream = inStreamLoc.Detach();

   }

@@ -521,10 +547,133 @@
   COM_TRY_END

 }

 

-STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)

+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes)

 {

   COM_TRY_BEGIN

-  return Callback->SetOperationResult(operationResult);

+  return Callback->SetOperationResult(opRes);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)

+{

+  COM_TRY_BEGIN

+  return GetStream2(index, inStream,

+      (*UpdatePairs)[index].ArcIndex < 0 ?

+          NUpdateNotifyOp::kAdd :

+          NUpdateNotifyOp::kUpdate);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)

+{

+  COM_TRY_BEGIN

+

+  bool isDir = false;

+

+  if (indexType == NArchive::NEventIndexType::kOutArcIndex)

+  {

+    UString name;

+    if (index != (UInt32)(Int32)-1)

+    {

+      const CUpdatePair2 &up = (*UpdatePairs)[index];

+      if (up.ExistOnDisk())

+      {

+        name = DirItems->GetLogPath(up.DirIndex);

+        isDir = DirItems->Items[up.DirIndex].IsDir();

+      }

+    }

+    return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);

+  }

+  

+  wchar_t temp[16];

+  UString s2;

+  const wchar_t *s = NULL;

+  

+  if (indexType == NArchive::NEventIndexType::kInArcIndex)

+  {

+    if (index != (UInt32)(Int32)-1)

+    {

+      if (ArcItems)

+      {

+        const CArcItem &ai = (*ArcItems)[index];

+        s = ai.Name;

+        isDir = ai.IsDir;

+      }

+      else if (Arc)

+      {

+        RINOK(Arc->GetItemPath(index, s2));

+        s = s2;

+        RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));

+      }

+    }

+  }

+  else if (indexType == NArchive::NEventIndexType::kBlockIndex)

+  {

+    temp[0] = '#';

+    ConvertUInt32ToString(index, temp + 1);

+    s = temp;

+  }

+

+  if (!s)

+    s = L"";

+

+  return Callback->ReportUpdateOpeartion(op, s, isDir);

+

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)

+{

+  COM_TRY_BEGIN

+

+  bool isEncrypted = false;

+  wchar_t temp[16];

+  UString s2;

+  const wchar_t *s = NULL;

+  

+  if (indexType == NArchive::NEventIndexType::kOutArcIndex)

+  {

+    /*

+    UString name;

+    if (index != (UInt32)(Int32)-1)

+    {

+      const CUpdatePair2 &up = (*UpdatePairs)[index];

+      if (up.ExistOnDisk())

+      {

+        s2 = DirItems->GetLogPath(up.DirIndex);

+        s = s2;

+      }

+    }

+    */

+    return E_FAIL;

+  }

+ 

+  if (indexType == NArchive::NEventIndexType::kInArcIndex)

+  {

+    if (index != (UInt32)(Int32)-1)

+    {

+      if (ArcItems)

+        s = (*ArcItems)[index].Name;

+      else if (Arc)

+      {

+        RINOK(Arc->GetItemPath(index, s2));

+        s = s2;

+      }

+      if (Archive)

+      {

+        RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted));

+      }

+    }

+  }

+  else if (indexType == NArchive::NEventIndexType::kBlockIndex)

+  {

+    temp[0] = '#';

+    ConvertUInt32ToString(index, temp + 1);

+    s = temp;

+  }

+

+  return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s);

+

   COM_TRY_END

 }

 

@@ -547,7 +696,7 @@
   while (res.Len() < 2)

     res.InsertAtFront(FTEXT('0'));

   FString fileName = VolName;

-  fileName += L'.';

+  fileName += FTEXT('.');

   fileName += res;

   fileName += VolExt;

   COutFileStream *streamSpec = new COutFileStream;

@@ -572,3 +721,37 @@
   return Callback->CryptoGetTextPassword(password);

   COM_TRY_END

 }

+

+HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)

+{

+  if (error == ERROR_LOCK_VIOLATION)

+  {

+    MT_LOCK

+    UInt32 index = (UInt32)val;

+    FOR_VECTOR(i, _openFiles_Indexes)

+    {

+      if (_openFiles_Indexes[i] == index)

+      {

+        RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error));

+        break;

+      }

+    }

+  }

+  return HRESULT_FROM_WIN32(error);

+}

+

+void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)

+{

+  MT_LOCK

+  UInt32 index = (UInt32)val;

+  FOR_VECTOR(i, _openFiles_Indexes)

+  {

+    if (_openFiles_Indexes[i] == index)

+    {

+      _openFiles_Indexes.Delete(i);

+      _openFiles_Paths.Delete(i);

+      return;

+    }

+  }

+  throw 20141125;

+}

diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
index 41544db..81f5ed6 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -5,26 +5,35 @@
 

 #include "../../../Common/MyCom.h"

 

+#include "../../Common/FileStreams.h"

+

 #include "../../IPassword.h"

 #include "../../ICoder.h"

 

 #include "../Common/UpdatePair.h"

 #include "../Common/UpdateProduce.h"

 

+#include "OpenArchive.h"

+

 #define INTERFACE_IUpdateCallbackUI(x) \

+  virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \

   virtual HRESULT SetTotal(UInt64 size) x; \

   virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \

   virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \

   virtual HRESULT CheckBreak() x; \

-  virtual HRESULT Finilize() x; \

-  virtual HRESULT SetNumFiles(UInt64 numFiles) x; \

-  virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \

-  virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \

-  virtual HRESULT SetOperationResult(Int32 operationResult) x; \

+  /* virtual HRESULT Finalize() x; */ \

+  virtual HRESULT SetNumItems(UInt64 numItems) x; \

+  virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \

+  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \

+  virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \

+  virtual HRESULT SetOperationResult(Int32 opRes) x; \

+  virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \

+  virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \

+  /* virtual HRESULT SetPassword(const UString &password) x; */ \

   virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \

   virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \

-  /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \

-  /* virtual HRESULT CloseProgress() { return S_OK; }; */

+  virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \

+  /* virtual HRESULT CloseProgress() { return S_OK; } */

 

 struct IUpdateCallbackUI

 {

@@ -48,11 +57,14 @@
 

 class CArchiveUpdateCallback:

   public IArchiveUpdateCallback2,

+  public IArchiveUpdateCallbackFile,

+  public IArchiveExtractCallbackMessage,

   public IArchiveGetRawProps,

   public IArchiveGetRootProps,

   public ICryptoGetTextPassword2,

   public ICryptoGetTextPassword,

   public ICompressProgressInfo,

+  public IInFileStream_Callback,

   public CMyUnknownImp

 {

   #if defined(_WIN32) && !defined(UNDER_CE)

@@ -64,41 +76,53 @@
   UInt32 _hardIndex_To;

 

 public:

-  MY_UNKNOWN_IMP6(

-      IArchiveUpdateCallback2,

-      IArchiveGetRawProps,

-      IArchiveGetRootProps,

-      ICryptoGetTextPassword2,

-      ICryptoGetTextPassword,

-      ICompressProgressInfo)

+  MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)

+    MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)

+    MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)

+    MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)

+    MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)

+    MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2)

+    MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)

+    MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

 

   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

 

   INTERFACE_IArchiveUpdateCallback2(;)

+  INTERFACE_IArchiveUpdateCallbackFile(;)

+  INTERFACE_IArchiveExtractCallbackMessage(;)

   INTERFACE_IArchiveGetRawProps(;)

   INTERFACE_IArchiveGetRootProps(;)

 

   STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);

   STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

+  CRecordVector<UInt32> _openFiles_Indexes;

+  FStringVector _openFiles_Paths;

+

+  bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }

+  virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error);

+  virtual void InFileStream_On_Destroy(UINT_PTR val);

+

   CRecordVector<UInt64> VolumesSizes;

   FString VolName;

   FString VolExt;

 

   IUpdateCallbackUI *Callback;

 

-  bool ShareForWrite;

-  bool StdInMode;

-  

   const CDirItems *DirItems;

   const CDirItem *ParentDirItem;

   

+  const CArc *Arc;

+  CMyComPtr<IInArchive> Archive;

   const CObjectVector<CArcItem> *ArcItems;

   const CRecordVector<CUpdatePair2> *UpdatePairs;

   const UStringVector *NewNames;

-  CMyComPtr<IInArchive> Archive;

-  CMyComPtr<IArchiveGetRawProps> GetRawProps;

-  CMyComPtr<IArchiveGetRootProps> GetRootProps;

+

+  bool ShareForWrite;

+  bool StdInMode;

 

   bool KeepOriginalItemNames;

   bool StoreNtSecurity;

@@ -107,6 +131,7 @@
 

   Byte *ProcessedItemsStatuses;

 

+

   CArchiveUpdateCallback();

 

   bool IsDir(const CUpdatePair2 &up) const

diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
index e9c9c51..10864b2 100644
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -46,8 +46,8 @@
 {

   UString m;

   m.SetFromAscii(message);

-  m += L'\n'; m += s1;

-  m += L'\n'; m += s2;

+  m.Add_LF(); m += s1;

+  m.Add_LF(); m += s2;

   throw m;

 }

 

@@ -92,6 +92,7 @@
 

   {

     arcIndices.ClearAndSetSize(numArcItems);

+    if (numArcItems != 0)

     {

       unsigned *vals = &arcIndices[0];

       for (unsigned i = 0; i < numArcItems; i++)

diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
index 6726af3..4f28a1e 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -24,15 +24,10 @@
     up2.NewData = up2.NewProps = true;

     up2.UseArcProps = false;

     

-    switch (actionSet.StateActions[pair.State])

+    switch (actionSet.StateActions[(unsigned)pair.State])

     {

       case NPairAction::kIgnore:

-        /*

-        if (pair.State != NPairState::kOnlyOnDisk)

-          IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]);

-        // cout << "deleting";

-        */

-        if (callback)

+        if (pair.ArcIndex >= 0 && callback)

           callback->ShowDeleteFile(pair.ArcIndex);

         continue;

 

@@ -67,7 +62,9 @@
         up2.UseArcProps = (pair.ArcIndex >= 0);

         break;

     }

+

     operationChain.Add(up2);

   }

+  

   operationChain.ReserveDown();

 }

diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
index f53055e..8467543 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -43,7 +43,7 @@
 

 struct IUpdateProduceCallback

 {

-  virtual HRESULT ShowDeleteFile(int arcIndex) = 0;

+  virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;

 };

 

 void UpdateProduce(

diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
index 6ff225b..03d6eed 100644
--- a/CPP/7zip/UI/Common/WorkDir.cpp
+++ b/CPP/7zip/UI/Common/WorkDir.cpp
@@ -16,7 +16,8 @@
 FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)

 {

   NWorkDir::NMode::EEnum mode = workDirInfo.Mode;

-  #ifndef UNDER_CE

+  

+  #if defined(_WIN32) && !defined(UNDER_CE)

   if (workDirInfo.ForRemovableOnly)

   {

     mode = NWorkDir::NMode::kCurrent;

@@ -36,13 +37,15 @@
     */

   }

   #endif

-  int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1;

+  

+  int pos = path.ReverseFind_PathSepar() + 1;

   fileName = path.Ptr(pos);

+  

   switch (mode)

   {

     case NWorkDir::NMode::kCurrent:

     {

-      return path.Left(pos);;

+      return path.Left(pos);

     }

     case NWorkDir::NMode::kSpecified:

     {

diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
index df00aac..d349fae 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.h
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -111,8 +111,11 @@
 

 struct CContextMenuInfo

 {

-  bool Cascaded;

-  bool MenuIcons;

+  CBoolPair Cascaded;

+  CBoolPair MenuIcons;

+  CBoolPair ElimDup;

+

+  bool Flags_Def;

   UInt32 Flags;

 

   void Save() const;

diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp
index 16cd24c..9cf8dd6 100644
--- a/CPP/7zip/UI/Console/BenchCon.cpp
+++ b/CPP/7zip/UI/Console/BenchCon.cpp
@@ -23,7 +23,7 @@
 

 void CPrintBenchCallback::NewLine()

 {

-  Print("\n");

+  fputc('\n', _file);

 }

 

 HRESULT CPrintBenchCallback::CheckBreak()

@@ -36,7 +36,6 @@
 {

   CPrintBenchCallback callback;

   callback._file = f;

-  callback.NewLine();

   return Bench(EXTERNAL_CODECS_LOC_VARS

       &callback, NULL, props, numIterations, true);

 }

diff --git a/CPP/7zip/UI/Console/Console.mak b/CPP/7zip/UI/Console/Console.mak
index b0f8301..6757e6b 100644
--- a/CPP/7zip/UI/Console/Console.mak
+++ b/CPP/7zip/UI/Console/Console.mak
@@ -33,3 +33,4 @@
   $O\UpdatePair.obj \

   $O\UpdateProduce.obj \

 

+#

diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
index 9fbad17..a6f17af 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -4,11 +4,15 @@
 

 #include "ConsoleClose.h"

 

-static int g_BreakCounter = 0;

-static const int kBreakAbortThreshold = 2;

+#if !defined(UNDER_CE) && defined(_WIN32)

+#include "../../../Common/MyWindows.h"

+#endif

 

 namespace NConsoleClose {

 

+unsigned g_BreakCounter = 0;

+static const unsigned kBreakAbortThreshold = 2;

+

 #if !defined(UNDER_CE) && defined(_WIN32)

 static BOOL WINAPI HandlerRoutine(DWORD ctrlType)

 {

@@ -23,7 +27,7 @@
     return TRUE;

   return FALSE;

   /*

-  switch(ctrlType)

+  switch (ctrlType)

   {

     case CTRL_C_EVENT:

     case CTRL_BREAK_EVENT:

@@ -35,29 +39,18 @@
 }

 #endif

 

-bool TestBreakSignal()

-{

-  #ifdef UNDER_CE

-  return false;

-  #else

-  /*

-  if (g_BreakCounter > 0)

-    return true;

-  */

-  return (g_BreakCounter > 0);

-  #endif

-}

-

+/*

 void CheckCtrlBreak()

 {

   if (TestBreakSignal())

     throw CCtrlBreakException();

 }

+*/

 

 CCtrlHandlerSetter::CCtrlHandlerSetter()

 {

   #if !defined(UNDER_CE) && defined(_WIN32)

-  if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE))

+  if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))

     throw "SetConsoleCtrlHandler fails";

   #endif

 }

@@ -65,8 +58,11 @@
 CCtrlHandlerSetter::~CCtrlHandlerSetter()

 {

   #if !defined(UNDER_CE) && defined(_WIN32)

-  if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE))

-    throw "SetConsoleCtrlHandler fails";

+  if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE))

+  {

+    // warning for throw in destructor.

+    // throw "SetConsoleCtrlHandler fails";

+  }

   #endif

 }

 

diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
index 7101018..0a0bbf0 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.h
+++ b/CPP/7zip/UI/Console/ConsoleClose.h
@@ -1,11 +1,20 @@
-// ConsoleCloseUtils.h

+// ConsoleClose.h

 

-#ifndef __CONSOLECLOSEUTILS_H

-#define __CONSOLECLOSEUTILS_H

+#ifndef __CONSOLE_CLOSE_H

+#define __CONSOLE_CLOSE_H

 

 namespace NConsoleClose {

 

-bool TestBreakSignal();

+extern unsigned g_BreakCounter;

+

+inline bool TestBreakSignal()

+{

+  #ifdef UNDER_CE

+  return false;

+  #else

+  return (g_BreakCounter != 0);

+  #endif

+}

 

 class CCtrlHandlerSetter

 {

@@ -17,7 +26,7 @@
 class CCtrlBreakException

 {};

 

-void CheckCtrlBreak();

+// void CheckCtrlBreak();

 

 }

 

diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index 0c6f806..cc82770 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -2,12 +2,6 @@
 

 #include "StdAfx.h"

 

-// #undef sprintf

-

-#include "ConsoleClose.h"

-#include "ExtractCallbackConsole.h"

-#include "UserInputUtils.h"

-

 #include "../../../Common/IntToString.h"

 #include "../../../Common/Wildcard.h"

 

@@ -17,25 +11,146 @@
 #include "../../../Windows/ErrorMsg.h"

 #include "../../../Windows/PropVariantConv.h"

 

+#ifndef _7ZIP_ST

+#include "../../../Windows/Synchronization.h"

+#endif

+

 #include "../../Common/FilePathAutoRename.h"

 

 #include "../Common/ExtractingFilePath.h"

 

+#include "ConsoleClose.h"

+#include "ExtractCallbackConsole.h"

+#include "UserInputUtils.h"

+

 using namespace NWindows;

 using namespace NFile;

 using namespace NDir;

 

-static const char *kTestString    =  "Testing     ";

-static const char *kExtractString =  "Extracting  ";

-static const char *kSkipString    =  "Skipping    ";

+static HRESULT CheckBreak2()

+{

+  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;

+}

+

+static const char *kError = "ERROR: ";

+

+

+void CExtractScanConsole::StartScanning()

+{

+  if (NeedPercents())

+    _percent.Command = "Scan";

+}

+

+HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)

+{

+  if (NeedPercents())

+  {

+    _percent.Files = st.NumDirs + st.NumFiles;

+    _percent.Completed = st.GetTotalBytes();

+    _percent.FileName = fs2us(path);

+    _percent.Print();

+  }

+

+  return CheckBreak2();

+}

+

+HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)

+{

+  ClosePercentsAndFlush();

+  

+  if (_se)

+  {

+    *_se << endl << kError << NError::MyFormatMessage(systemError) << endl <<

+        fs2us(path) << endl << endl;

+    _se->Flush();

+  }

+  return HRESULT_FROM_WIN32(systemError);

+}

+

+

+void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)

+{

+  char temp[32];

+  ConvertUInt64ToString(val, temp);

+  s += temp;

+  s.Add_Space();

+  s += name;

+}

+

+void PrintSize_bytes_Smart(AString &s, UInt64 val)

+{

+  Print_UInt64_and_String(s, val, "bytes");

+

+  if (val == 0)

+    return;

+

+  unsigned numBits = 10;

+  char c = 'K';

+  char temp[4] = { 'K', 'i', 'B', 0 };

+       if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }

+  else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }

+  temp[0] = c;

+  s += " (";

+  Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);

+  s += ')';

+}

+

+void Print_DirItemsStat(AString &s, const CDirItemsStat &st)

+{

+  if (st.NumDirs != 0)

+  {

+    Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders");

+    s += ", ";

+  }

+  Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");

+  s += ", ";

+  PrintSize_bytes_Smart(s, st.FilesSize);

+  if (st.NumAltStreams != 0)

+  {

+    s.Add_LF();

+    Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");

+    s += ", ";

+    PrintSize_bytes_Smart(s, st.AltStreamsSize);

+  }

+}

+

+void CExtractScanConsole::PrintStat(const CDirItemsStat &st)

+{

+  if (_so)

+  {

+    AString s;

+    Print_DirItemsStat(s, st);

+    *_so << s << endl;

+  }

+}

+

+

+

+

+

+

+

+#ifndef _7ZIP_ST

+static NSynchronization::CCriticalSection g_CriticalSection;

+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);

+#else

+#define MT_LOCK

+#endif

+

+

+static const char *kTestString    =  "T";

+static const char *kExtractString =  "-";

+static const char *kSkipString    =  ".";

 

 // static const char *kCantAutoRename = "can not create file with auto name\n";

 // static const char *kCantRenameFile = "can not rename existing file\n";

 // static const char *kCantDeleteOutputFile = "can not delete output file ";

-static const char *kError = "ERROR: ";

+

 static const char *kMemoryExceptionMessage = "Can't allocate required memory!";

 

-static const char *kProcessing = "Processing archive: ";

+static const char *kExtracting = "Extracting archive: ";

+static const char *kTesting = "Testing archive: ";

+

 static const char *kEverythingIsOk = "Everything is Ok";

 static const char *kNoFiles = "No files to process";

 

@@ -49,8 +164,9 @@
 static const char *kDataAfterEnd = "There are some data after the end of the payload data";

 static const char *kIsNotArc = "Is not archive";

 static const char *kHeadersError = "Headers Error";

+static const char *kWrongPassword = "Wrong password";

 

-static const char *k_ErrorFlagsMessages[] =

+static const char * const k_ErrorFlagsMessages[] =

 {

     "Is not archive"

   , "Headers Error"

@@ -65,31 +181,72 @@
   , "CRC Error"

 };

 

-

-STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)

+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)

 {

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  return S_OK;

+  MT_LOCK

+

+  if (NeedPercents())

+  {

+    _percent.Total = size;

+    _percent.Print();

+  }

+  return CheckBreak2();

 }

 

-STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)

+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)

 {

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  return S_OK;

+  MT_LOCK

+

+  if (NeedPercents())

+  {

+    if (completeValue)

+      _percent.Completed = *completeValue;

+    _percent.Print();

+  }

+  return CheckBreak2();

+}

+

+static const char *kTab = "  ";

+

+static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)

+{

+  *_so << kTab << "Path:     " << path << endl;

+  if (size)

+  {

+    AString s;

+    PrintSize_bytes_Smart(s, *size);

+    *_so << kTab << "Size:     " << s << endl;

+  }

+  if (ft)

+  {

+    char temp[64];

+    FILETIME locTime;

+    if (FileTimeToLocalFileTime(ft, &locTime))

+      if (ConvertFileTimeToString(locTime, temp, true, true))

+        *_so << kTab << "Modified: " << temp << endl;

+  }

 }

 

 STDMETHODIMP CExtractCallbackConsole::AskOverwrite(

-    const wchar_t *existName, const FILETIME *, const UInt64 *,

-    const wchar_t *newName, const FILETIME *, const UInt64 *,

+    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

+    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

     Int32 *answer)

 {

-  (*OutStream) << "file " << existName << endl <<

-        "already exists. Overwrite with" << endl <<

-        newName;

+  MT_LOCK

   

-  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);

+  RINOK(CheckBreak2());

+

+  ClosePercentsAndFlush();

+

+  if (_so)

+  {

+    *_so << endl << "Would you like to replace the existing file:\n";

+    PrintFileInfo(_so, existName, existTime, existSize);

+    *_so << "with the file from archive:\n";

+    PrintFileInfo(_so, newName, newTime, newSize);

+  }

+  

+  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);

   

   switch (overwriteAnswer)

   {

@@ -101,86 +258,192 @@
     case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;

     default: return E_FAIL;

   }

-  return S_OK;

+  

+  if (_so)

+  {

+    *_so << endl;

+    if (NeedFlush)

+      _so->Flush();

+  }

+  

+  return CheckBreak2();

 }

 

-STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)

+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position)

 {

+  MT_LOCK

+  

+  _currentName = name;

+  

   const char *s;

+  unsigned requiredLevel = 1;

+

   switch (askExtractMode)

   {

     case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;

     case NArchive::NExtract::NAskMode::kTest:    s = kTestString; break;

-    case NArchive::NExtract::NAskMode::kSkip:    s = kSkipString; break;

-    default: s = ""; // return E_FAIL;

+    case NArchive::NExtract::NAskMode::kSkip:    s = kSkipString; requiredLevel = 2; break;

+    default: s = "???"; requiredLevel = 2;

   };

-  (*OutStream) << s << name;

-  if (position != 0)

-    (*OutStream) << " <" << *position << ">";

-  return S_OK;

+

+  bool show2 = (LogLevel >= requiredLevel && _so);

+

+  if (show2)

+  {

+    ClosePercents_for_so();

+    

+    _tempA = s;

+    if (name)

+      _tempA.Add_Space();

+    *_so << _tempA;

+

+    _tempU.Empty();

+    if (name)

+      _tempU = name;

+    _so->PrintUString(_tempU, _tempA);

+    if (position)

+      *_so << " <" << *position << ">";

+    *_so << endl;

+ 

+    if (NeedFlush)

+      _so->Flush();

+  }

+

+  if (NeedPercents())

+  {

+    if (PercentsNameLevel >= 1)

+    {

+      _percent.FileName.Empty();

+      _percent.Command.Empty();

+      if (PercentsNameLevel > 1 || !show2)

+      {

+        _percent.Command = s;

+        if (name)

+          _percent.FileName = name;

+      }

+    }

+    _percent.Print();

+  }

+

+  return CheckBreak2();

 }

 

 STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)

 {

-  (*OutStream) << message << endl;

-  NumFileErrorsInCurrent++;

+  MT_LOCK

+  

+  RINOK(CheckBreak2());

+

+  NumFileErrors_in_Current++;

   NumFileErrors++;

-  return S_OK;

+

+  ClosePercentsAndFlush();

+  if (_se)

+  {

+    *_se << kError << message << endl;

+    _se->Flush();

+  }

+

+  return CheckBreak2();

 }

 

-STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)

+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)

 {

-  switch (operationResult)

-  {

-    case NArchive::NExtract::NOperationResult::kOK:

-      break;

-    default:

+  dest.Empty();

+    const char *s = NULL;

+    

+    switch (opRes)

     {

-      NumFileErrorsInCurrent++;

-      NumFileErrors++;

-      (*OutStream) << "  :  ";

-      const char *s = NULL;

-      switch (operationResult)

-      {

-        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

-          s = kUnsupportedMethod;

-          break;

-        case NArchive::NExtract::NOperationResult::kCRCError:

-          s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);

-          break;

-        case NArchive::NExtract::NOperationResult::kDataError:

-          s = (encrypted ? kDataErrorEncrypted : kDataError);

-          break;

-        case NArchive::NExtract::NOperationResult::kUnavailable:

-          s = kUnavailableData;

-          break;

-        case NArchive::NExtract::NOperationResult::kUnexpectedEnd:

-          s = kUnexpectedEnd;

-          break;

-        case NArchive::NExtract::NOperationResult::kDataAfterEnd:

-          s = kDataAfterEnd;

-          break;

-        case NArchive::NExtract::NOperationResult::kIsNotArc:

-          s = kIsNotArc;

-          break;

-        case NArchive::NExtract::NOperationResult::kHeadersError:

-          s = kHeadersError;

-          break;

-      }

-      if (s)

-        (*OutStream) << "Error : " << s;

-      else

-      {

-        char temp[16];

-        ConvertUInt32ToString(operationResult, temp);

-        (*OutStream) << "Error #" << temp;

-      }

+      case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

+        s = kUnsupportedMethod;

+        break;

+      case NArchive::NExtract::NOperationResult::kCRCError:

+        s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);

+        break;

+      case NArchive::NExtract::NOperationResult::kDataError:

+        s = (encrypted ? kDataErrorEncrypted : kDataError);

+        break;

+      case NArchive::NExtract::NOperationResult::kUnavailable:

+        s = kUnavailableData;

+        break;

+      case NArchive::NExtract::NOperationResult::kUnexpectedEnd:

+        s = kUnexpectedEnd;

+        break;

+      case NArchive::NExtract::NOperationResult::kDataAfterEnd:

+        s = kDataAfterEnd;

+        break;

+      case NArchive::NExtract::NOperationResult::kIsNotArc:

+        s = kIsNotArc;

+        break;

+      case NArchive::NExtract::NOperationResult::kHeadersError:

+        s = kHeadersError;

+        break;

+      case NArchive::NExtract::NOperationResult::kWrongPassword:

+        s = kWrongPassword;

+        break;

+    }

+    

+    dest += kError;

+    if (s)

+      dest += s;

+    else

+    {

+      char temp[16];

+      ConvertUInt32ToString(opRes, temp);

+      dest += "Error #";

+      dest += temp;

+    }

+}

+

+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)

+{

+  MT_LOCK

+  

+  if (opRes == NArchive::NExtract::NOperationResult::kOK)

+  {

+    if (NeedPercents())

+    {

+      _percent.Command.Empty();

+      _percent.FileName.Empty();

+      _percent.Files++;

     }

   }

-  (*OutStream) << endl;

-  return S_OK;

+  else

+  {

+    NumFileErrors_in_Current++;

+    NumFileErrors++;

+    

+    if (_se)

+    {

+      ClosePercentsAndFlush();

+      

+      AString s;

+      SetExtractErrorMessage(opRes, encrypted, s);

+      

+      *_se << s;

+      if (!_currentName.IsEmpty())

+        *_se << " : " << _currentName;

+      *_se << endl;

+      _se->Flush();

+    }

+  }

+  

+  return CheckBreak2();

 }

 

+STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)

+{

+  if (opRes != NArchive::NExtract::NOperationResult::kOK)

+  {

+    _currentName = name;

+    return SetOperationResult(opRes, encrypted);

+  }

+

+  return CheckBreak2();

+}

+

+

+

 #ifndef _NO_CRYPTO

 

 HRESULT CExtractCallbackConsole::SetPassword(const UString &password)

@@ -192,55 +455,39 @@
 

 STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)

 {

-  if (!PasswordIsDefined)

-  {

-    Password = GetPassword(OutStream);

-    PasswordIsDefined = true;

-  }

-  return StringToBstr(Password, password);

+  COM_TRY_BEGIN

+  MT_LOCK

+  return Open_CryptoGetTextPassword(password);

+  COM_TRY_END

 }

 

 #endif

 

-HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)

+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)

 {

+  RINOK(CheckBreak2());

+

   NumTryArcs++;

-  ThereIsErrorInCurrent = false;

-  ThereIsWarningInCurrent = false;

-  NumFileErrorsInCurrent = 0;

-  (*OutStream) << endl << kProcessing << name << endl;

+  ThereIsError_in_Current = false;

+  ThereIsWarning_in_Current = false;

+  NumFileErrors_in_Current = 0;

+  

+  ClosePercents_for_so();

+  if (_so)

+    *_so << endl << (testMode ? kTesting : kExtracting) << name << endl;

+

+  if (NeedPercents())

+    _percent.Command = "Open";

   return S_OK;

 }

 

-HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)

-{

-  (*OutStream) << endl;

-  if (result != S_OK)

-  {

-    (*OutStream) << "Error: ";

-    if (result == S_FALSE)

-    {

-      (*OutStream) << (encrypted ?

-        "Can not open encrypted archive. Wrong password?" :

-        "Can not open file as archive");

-    }

-    else

-    {

-      if (result == E_OUTOFMEMORY)

-        (*OutStream) << "Can't allocate required memory";

-      else

-        (*OutStream) << NError::MyFormatMessage(result);

-    }

-    (*OutStream) << endl;

-    NumCantOpenArcs++;

-    ThereIsErrorInCurrent = true;

-  }

-  return S_OK;

-}

+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);

+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);

 

-AString GetOpenArcErrorMessage(UInt32 errorFlags)

+static AString GetOpenArcErrorMessage(UInt32 errorFlags)

 {

   AString s;

+  

   for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)

   {

     UInt32 f = (1 << i);

@@ -248,10 +495,11 @@
       continue;

     const char *m = k_ErrorFlagsMessages[i];

     if (!s.IsEmpty())

-      s += '\n';

+      s.Add_LF();

     s += m;

     errorFlags &= ~f;

   }

+  

   if (errorFlags != 0)

   {

     char sz[16];

@@ -259,125 +507,258 @@
     sz[1] = 'x';

     ConvertUInt32ToHex(errorFlags, sz + 2);

     if (!s.IsEmpty())

-      s += '\n';

+      s.Add_LF();

     s += sz;

   }

+  

   return s;

 }

 

-

-HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name,

-    UInt32 errorFlags, const wchar_t *errors,

-    UInt32 warningFlags, const wchar_t *warnings)

+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)

 {

-  if (level != 0)

+  if (errorFlags == 0)

+    return;

+  so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;

+}

+

+void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)

+{

+  s.Add_LF();

+  s.AddAscii(pre);

+  s.AddAscii(" as [");

+  s += arcType;

+  s.AddAscii("] archive");

+}

+

+void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)

+{

+  const CArcErrorInfo &er = arc.ErrorInfo;

+  

+  UString s = L"WARNING:\n";

+  s += arc.Path;

+  if (arc.FormatIndex == er.ErrorFormatIndex)

   {

-    (*OutStream) << name << endl;

+    s.Add_LF();

+    s.AddAscii("The archive is open with offset");

+  }

+  else

+  {

+    Add_Messsage_Pre_ArcType(s, "Can not open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex));

+    Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex));

+  }

+  

+  *_so << s << endl << endl;

+}

+        

+

+HRESULT CExtractCallbackConsole::OpenResult(

+    const CCodecs *codecs, const CArchiveLink &arcLink,

+    const wchar_t *name, HRESULT result)

+{

+  ClosePercents();

+

+  if (NeedPercents())

+  {

+    _percent.Files = 0;

+    _percent.Command.Empty();

+    _percent.FileName.Empty();

   }

 

-  if (errorFlags != 0)

-  {

-    (*OutStream) << "Errors: ";

-    (*OutStream) << endl;

-    (*OutStream) << GetOpenArcErrorMessage(errorFlags);

-    (*OutStream) << endl;

-    NumOpenArcErrors++;

-    ThereIsErrorInCurrent = true;

-  }

+ 

+  ClosePercentsAndFlush();

 

-  if (errors && wcslen(errors) != 0)

+  FOR_VECTOR (level, arcLink.Arcs)

   {

-    (*OutStream) << "Errors: ";

-    (*OutStream) << endl;

-    (*OutStream) << errors;

-    (*OutStream) << endl;

-    NumOpenArcErrors++;

-    ThereIsErrorInCurrent = true;

-  }

+    const CArc &arc = arcLink.Arcs[level];

+    const CArcErrorInfo &er = arc.ErrorInfo;

+    

+    UInt32 errorFlags = er.GetErrorFlags();

 

-  if (warningFlags != 0)

+    if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())

+    {

+      if (_se)

+      {

+        *_se << endl;

+        if (level != 0)

+          *_se << arc.Path << endl;

+      }

+      

+      if (errorFlags != 0)

+      {

+        if (_se)

+          PrintErrorFlags(*_se, "ERRORS:", errorFlags);

+        NumOpenArcErrors++;

+        ThereIsError_in_Current = true;

+      }

+      

+      if (!er.ErrorMessage.IsEmpty())

+      {

+        if (_se)

+          *_se << "ERRORS:" << endl << er.ErrorMessage << endl;

+        NumOpenArcErrors++;

+        ThereIsError_in_Current = true;

+      }

+      

+      if (_se)

+      {

+        *_se << endl;

+        _se->Flush();

+      }

+    }

+    

+    UInt32 warningFlags = er.GetWarningFlags();

+

+    if (warningFlags != 0 || !er.WarningMessage.IsEmpty())

+    {

+      if (_so)

+      {

+        *_so << endl;

+        if (level != 0)

+          *_so << arc.Path << endl;

+      }

+      

+      if (warningFlags != 0)

+      {

+        if (_so)

+          PrintErrorFlags(*_so, "WARNINGS:", warningFlags);

+        NumOpenArcWarnings++;

+        ThereIsWarning_in_Current = true;

+      }

+      

+      if (!er.WarningMessage.IsEmpty())

+      {

+        if (_so)

+          *_so << "WARNINGS:" << endl << er.WarningMessage << endl;

+        NumOpenArcWarnings++;

+        ThereIsWarning_in_Current = true;

+      }

+      

+      if (_so)

+      {

+        *_so << endl;

+        if (NeedFlush)

+          _so->Flush();

+      }

+    }

+

+  

+    if (er.ErrorFormatIndex >= 0)

+    {

+      if (_so)

+      {

+        Print_ErrorFormatIndex_Warning(_so, codecs, arc);

+        if (NeedFlush)

+          _so->Flush();

+      }

+      ThereIsWarning_in_Current = true;

+    }

+  }

+      

+  if (result == S_OK)

   {

-    (*OutStream) << "Warnings: ";

-    (*OutStream) << endl;

-    (*OutStream) << GetOpenArcErrorMessage(warningFlags);

-    (*OutStream) << endl;

-    NumOpenArcWarnings++;

-    ThereIsWarningInCurrent = true;

+    if (_so)

+    {

+      RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));

+      *_so << endl;

+    }

   }

-

-  if (warnings && wcslen(warnings) != 0)

+  else

   {

-    (*OutStream) << "Warnings: ";

-    (*OutStream) << endl;

-    (*OutStream) << warnings;

-    (*OutStream) << endl;

-    NumOpenArcWarnings++;

-    ThereIsWarningInCurrent = true;

+    NumCantOpenArcs++;

+    if (_so)

+      _so->Flush();

+    if (_se)

+    {

+      *_se << kError << name << endl;

+      HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);

+      RINOK(res);

+      if (result == S_FALSE)

+      {

+      }

+      else

+      {

+        if (result == E_OUTOFMEMORY)

+          *_se << "Can't allocate required memory";

+        else

+          *_se << NError::MyFormatMessage(result);

+        *_se << endl;

+      }

+      _se->Flush();

+    }

   }

-

-  (*OutStream) << endl;

-  return S_OK;

+  

+  

+  return CheckBreak2();

 }

   

 HRESULT CExtractCallbackConsole::ThereAreNoFiles()

 {

-  (*OutStream) << endl << kNoFiles << endl;

-  return S_OK;

+  ClosePercents_for_so();

+

+  if (_so)

+  {

+    *_so << endl << kNoFiles << endl;

+    if (NeedFlush)

+      _so->Flush();

+  }

+  return CheckBreak2();

 }

 

 HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)

 {

+  MT_LOCK

+  

+  if (NeedPercents())

+  {

+    _percent.ClosePrint(true);

+    _percent.Command.Empty();

+    _percent.FileName.Empty();

+  }

+

+  if (_so)

+    _so->Flush();

+

   if (result == S_OK)

   {

-    (*OutStream) << endl;

-

-    if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent)

+    if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)

     {

-      if (ThereIsWarningInCurrent)

+      if (ThereIsWarning_in_Current)

         NumArcsWithWarnings++;

       else

         NumOkArcs++;

-      (*OutStream) << kEverythingIsOk << endl;

+      if (_so)

+        *_so << kEverythingIsOk << endl;

     }

     else

     {

       NumArcsWithError++;

-      if (NumFileErrorsInCurrent != 0)

-        (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl;

+      if (_so)

+      {

+        *_so << endl;

+        if (NumFileErrors_in_Current != 0)

+          *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;

+      }

     }

-    return S_OK;

+    if (_so && NeedFlush)

+      _so->Flush();

   }

-  

-  NumArcsWithError++;

-  if (result == E_ABORT || result == ERROR_DISK_FULL)

-    return result;

-  (*OutStream) << endl << kError;

-  if (result == E_OUTOFMEMORY)

-    (*OutStream) << kMemoryExceptionMessage;

   else

-    (*OutStream) << NError::MyFormatMessage(result);

-  (*OutStream) << endl;

-  return S_OK;

-}

+  {

+    NumArcsWithError++;

+    if (result == E_ABORT || result == ERROR_DISK_FULL)

+      return result;

+    

+    if (_se)

+    {

+      *_se << endl << kError;

+      if (result == E_OUTOFMEMORY)

+        *_se << kMemoryExceptionMessage;

+      else

+        *_se << NError::MyFormatMessage(result);

+      *_se << endl;

+      _se->Flush();

+    }

+  }

 

-HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)

-{

-  UString s = L"Warning:\n";

-  if (wcscmp(okType, errorType) == 0)

-  {

-    s += L"The archive is open with offset";

-  }

-  else

-  {

-    s += name;

-    s += L"\nCan not open the file as [";

-    s += errorType;

-    s += L"] archive\n";

-    s += L"The file is open as [";

-    s += okType;

-    s += L"] archive";

-  }

- (*OutStream) << s << endl << endl;

- ThereIsWarningInCurrent = true;

-  return S_OK;

+  return CheckBreak2();

 }

diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
index cefa2c2..5de6c5b 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -1,28 +1,95 @@
 // ExtractCallbackConsole.h

 

-#ifndef __EXTRACTCALLBACKCONSOLE_H

-#define __EXTRACTCALLBACKCONSOLE_H

+#ifndef __EXTRACT_CALLBACK_CONSOLE_H

+#define __EXTRACT_CALLBACK_CONSOLE_H

 

-#include "../../../Common/MyString.h"

 #include "../../../Common/StdOutStream.h"

 

-#include "../../Common/FileStreams.h"

-

 #include "../../IPassword.h"

 

 #include "../../Archive/IArchive.h"

 

 #include "../Common/ArchiveExtractCallback.h"

 

+#include "PercentPrinter.h"

+

+#include "OpenCallbackConsole.h"

+

+class CExtractScanConsole: public IDirItemsCallback

+{

+  CStdOutStream *_so;

+  CStdOutStream *_se;

+  CPercentPrinter _percent;

+

+  bool NeedPercents() const { return _percent._so != NULL; }

+  

+  void ClosePercentsAndFlush()

+  {

+    if (NeedPercents())

+      _percent.ClosePrint(true);

+    if (_so)

+      _so->Flush();

+  }

+

+public:

+  void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)

+  {

+    _so = outStream;

+    _se = errorStream;

+    _percent._so = percentStream;

+  }

+  

+  void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }

+

+  void StartScanning();

+  

+  INTERFACE_IDirItemsCallback(;)

+

+  void CloseScanning()

+  {

+    if (NeedPercents())

+      _percent.ClosePrint(true);

+  }

+

+  void PrintStat(const CDirItemsStat &st);

+};

+

+

+

+

 class CExtractCallbackConsole:

   public IExtractCallbackUI,

+  // public IArchiveExtractCallbackMessage,

+  public IFolderArchiveExtractCallback2,

   #ifndef _NO_CRYPTO

   public ICryptoGetTextPassword,

   #endif

+  public COpenCallbackConsole,

   public CMyUnknownImp

 {

+  AString _tempA;

+  UString _tempU;

+

+  UString _currentName;

+

+  void ClosePercents_for_so()

+  {

+    if (NeedPercents() && _so == _percent._so)

+      _percent.ClosePrint(false);

+  }

+  

+  void ClosePercentsAndFlush()

+  {

+    if (NeedPercents())

+      _percent.ClosePrint(true);

+    if (_so)

+      _so->Flush();

+  }

+

 public:

   MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)

+  // MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)

+  MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)

   #ifndef _NO_CRYPTO

   MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)

   #endif

@@ -32,57 +99,55 @@
   STDMETHOD(SetTotal)(UInt64 total);

   STDMETHOD(SetCompleted)(const UInt64 *completeValue);

 

-  // IFolderArchiveExtractCallback

-  STDMETHOD(AskOverwrite)(

-      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

-      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

-      Int32 *answer);

-  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);

+  INTERFACE_IFolderArchiveExtractCallback(;)

 

-  STDMETHOD(MessageError)(const wchar_t *message);

-  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);

+  INTERFACE_IExtractCallbackUI(;)

+  // INTERFACE_IArchiveExtractCallbackMessage(;)

+  INTERFACE_IFolderArchiveExtractCallback2(;)

 

-  HRESULT BeforeOpen(const wchar_t *name);

-  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);

-  HRESULT SetError(int level, const wchar_t *name,

-        UInt32 errorFlags, const wchar_t *errors,

-        UInt32 warningFlags, const wchar_t *warnings);

-

-  HRESULT ThereAreNoFiles();

-  HRESULT ExtractResult(HRESULT result);

-  HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);

-

- 

   #ifndef _NO_CRYPTO

-  HRESULT SetPassword(const UString &password);

-  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

-  bool PasswordIsDefined;

-  UString Password;

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

   #endif

   

   UInt64 NumTryArcs;

-  bool ThereIsErrorInCurrent;

-  bool ThereIsWarningInCurrent;

+  

+  bool ThereIsError_in_Current;

+  bool ThereIsWarning_in_Current;

 

-  UInt64 NumCantOpenArcs;

   UInt64 NumOkArcs;

+  UInt64 NumCantOpenArcs;

   UInt64 NumArcsWithError;

   UInt64 NumArcsWithWarnings;

 

-  UInt64 NumProblemArcsLevs;

   UInt64 NumOpenArcErrors;

   UInt64 NumOpenArcWarnings;

   

   UInt64 NumFileErrors;

-  UInt64 NumFileErrorsInCurrent;

+  UInt64 NumFileErrors_in_Current;

 

-  CStdOutStream *OutStream;

+  bool NeedFlush;

+  unsigned PercentsNameLevel;

+  unsigned LogLevel;

 

-  void Init()

+  CExtractCallbackConsole():

+      NeedFlush(false),

+      PercentsNameLevel(1),

+      LogLevel(0)

+      {}

+

+  void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }

+

+  void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)

   {

+    COpenCallbackConsole::Init(outStream, errorStream, percentStream);

+

     NumTryArcs = 0;

+    

+    ThereIsError_in_Current = false;

+    ThereIsWarning_in_Current = false;

+

     NumOkArcs = 0;

     NumCantOpenArcs = 0;

     NumArcsWithError = 0;

@@ -90,10 +155,10 @@
 

     NumOpenArcErrors = 0;

     NumOpenArcWarnings = 0;

+    

     NumFileErrors = 0;

-    NumFileErrorsInCurrent = 0;

+    NumFileErrors_in_Current = 0;

   }

-

 };

 

 #endif

diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
index a9e62c2..863c5e5 100644
--- a/CPP/7zip/UI/Console/HashCon.cpp
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -3,9 +3,6 @@
 #include "StdAfx.h"

 

 #include "../../../Common/IntToString.h"

-#include "../../../Common/StringConvert.h"

-

-#include "../../../Windows/ErrorMsg.h"

 

 #include "ConsoleClose.h"

 #include "HashCon.h"

@@ -14,53 +11,85 @@
 

 static const char *kScanningMessage = "Scanning";

 

-HRESULT CHashCallbackConsole::CheckBreak()

+static HRESULT CheckBreak2()

 {

   return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;

 }

 

+HRESULT CHashCallbackConsole::CheckBreak()

+{

+  return CheckBreak2();

+}

+

 HRESULT CHashCallbackConsole::StartScanning()

 {

-  (*OutStream) << kScanningMessage;

-  return CheckBreak();

+  if (PrintHeaders && _so)

+    *_so << kScanningMessage << endl;

+  if (NeedPercents())

+  {

+    _percent.ClearCurState();

+    _percent.Command = "Scan";

+  }

+  return CheckBreak2();

 }

 

-HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)

+HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)

 {

-  return CheckBreak();

+  if (NeedPercents())

+  {

+    _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;

+    _percent.Completed = st.GetTotalBytes();

+    _percent.FileName = fs2us(path);

+    _percent.Print();

+  }

+  return CheckBreak2();

 }

 

-HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)

+HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError)

 {

-  return CanNotFindError_Base(name, systemError);

+  return ScanError_Base(path, systemError);

 }

 

-HRESULT CHashCallbackConsole::FinishScanning()

+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);

+

+HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st)

 {

-  (*OutStream) << endl << endl;

-  return CheckBreak();

+  if (NeedPercents())

+  {

+    _percent.ClosePrint(true);

+    _percent.ClearCurState();

+  }

+  if (PrintHeaders && _so)

+  {

+    Print_DirItemsStat(_s, st);

+    *_so << _s << endl << endl;

+  }

+  return CheckBreak2();

 }

 

 HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */)

 {

-  return CheckBreak();

+  return CheckBreak2();

 }

 

 HRESULT CHashCallbackConsole::SetTotal(UInt64 size)

 {

-  if (EnablePercents)

-    m_PercentPrinter.SetTotal(size);

-  return CheckBreak();

+  if (NeedPercents())

+  {

+    _percent.Total = size;

+    _percent.Print();

+  }

+  return CheckBreak2();

 }

 

 HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)

 {

-  if (completeValue && EnablePercents)

+  if (completeValue && NeedPercents())

   {

-    m_PercentPrinter.SetRatio(*completeValue);

-    m_PercentPrinter.PrintRatio();

+    _percent.Completed = *completeValue;

+    _percent.Print();

   }

-  return CheckBreak();

+  return CheckBreak2();

 }

 

 static void AddMinuses(AString &s, unsigned num)

@@ -69,171 +98,228 @@
     s += '-';

 }

 

-static void SetSpaces(char *s, int num)

+static void AddSpaces_if_Positive(AString &s, int num)

 {

   for (int i = 0; i < num; i++)

-    s[i] = ' ';

+    s.Add_Space();

 }

 

-static void SetSpacesAndNul(char *s, int num)

+static void SetSpacesAndNul(char *s, unsigned num)

 {

-  SetSpaces(s, num);

+  for (unsigned i = 0; i < num; i++)

+    s[i] = ' ';

   s[num] = 0;

 }

 

-static void AddSpaces(UString &s, int num)

-{

-  for (int i = 0; i < num; i++)

-    s += ' ';

-}

+static const unsigned kSizeField_Len = 13;

+static const unsigned kNameField_Len = 12;

 

-static const int kSizeField_Len = 13;

-static const int kNameField_Len = 12;

+static const unsigned kHashColumnWidth_Min = 4 * 2;

 

 static unsigned GetColumnWidth(unsigned digestSize)

 {

   unsigned width = digestSize * 2;

-  const unsigned kMinColumnWidth = 8;

-  return width < kMinColumnWidth ? kMinColumnWidth: width;

+  return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;

 }

 

 void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)

 {

-  AString s;

+  _s.Empty();

+  

   for (unsigned i = 0; i < hashers.Size(); i++)

   {

+    if (i != 0)

+      _s.Add_Space();

     const CHasherState &h = hashers[i];

-    AddMinuses(s, GetColumnWidth(h.DigestSize));

-    s += ' ';

+    AddMinuses(_s, GetColumnWidth(h.DigestSize));

   }

-  AddMinuses(s, kSizeField_Len);

-  s += "  ";

-  AddMinuses(s, kNameField_Len);

-  m_PercentPrinter.PrintString(s);

-  m_PercentPrinter.PrintNewLine();

+

+  if (PrintSize)

+  {

+    _s.Add_Space();

+    AddMinuses(_s, kSizeField_Len);

+  }

+

+  if (PrintName)

+  {

+    AddSpacesBeforeName();

+    AddMinuses(_s, kNameField_Len);

+  }

+  

+  *_so << _s << endl;

 }

 

 HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)

 {

-  UString s;

-  FOR_VECTOR (i, hb.Hashers)

+  if (PrintHeaders && _so)

   {

-    const CHasherState &h = hb.Hashers[i];

-    s += h.Name;

-    AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1);

+    _s.Empty();

+    ClosePercents_for_so();

+    

+    FOR_VECTOR (i, hb.Hashers)

+    {

+      if (i != 0)

+        _s.Add_Space();

+      const CHasherState &h = hb.Hashers[i];

+      _s += h.Name;

+      AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());

+    }

+    

+    if (PrintSize)

+    {

+      _s.Add_Space();

+      const AString s2 = "Size";

+      AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());

+      _s += s2;

+    }

+    

+    if (PrintName)

+    {

+      AddSpacesBeforeName();

+      _s += "Name";

+    }

+    

+    *_so << _s << endl;

+    PrintSeparatorLine(hb.Hashers);

   }

-  UString s2 = L"Size";

-  AddSpaces(s, kSizeField_Len - s2.Len());

-  s += s2;

-  s += L"  ";

-  s += L"Name";

-  m_PercentPrinter.PrintString(s);

-  m_PercentPrinter.PrintNewLine();

-  PrintSeparatorLine(hb.Hashers);

-  return CheckBreak();

+  

+  return CheckBreak2();

 }

 

-HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)

+HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError)

 {

-  FailedCodes.Add(systemError);

-  FailedFiles.Add(name);

-  // if (systemError == ERROR_SHARING_VIOLATION)

-  {

-    m_PercentPrinter.PrintString(name);

-    m_PercentPrinter.PrintString(": WARNING: ");

-    m_PercentPrinter.PrintString(NWindows::NError::MyFormatMessage(systemError));

-    return S_FALSE;

-  }

-  // return systemError;

+  return OpenFileError_Base(path, systemError);

 }

 

 HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)

 {

-  m_FileName = name;

-  return CheckBreak();

+  _fileName = name;

+

+  if (NeedPercents())

+  {

+    if (PrintNameInPercents)

+    {

+      _percent.FileName.Empty();

+      if (name)

+        _percent.FileName = name;

+    }

+   _percent.Print();

+  }

+  return CheckBreak2();

 }

 

 void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,

     const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)

 {

+  ClosePercents_for_so();

+

+  _s.Empty();

+

   FOR_VECTOR (i, hashers)

   {

     const CHasherState &h = hashers[i];

-

     char s[k_HashCalc_DigestSize_Max * 2 + 64];

     s[0] = 0;

     if (showHash)

       AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);

-    SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s) + 1);

-    m_PercentPrinter.PrintString(s);

+    SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s));

+    if (i != 0)

+      _s.Add_Space();

+    _s += s;

   }

-  char s[64];

-  s[0] = 0;

-  char *p = s;

-  if (showHash && fileSize != 0)

+  

+  if (PrintSize)

   {

-    p = s + 32;

-    ConvertUInt64ToString(fileSize, p);

-    int numSpaces = kSizeField_Len - (int)strlen(p);

-    if (numSpaces > 0)

+    _s.Add_Space();

+

+    char s[kSizeField_Len + 32];

+    char *p = s;

+    

+    if (showHash)

     {

-      p -= numSpaces;

-      SetSpaces(p, numSpaces);

+      p = s + kSizeField_Len;

+      ConvertUInt64ToString(fileSize, p);

+      int numSpaces = kSizeField_Len - (int)strlen(p);

+      if (numSpaces > 0)

+      {

+        p -= (unsigned)numSpaces;

+        for (unsigned i = 0; i < (unsigned)numSpaces; i++)

+          p[i] = ' ';

+      }

     }

+    else

+      SetSpacesAndNul(s, kSizeField_Len);

+    

+    _s += p;

   }

-  else

-    SetSpacesAndNul(s, kSizeField_Len - (int)strlen(s));

-  unsigned len = (unsigned)strlen(p);

-  p[len] = ' ';

-  p[len + 1] = ' ';

-  p[len + 2] = 0;

-  m_PercentPrinter.PrintString(p);

+

+  if (PrintName)

+    AddSpacesBeforeName();

+  

+  *_so << _s;

 }

 

 HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)

 {

-  PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);

-  if (m_FileName.IsEmpty())

-    m_PercentPrinter.PrintString(kEmptyFileAlias);

-  else

-    m_PercentPrinter.PrintString(m_FileName);

-  m_PercentPrinter.PrintNewLine();

-  return S_OK;

+  if (_so)

+  {

+    PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);

+    if (PrintName)

+    {

+      if (_fileName.IsEmpty())

+        *_so << kEmptyFileAlias;

+      else

+        *_so << _fileName;

+    }

+    *_so << endl;

+  }

+  

+  if (NeedPercents())

+  {

+    _percent.Files++;

+    _percent.Print();

+  }

+

+  return CheckBreak2();

 }

 

-static const char *k_DigestTitles[] =

+static const char * const k_DigestTitles[] =

 {

-    " :"

+    " : "

   , " for data:              "

   , " for data and names:    "

   , " for streams and names: "

 };

 

-static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned digestIndex)

+static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex)

 {

+  so << h.Name;

+  

+  {

+    AString temp;

+    AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len());

+    so << temp;

+  }

+

+  so << k_DigestTitles[digestIndex];

+

   char s[k_HashCalc_DigestSize_Max * 2 + 64];

-  UString name = h.Name;

-  AddSpaces(name, 6 - (int)name.Len());

-  p << name;

-  p << k_DigestTitles[digestIndex];

   s[0] = 0;

   AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);

-  p << s;

-  p << "\n";

+  so << s << endl;

 }

 

-

-void PrintHashStat(CStdOutStream &p, const CHashBundle &hb)

+void PrintHashStat(CStdOutStream &so, const CHashBundle &hb)

 {

   FOR_VECTOR (i, hb.Hashers)

   {

     const CHasherState &h = hb.Hashers[i];

-    p << "\n";

-    PrintSum(p, h, k_HashCalc_Index_DataSum);

+    PrintSum(so, h, k_HashCalc_Index_DataSum);

     if (hb.NumFiles != 1 || hb.NumDirs != 0)

-      PrintSum(p, h, k_HashCalc_Index_NamesSum);

+      PrintSum(so, h, k_HashCalc_Index_NamesSum);

     if (hb.NumAltStreams != 0)

-      PrintSum(p, h, k_HashCalc_Index_StreamsSum);

+      PrintSum(so, h, k_HashCalc_Index_StreamsSum);

+    so << endl;

   }

 }

 

@@ -243,32 +329,39 @@
   s[0] = ':';

   s[1] = ' ';

   ConvertUInt64ToString(value, s + 2);

-  m_PercentPrinter.PrintString(name);

-  m_PercentPrinter.PrintString(s);

-  m_PercentPrinter.PrintNewLine();

+  *_so << name << s << endl;

 }

 

 HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb)

 {

-  PrintSeparatorLine(hb.Hashers);

-

-  PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);

-  m_PercentPrinter.PrintNewLine();

-  m_PercentPrinter.PrintNewLine();

+  ClosePercents2();

   

-  if (hb.NumFiles != 1 || hb.NumDirs != 0)

+  if (PrintHeaders && _so)

   {

-    if (hb.NumDirs != 0)

-      PrintProperty("Folders", hb.NumDirs);

-    PrintProperty("Files", hb.NumFiles);

+    PrintSeparatorLine(hb.Hashers);

+    

+    PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);

+    

+    *_so << endl << endl;

+    

+    if (hb.NumFiles != 1 || hb.NumDirs != 0)

+    {

+      if (hb.NumDirs != 0)

+        PrintProperty("Folders", hb.NumDirs);

+      PrintProperty("Files", hb.NumFiles);

+    }

+    

+    PrintProperty("Size", hb.FilesSize);

+    

+    if (hb.NumAltStreams != 0)

+    {

+      PrintProperty("Alternate streams", hb.NumAltStreams);

+      PrintProperty("Alternate streams size", hb.AltStreamsSize);

+    }

+    

+    *_so << endl;

+    PrintHashStat(*_so, hb);

   }

-  PrintProperty("Size", hb.FilesSize);

-  if (hb.NumAltStreams != 0)

-  {

-    PrintProperty("AltStreams", hb.NumAltStreams);

-    PrintProperty("AltStreams size", hb.AltStreamsSize);

-  }

-  PrintHashStat(*m_PercentPrinter.OutStream, hb);

-  m_PercentPrinter.PrintNewLine();

+

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h
index 0e7469d..9c12869 100644
--- a/CPP/7zip/UI/Console/HashCon.h
+++ b/CPP/7zip/UI/Console/HashCon.h
@@ -9,18 +9,40 @@
 

 class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase

 {

-  UString m_FileName;

+  UString _fileName;

+  AString _s;

+

+  void AddSpacesBeforeName()

+  {

+    _s.Add_Space();

+    _s.Add_Space();

+  }

 

   void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers);

   void PrintResultLine(UInt64 fileSize,

       const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash);

   void PrintProperty(const char *name, UInt64 value);

+

 public:

+  bool PrintNameInPercents;

+

+  bool PrintHeaders;

+  

+  bool PrintSize;

+  bool PrintName;

+

+  CHashCallbackConsole():

+      PrintNameInPercents(true),

+      PrintHeaders(false),

+      PrintSize(true),

+      PrintName(true)

+    {}

+  

   ~CHashCallbackConsole() { }

 

   INTERFACE_IHashCallbackUI(;)

 };

 

-void PrintHashStat(CStdOutStream &stdStream, const CHashBundle &hb);

+void PrintHashStat(CStdOutStream &so, const CHashBundle &hb);

 

 #endif

diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index dbbdeae..77168c9 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -23,9 +23,10 @@
 using namespace NWindows;

 using namespace NCOM;

 

+extern CStdOutStream *g_StdStream;

+extern CStdOutStream *g_ErrStream;

 

-

-static const char *kPropIdToName[] =

+static const char * const kPropIdToName[] =

 {

     "0"

   , "1"

@@ -120,6 +121,9 @@
   , "Hard Link"

   , "iNode"

   , "Stream ID"

+  , "Read-only"

+  , "Out Name"

+  , "Copy Link"

 };

 

 static const char kEmptyAttribChar = '.';

@@ -131,6 +135,8 @@
 static const char *kString_AltStreams = "alternate streams";

 static const char *kString_Streams = "streams";

 

+static const char *kError = "ERROR: ";

+

 static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)

 {

   if (isDir)

@@ -163,8 +169,8 @@
   AString NameA;

   EAdjustment TitleAdjustment;

   EAdjustment TextAdjustment;

-  int PrefixSpacesWidth;

-  int Width;

+  unsigned PrefixSpacesWidth;

+  unsigned Width;

 };

 

 struct CFieldInfoInit

@@ -173,8 +179,8 @@
   const char *Name;

   EAdjustment TitleAdjustment;

   EAdjustment TextAdjustment;

-  int PrefixSpacesWidth;

-  int Width;

+  unsigned PrefixSpacesWidth;

+  unsigned Width;

 };

 

 static const CFieldInfoInit kStandardFieldTable[] =

@@ -186,71 +192,105 @@
   { kpidPath, "Name", kLeft, kLeft, 2, 24 }

 };

 

-const int kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width

+const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width

 static const char *g_Spaces =

 "                                " ;

 

-static void PrintSpaces(int numSpaces)

+static void PrintSpaces(unsigned numSpaces)

 {

   if (numSpaces > 0 && numSpaces <= kNumSpacesMax)

     g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);

 }

 

-static void PrintSpacesToString(char *dest, int numSpaces)

+static void PrintSpacesToString(char *dest, unsigned numSpaces)

 {

-  int i;

+  unsigned i;

   for (i = 0; i < numSpaces; i++)

     dest[i] = ' ';

   dest[i] = 0;

 }

 

-static void PrintString(EAdjustment adj, int width, const UString &textString)

+// extern int g_CodePage;

+

+static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp)

 {

-  const int numSpaces = width - textString.Len();

-  int numLeftSpaces = 0;

-  switch (adj)

+  /*

+  // we don't need multibyte align.

+  int codePage = g_CodePage;

+  if (codePage == -1)

+    codePage = CP_OEMCP;

+  if (codePage == CP_UTF8)

+    ConvertUnicodeToUTF8(s, temp);

+  else

+    UnicodeStringToMultiByte2(temp, s, (UINT)codePage);

+  */

+

+  unsigned numSpaces = 0;

+

+  if (width > s.Len())

   {

-    case kLeft:   numLeftSpaces = 0; break;

-    case kCenter: numLeftSpaces = numSpaces / 2; break;

-    case kRight:  numLeftSpaces = numSpaces; break;

+    numSpaces = width - s.Len();

+    unsigned numLeftSpaces = 0;

+    switch (adj)

+    {

+      case kLeft:   numLeftSpaces = 0; break;

+      case kCenter: numLeftSpaces = numSpaces / 2; break;

+      case kRight:  numLeftSpaces = numSpaces; break;

+    }

+    PrintSpaces(numLeftSpaces);

+    numSpaces -= numLeftSpaces;

   }

-  PrintSpaces(numLeftSpaces);

-  g_StdOut << textString;

-  PrintSpaces(numSpaces - numLeftSpaces);

+  

+  g_StdOut.PrintUString(s, temp);

+  PrintSpaces(numSpaces);

 }

 

-static void PrintString(EAdjustment adj, int width, const char *textString)

+static void PrintString(EAdjustment adj, unsigned width, const char *s)

 {

-  const int numSpaces = width - (int)strlen(textString);

-  int numLeftSpaces = 0;

-  switch (adj)

+  unsigned numSpaces = 0;

+  unsigned len = (unsigned)strlen(s);

+

+  if (width > len)

   {

-    case kLeft:   numLeftSpaces = 0; break;

-    case kCenter: numLeftSpaces = numSpaces / 2; break;

-    case kRight:  numLeftSpaces = numSpaces; break;

+    numSpaces = width - len;

+    unsigned numLeftSpaces = 0;

+    switch (adj)

+    {

+      case kLeft:   numLeftSpaces = 0; break;

+      case kCenter: numLeftSpaces = numSpaces / 2; break;

+      case kRight:  numLeftSpaces = numSpaces; break;

+    }

+    PrintSpaces(numLeftSpaces);

+    numSpaces -= numLeftSpaces;

   }

-  PrintSpaces(numLeftSpaces);

-  g_StdOut << textString;

-  PrintSpaces(numSpaces - numLeftSpaces);

+  

+  g_StdOut << s;

+  PrintSpaces(numSpaces);

 }

 

-static void PrintStringToString(char *dest, EAdjustment adj, int width, const char *textString)

+static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString)

 {

-  int len = (int)strlen(textString);

-  const int numSpaces = width - len;

-  int numLeftSpaces = 0;

-  switch (adj)

+  unsigned numSpaces = 0;

+  unsigned len = (unsigned)strlen(textString);

+  

+  if (width > len)

   {

-    case kLeft:   numLeftSpaces = 0; break;

-    case kCenter: numLeftSpaces = numSpaces / 2; break;

-    case kRight:  numLeftSpaces = numSpaces; break;

-  }

-  PrintSpacesToString(dest, numLeftSpaces);

-  if (numLeftSpaces > 0)

+    numSpaces = width - len;

+    unsigned numLeftSpaces = 0;

+    switch (adj)

+    {

+      case kLeft:   numLeftSpaces = 0; break;

+      case kCenter: numLeftSpaces = numSpaces / 2; break;

+      case kRight:  numLeftSpaces = numSpaces; break;

+    }

+    PrintSpacesToString(dest, numLeftSpaces);

     dest += numLeftSpaces;

+    numSpaces -= numLeftSpaces;

+  }

+  

   memcpy(dest, textString, len);

   dest += len;

-  PrintSpacesToString(dest, numSpaces - numLeftSpaces);

+  PrintSpacesToString(dest, numSpaces);

 }

 

 struct CListUInt64Def

@@ -287,12 +327,12 @@
   UInt64 NumFiles;

 

   CListStat(): NumFiles(0) {}

-  void Update(const CListStat &stat)

+  void Update(const CListStat &st)

   {

-    Size.Add(stat.Size);

-    PackSize.Add(stat.PackSize);

-    MTime.Update(stat.MTime);

-    NumFiles += stat.NumFiles;

+    Size.Add(st.Size);

+    PackSize.Add(st.PackSize);

+    MTime.Update(st.MTime);

+    NumFiles += st.NumFiles;

   }

   void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }

 };

@@ -305,11 +345,11 @@
 

   CListStat2(): NumDirs(0) {}

 

-  void Update(const CListStat2 &stat)

+  void Update(const CListStat2 &st)

   {

-    MainFiles.Update(stat.MainFiles);

-    AltStreams.Update(stat.AltStreams);

-    NumDirs += stat.NumDirs;

+    MainFiles.Update(st.MainFiles);

+    AltStreams.Update(st.AltStreams);

+    NumDirs += st.NumDirs;

   }

   const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; }

   CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; }

@@ -319,34 +359,34 @@
 {

   CObjectVector<CFieldInfo> _fields;

 

-  void AddProp(BSTR name, PROPID propID, bool isRawProp);

+  void AddProp(const wchar_t *name, PROPID propID, bool isRawProp);

 public:

   const CArc *Arc;

   bool TechMode;

   UString FilePath;

   AString TempAString;

   UString TempWString;

-  bool IsFolder;

+  bool IsDir;

 

   AString LinesString;

 

   void Clear() { _fields.Clear(); LinesString.Empty(); }

-  void Init(const CFieldInfoInit *standardFieldTable, int numItems);

+  void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems);

 

   HRESULT AddMainProps(IInArchive *archive);

   HRESULT AddRawProps(IArchiveGetRawProps *getRawProps);

   

   void PrintTitle();

   void PrintTitleLines();

-  HRESULT PrintItemInfo(UInt32 index, const CListStat &stat);

-  void PrintSum(const CListStat &stat, UInt64 numDirs, const char *str);

-  void PrintSum(const CListStat2 &stat);

+  HRESULT PrintItemInfo(UInt32 index, const CListStat &st);

+  void PrintSum(const CListStat &st, UInt64 numDirs, const char *str);

+  void PrintSum(const CListStat2 &stat2);

 };

 

-void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)

+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems)

 {

   Clear();

-  for (int i = 0; i < numItems; i++)

+  for (unsigned i = 0; i < numItems; i++)

   {

     CFieldInfo &f = _fields.AddNew();

     const CFieldInfoInit &fii = standardFieldTable[i];

@@ -358,9 +398,9 @@
     f.PrefixSpacesWidth = fii.PrefixSpacesWidth;

     f.Width = fii.Width;

 

-    int k;

+    unsigned k;

     for (k = 0; k < fii.PrefixSpacesWidth; k++)

-      LinesString += ' ';

+      LinesString.Add_Space();

     for (k = 0; k < fii.Width; k++)

       LinesString += '-';

   }

@@ -383,13 +423,13 @@
   }

 }

 

-void CFieldPrinter::AddProp(BSTR name, PROPID propID, bool isRawProp)

+void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)

 {

   CFieldInfo f;

   f.PropID = propID;

   f.IsRawProp = isRawProp;

   GetPropName(propID, name, f.NameA, f.NameU);

-  f.NameU += L" = ";

+  f.NameU.AddAscii(" = ");

   if (!f.NameA.IsEmpty())

     f.NameA += " = ";

   else

@@ -486,9 +526,9 @@
 

 #endif

 

-#define MY_ENDL '\n'

+#define MY_ENDL endl

 

-HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)

+HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)

 {

   char temp[128];

   size_t tempPos = 0;

@@ -530,7 +570,7 @@
       continue;

     }

 

-    int width = f.Width;

+    const unsigned width = f.Width;

     

     if (f.IsRawProp)

     {

@@ -561,7 +601,7 @@
           if (ConvertNtReparseToString((const Byte *)data, dataSize, s))

           {

             needPrint = false;

-            g_StdOut << s;

+            g_StdOut.PrintUString(s, TempAString);

           }

         }

       

@@ -593,15 +633,15 @@
       CPropVariant prop;

       switch (f.PropID)

       {

-        case kpidSize: if (stat.Size.Def) prop = stat.Size.Val; break;

-        case kpidPackSize: if (stat.PackSize.Def) prop = stat.PackSize.Val; break;

-        case kpidMTime: if (stat.MTime.Def) prop = stat.MTime.Val; break;

+        case kpidSize: if (st.Size.Def) prop = st.Size.Val; break;

+        case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break;

+        case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break;

         default:

           RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop));

       }

       if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))

       {

-        GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsFolder, techMode, temp + tempPos);

+        GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos);

         if (techMode)

           g_StdOut << temp + tempPos;

         else

@@ -626,24 +666,22 @@
           tempPos += len;

           if (len < (unsigned)f.Width)

           {

-            len = (size_t)f.Width - len;

-            PrintSpacesToString(temp + tempPos, (int)len);

+            len = f.Width - len;

+            PrintSpacesToString(temp + tempPos, (unsigned)len);

             tempPos += len;

           }

         }

       }

       else if (prop.vt == VT_BSTR)

       {

+        TempWString.SetFromBstr(prop.bstrVal);

         if (techMode)

         {

-          int len = (int)wcslen(prop.bstrVal);

-          MyStringCopy(TempWString.GetBuffer(len), prop.bstrVal);

           // replace CR/LF here.

-          TempWString.ReleaseBuffer(len);

           g_StdOut.PrintUString(TempWString, TempAString);

         }

         else

-          PrintString(f.TextAdjustment, width, prop.bstrVal);

+          PrintUString(f.TextAdjustment, width, TempWString, TempAString);

       }

       else

       {

@@ -665,55 +703,48 @@
   return S_OK;

 }

 

-static void PrintNumber(EAdjustment adj, int width, const CListUInt64Def &value)

+static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value)

 {

-  wchar_t s[32];

+  char s[32];

   s[0] = 0;

   if (value.Def)

     ConvertUInt64ToString(value.Val, s);

   PrintString(adj, width, s);

 }

 

-static void PrintNumberAndString(AString &s, UInt64 value, const char *text)

-{

-  char t[32];

-  ConvertUInt64ToString(value, t);

-  s += t;

-  s += ' ';

-  s += text;

-}

+void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);

 

-void CFieldPrinter::PrintSum(const CListStat &stat, UInt64 numDirs, const char *str)

+void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str)

 {

   FOR_VECTOR (i, _fields)

   {

     const CFieldInfo &f = _fields[i];

     PrintSpaces(f.PrefixSpacesWidth);

     if (f.PropID == kpidSize)

-      PrintNumber(f.TextAdjustment, f.Width, stat.Size);

+      PrintNumber(f.TextAdjustment, f.Width, st.Size);

     else if (f.PropID == kpidPackSize)

-      PrintNumber(f.TextAdjustment, f.Width, stat.PackSize);

+      PrintNumber(f.TextAdjustment, f.Width, st.PackSize);

     else if (f.PropID == kpidMTime)

     {

       char s[64];

       s[0] = 0;

-      if (stat.MTime.Def)

-        PrintTime(s, &stat.MTime.Val);

+      if (st.MTime.Def)

+        PrintTime(s, &st.MTime.Val);

       PrintString(f.TextAdjustment, f.Width, s);

     }

     else if (f.PropID == kpidPath)

     {

       AString s;

-      PrintNumberAndString(s, stat.NumFiles, str);

+      Print_UInt64_and_String(s, st.NumFiles, str);

       if (numDirs != 0)

       {

         s += ", ";

-        PrintNumberAndString(s, numDirs, kString_Dirs);

+        Print_UInt64_and_String(s, numDirs, kString_Dirs);

       }

       PrintString(f.TextAdjustment, 0, s);

     }

     else

-      PrintString(f.TextAdjustment, f.Width, L"");

+      PrintString(f.TextAdjustment, f.Width, "");

   }

   g_StdOut << endl;

 }

@@ -724,9 +755,9 @@
   if (stat2.AltStreams.NumFiles != 0)

   {

     PrintSum(stat2.AltStreams, 0, kString_AltStreams);;

-    CListStat stat = stat2.MainFiles;

-    stat.Update(stat2.AltStreams);

-    PrintSum(stat, 0, kString_Streams);

+    CListStat st = stat2.MainFiles;

+    st.Update(stat2.AltStreams);

+    PrintSum(st, 0, kString_Streams);

   }

 }

 

@@ -757,12 +788,12 @@
   return S_OK;

 }

 

-static void PrintPropNameAndNumber(const char *name, UInt64 val)

+static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val)

 {

-  g_StdOut << name << ": " << val << endl;

+  so << name << ": " << val << endl;

 }

 

-static void PrintPropName_and_Eq(PROPID propID)

+static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID)

 {

   const char *s;

   char temp[16];

@@ -773,28 +804,28 @@
     ConvertUInt32ToString(propID, temp);

     s = temp;

   }

-  g_StdOut << s << " = ";

+  so << s << " = ";

 }

 

-static void PrintPropNameAndNumber(PROPID propID, UInt64 val)

+static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val)

 {

-  PrintPropName_and_Eq(propID);

-  g_StdOut << val << endl;

+  PrintPropName_and_Eq(so, propID);

+  so << val << endl;

 }

 

-static void PrintPropNameAndNumber_Signed(PROPID propID, Int64 val)

+static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val)

 {

-  PrintPropName_and_Eq(propID);

-  g_StdOut << val << endl;

+  PrintPropName_and_Eq(so, propID);

+  so << val << endl;

 }

 

-static void PrintPropPair(const char *name, const wchar_t *val)

+static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val)

 {

-  g_StdOut << name << " = " << val << endl;

+  so << name << " = " << val << endl;

 }

 

 

-static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVariant &prop)

+static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)

 {

   UString s;

   ConvertPropertyToString(s, prop, propID);

@@ -804,23 +835,23 @@
     UString nameU;

     GetPropName(propID, name, nameA, nameU);

     if (!nameA.IsEmpty())

-      PrintPropPair(nameA, s);

+      PrintPropPair(so, nameA, s);

     else

-      g_StdOut << nameU << " = " << s << endl;

+      so << nameU << " = " << s << endl;

   }

 }

 

-static HRESULT PrintArcProp(IInArchive *archive, PROPID propID, const wchar_t *name)

+static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name)

 {

   CPropVariant prop;

   RINOK(archive->GetArchiveProperty(propID, &prop));

-  PrintPropertyPair2(propID, name, prop);

+  PrintPropertyPair2(so, propID, name, prop);

   return S_OK;

 }

 

-static void PrintArcTypeError(const UString &type, bool isWarning)

+static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning)

 {

-  g_StdOut << "Open " << (isWarning ? "Warning" : "Error")

+  so << "Open " << (isWarning ? "WARNING" : "ERROR")

     << ": Can not open the file as ["

     << type

     << "] archive"

@@ -829,25 +860,109 @@
 

 int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);

 

-AString GetOpenArcErrorMessage(UInt32 errorFlags);

+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);

 

-static void PrintErrorFlags(const char *s, UInt32 errorFlags)

+static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)

 {

-  g_StdOut << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;

-}

-

-static void ErrorInfo_Print(const CArcErrorInfo &er)

-{

-  if (er.AreThereErrors())

-    PrintErrorFlags("Errors:", er.GetErrorFlags());

+  PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags());

   if (!er.ErrorMessage.IsEmpty())

-    PrintPropPair("Error", er.ErrorMessage);

-  if (er.AreThereWarnings())

-    PrintErrorFlags("Warnings:", er.GetWarningFlags());

+    PrintPropPair(so, "ERROR", er.ErrorMessage);

+  

+  PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags());

   if (!er.WarningMessage.IsEmpty())

-    PrintPropPair("Warning", er.WarningMessage);

+    PrintPropPair(so, "WARNING", er.WarningMessage);

 }

 

+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)

+{

+  FOR_VECTOR (r, arcLink.Arcs)

+  {

+    const CArc &arc = arcLink.Arcs[r];

+    const CArcErrorInfo &er = arc.ErrorInfo;

+    

+    so << "--\n";

+    PrintPropPair(so, "Path", arc.Path);

+    if (er.ErrorFormatIndex >= 0)

+    {

+      if (er.ErrorFormatIndex == arc.FormatIndex)

+        so << "Warning: The archive is open with offset" << endl;

+      else

+        PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);

+    }

+    PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex));

+    

+    ErrorInfo_Print(so, er);

+    

+    Int64 offset = arc.GetGlobalOffset();

+    if (offset != 0)

+      PrintPropNameAndNumber_Signed(so, kpidOffset, offset);

+    IInArchive *archive = arc.Archive;

+    RINOK(PrintArcProp(so, archive, kpidPhySize, NULL));

+    if (er.TailSize != 0)

+      PrintPropNameAndNumber(so, kpidTailSize, er.TailSize);

+    {

+      UInt32 numProps;

+      RINOK(archive->GetNumberOfArchiveProperties(&numProps));

+      

+      for (UInt32 j = 0; j < numProps; j++)

+      {

+        CMyComBSTR name;

+        PROPID propID;

+        VARTYPE vt;

+        RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));

+        RINOK(PrintArcProp(so, archive, propID, name));

+      }

+    }

+    

+    if (r != arcLink.Arcs.Size() - 1)

+    {

+      UInt32 numProps;

+      so << "----\n";

+      if (archive->GetNumberOfProperties(&numProps) == S_OK)

+      {

+        UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;

+        for (UInt32 j = 0; j < numProps; j++)

+        {

+          CMyComBSTR name;

+          PROPID propID;

+          VARTYPE vt;

+          RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));

+          CPropVariant prop;

+          RINOK(archive->GetProperty(mainIndex, propID, &prop));

+          PrintPropertyPair2(so, propID, name, prop);

+        }

+      }

+    }

+  }

+  return S_OK;

+}

+

+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)

+{

+  #ifndef _NO_CRYPTO

+  if (arcLink.PasswordWasAsked)

+    so << "Can not open encrypted archive. Wrong password?";

+  else

+  #endif

+  {

+    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+    {

+      so << arcLink.NonOpen_ArcPath << endl;

+      PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);

+    }

+    else

+      so << "Can not open the file as archive";

+  }

+

+  so << endl;

+  so << endl;

+  ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo);

+

+  return S_OK;

+}

+

+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);

+

 HRESULT ListArchives(CCodecs *codecs,

     const CObjectVector<COpenType> &types,

     const CIntVector &excludedFormats,

@@ -865,7 +980,7 @@
     UInt64 &numErrors,

     UInt64 &numWarnings)

 {

-  bool AllFilesAreAllowed = wildcardCensor.AreAllAllowed();

+  bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();

 

   numErrors = 0;

   numWarnings = 0;

@@ -874,7 +989,7 @@
   if (!techMode)

     fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable));

 

-  CListStat2 stat2;

+  CListStat2 stat2total;

   

   CBoolArr skipArcs(arcPaths.Size());

   unsigned arcIndex;

@@ -884,18 +999,34 @@
   UInt64 numArcs = 0;

   UInt64 totalArcSizes = 0;

 

+  HRESULT lastError = 0;

+

   for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)

   {

     if (skipArcs[arcIndex])

       continue;

-    const UString &archiveName = arcPaths[arcIndex];

+    const UString &arcPath = arcPaths[arcIndex];

     UInt64 arcPackSize = 0;

+    

     if (!stdInMode)

     {

       NFile::NFind::CFileInfo fi;

-      if (!fi.Find(us2fs(archiveName)) || fi.IsDir())

+      if (!fi.Find(us2fs(arcPath)))

       {

-        g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;

+        DWORD errorCode = GetLastError();

+        if (errorCode == 0)

+          errorCode = ERROR_FILE_NOT_FOUND;

+        lastError = HRESULT_FROM_WIN32(lastError);;

+        g_StdOut.Flush();

+        *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) <<

+              endl << arcPath << endl << endl;

+        numErrors++;

+        continue;

+      }

+      if (fi.IsDir())

+      {

+        g_StdOut.Flush();

+        *g_ErrStream << endl << kError << arcPath << " is not a file" << endl << endl;

         numErrors++;

         continue;

       }

@@ -906,7 +1037,7 @@
     CArchiveLink arcLink;

 

     COpenCallbackConsole openCallback;

-    openCallback.OutStream = &g_StdOut;

+    openCallback.Init(&g_StdOut, g_ErrStream, NULL);

 

     #ifndef _NO_CRYPTO

 

@@ -930,44 +1061,40 @@
     options.excludedFormats = &excludedFormats;

     options.stdInMode = stdInMode;

     options.stream = NULL;

-    options.filePath = archiveName;

-    HRESULT result = arcLink.Open2(options, &openCallback);

+    options.filePath = arcPath;

+

+    if (enableHeaders)

+    {

+      g_StdOut << endl << kListing << arcPath << endl << endl;

+    }

+    

+    HRESULT result = arcLink.Open_Strict(options, &openCallback);

 

     if (result != S_OK)

     {

       if (result == E_ABORT)

         return result;

-      g_StdOut << endl << "Error: " << archiveName << ": ";

+      g_StdOut.Flush();

+      *g_ErrStream << endl << kError << arcPath << " : ";

       if (result == S_FALSE)

       {

-        #ifndef _NO_CRYPTO

-        if (openCallback.Open_WasPasswordAsked())

-          g_StdOut << "Can not open encrypted archive. Wrong password?";

-        else

-        #endif

-        {

-          if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

-          {

-            PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);

-          }

-          else

-            g_StdOut << "Can not open the file as archive";

-        }

-        g_StdOut << endl;

-        ErrorInfo_Print(arcLink.NonOpen_ErrorInfo);

+        Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);

       }

-      else if (result == E_OUTOFMEMORY)

-        g_StdOut << "Can't allocate required memory";

       else

-        g_StdOut << NError::MyFormatMessage(result);

-      g_StdOut << endl;

+      {

+        lastError = result;

+        *g_ErrStream << "opening : ";

+        if (result == E_OUTOFMEMORY)

+          *g_ErrStream << "Can't allocate required memory";

+        else

+          *g_ErrStream << NError::MyFormatMessage(result);

+      }

+      *g_ErrStream << endl;

       numErrors++;

       continue;

     }

+    

     {

-      if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

-        numErrors++;

-      

       FOR_VECTOR (r, arcLink.Arcs)

       {

         const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo;

@@ -998,72 +1125,15 @@
       {

         int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);

         if (index >= 0 && (unsigned)index > arcIndex)

-          skipArcs[index] = true;

+          skipArcs[(unsigned)index] = true;

       }

     }

 

 

     if (enableHeaders)

     {

-      g_StdOut << endl << kListing << archiveName << endl << endl;

+      RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink));

 

-      FOR_VECTOR (r, arcLink.Arcs)

-      {

-        const CArc &arc = arcLink.Arcs[r];

-        const CArcErrorInfo &er = arc.ErrorInfo;

-        

-        g_StdOut << "--\n";

-        PrintPropPair("Path", arc.Path);

-        if (er.ErrorFormatIndex >= 0)

-        {

-          if (er.ErrorFormatIndex == arc.FormatIndex)

-            g_StdOut << "Warning: The archive is open with offset" << endl;

-          else

-            PrintArcTypeError(codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);

-        }

-        PrintPropPair("Type", codecs->GetFormatNamePtr(arc.FormatIndex));

-

-        ErrorInfo_Print(er);

-

-        Int64 offset = arc.GetGlobalOffset();

-        if (offset != 0)

-          PrintPropNameAndNumber_Signed(kpidOffset, offset);

-        IInArchive *archive = arc.Archive;

-        RINOK(PrintArcProp(archive, kpidPhySize, NULL));

-        if (er.TailSize != 0)

-          PrintPropNameAndNumber(kpidTailSize, er.TailSize);

-        UInt32 numProps;

-        RINOK(archive->GetNumberOfArchiveProperties(&numProps));

-        {

-          for (UInt32 j = 0; j < numProps; j++)

-          {

-            CMyComBSTR name;

-            PROPID propID;

-            VARTYPE vt;

-            RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));

-            RINOK(PrintArcProp(archive, propID, name));

-          }

-        }

-        if (r != arcLink.Arcs.Size() - 1)

-        {

-          UInt32 numProps;

-          g_StdOut << "----\n";

-          if (archive->GetNumberOfProperties(&numProps) == S_OK)

-          {

-            UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;

-            for (UInt32 j = 0; j < numProps; j++)

-            {

-              CMyComBSTR name;

-              PROPID propID;

-              VARTYPE vt;

-              RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));

-              CPropVariant prop;

-              RINOK(archive->GetProperty(mainIndex, propID, &prop));

-              PrintPropertyPair2(propID, name, prop);

-            }

-          }

-        }

-      }

       g_StdOut << endl;

       if (techMode)

         g_StdOut << "----------\n";

@@ -1091,10 +1161,14 @@
       }

     }

     

-    CListStat2 stat;

+    CListStat2 stat2;

     

     UInt32 numItems;

     RINOK(archive->GetNumberOfItems(&numItems));

+ 

+    CReadArcItem item;

+    UStringVector pathParts;

+    

     for (UInt32 i = 0; i < numItems; i++)

     {

       if (NConsoleClose::TestBreakSignal())

@@ -1122,12 +1196,25 @@
           continue;

       }

 

-      RINOK(Archive_IsItem_Folder(archive, i, fp.IsFolder));

+      RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir));

 

-      if (!AllFilesAreAllowed)

+      if (!allFilesAreAllowed)

       {

-        if (!wildcardCensor.CheckPath(isAltStream, fp.FilePath, !fp.IsFolder))

-          continue;

+        if (isAltStream)

+        {

+          RINOK(arc.GetItem(i, item));

+          if (!CensorNode_CheckPath(wildcardCensor, item))

+            continue;

+        }

+        else

+        {

+          SplitPathToParts(fp.FilePath, pathParts);;

+          bool include;

+          if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include))

+            continue;

+          if (!include)

+            continue;

+        }

       }

       

       CListStat st;

@@ -1136,33 +1223,35 @@
       RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize));

       RINOK(GetItemMTime(archive, i, st.MTime));

 

-      if (fp.IsFolder)

-        stat.NumDirs++;

+      if (fp.IsDir)

+        stat2.NumDirs++;

       else

         st.NumFiles = 1;

-      stat.GetStat(isAltStream).Update(st);

+      stat2.GetStat(isAltStream).Update(st);

 

       if (isAltStream && !showAltStreams)

         continue;

       RINOK(fp.PrintItemInfo(i, st));

     }

 

-    UInt64 numStreams = stat.GetNumStreams();

+    UInt64 numStreams = stat2.GetNumStreams();

     if (!stdInMode

-        && !stat.MainFiles.PackSize.Def

-        && !stat.AltStreams.PackSize.Def)

+        && !stat2.MainFiles.PackSize.Def

+        && !stat2.AltStreams.PackSize.Def)

     {

       if (arcLink.VolumePaths.Size() != 0)

         arcPackSize += arcLink.VolumesSize;

-      stat.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);

+      stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);

     }

-    stat.MainFiles.SetSizeDefIfNoFiles();

-    stat.AltStreams.SetSizeDefIfNoFiles();

+  

+    stat2.MainFiles.SetSizeDefIfNoFiles();

+    stat2.AltStreams.SetSizeDefIfNoFiles();

+    

     if (enableHeaders && !techMode)

     {

       fp.PrintTitleLines();

       g_StdOut << endl;

-      fp.PrintSum(stat);

+      fp.PrintSum(stat2);

     }

 

     if (enableHeaders)

@@ -1170,23 +1259,30 @@
       if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

       {

         g_StdOut << "----------\n";

-        PrintPropPair("Path", arcLink.NonOpen_ArcPath);

-        PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);

+        PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath);

+        PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);

       }

     }

-    stat2.Update(stat);

-    fflush(stdout);

+    

+    stat2total.Update(stat2);

+

+    g_StdOut.Flush();

   }

+  

   if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))

   {

     g_StdOut << endl;

     fp.PrintTitleLines();

     g_StdOut << endl;

-    fp.PrintSum(stat2);

+    fp.PrintSum(stat2total);

     g_StdOut << endl;

-    PrintPropNameAndNumber("Archives", numArcs);

-    PrintPropNameAndNumber("Volumes", numVolumes);

-    PrintPropNameAndNumber("Total archives size", totalArcSizes);

+    PrintPropNameAndNumber(g_StdOut, "Archives", numArcs);

+    PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes);

+    PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes);

   }

+

+  if (numErrors == 1 && lastError != 0)

+    return lastError;

+  

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index f092f36..f54e9c3 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -2,9 +2,15 @@
 

 #include "StdAfx.h"

 

-#include <Psapi.h>

+#include "../../../Common/MyWindows.h"

 

-#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)

+#ifdef _WIN32

+#include <Psapi.h>

+#endif

+

+#include "../../../../C/CpuArch.h"

+

+#if defined( _7ZIP_LARGE_PAGES)

 #include "../../../../C/Alloc.h"

 #endif

 

@@ -15,25 +21,26 @@
 #include "../../../Common/MyException.h"

 #include "../../../Common/StringConvert.h"

 #include "../../../Common/StringToInt.h"

+#include "../../../Common/UTFConvert.h"

 

 #include "../../../Windows/ErrorMsg.h"

+

 #ifdef _WIN32

 #include "../../../Windows/MemoryLock.h"

 #endif

 

-#ifndef _7ZIP_ST

-#include "../../../Windows/Synchronization.h"

-#endif

-

 #include "../../../Windows/TimeUtils.h"

 

 #include "../Common/ArchiveCommandLine.h"

 #include "../Common/ExitCode.h"

 #include "../Common/Extract.h"

+

 #ifdef EXTERNAL_CODECS

 #include "../Common/LoadCodecs.h"

 #endif

 

+#include "../../Common/RegisterCodec.h"

+

 #include "BenchCon.h"

 #include "ConsoleClose.h"

 #include "ExtractCallbackConsole.h"

@@ -56,7 +63,15 @@
 #ifdef _WIN32

 HINSTANCE g_hInstance = 0;

 #endif

+

 extern CStdOutStream *g_StdStream;

+extern CStdOutStream *g_ErrStream;

+

+extern unsigned g_NumCodecs;

+extern const CCodecInfo *g_Codecs[];

+

+extern unsigned g_NumHashers;

+extern const CHasherInfo *g_Hashers[];

 

 static const char *kCopyrightString = "\n7-Zip"

 #ifndef EXTERNAL_CODECS

@@ -67,14 +82,16 @@
 #endif

 #endif

 

-#ifdef _WIN64

+#ifdef MY_CPU_64BIT

 " [64]"

+#elif defined MY_CPU_32BIT

+" [32]"

 #endif

 

-" " MY_VERSION_COPYRIGHT_DATE "\n";

+" " MY_VERSION_COPYRIGHT_DATE "\n\n";

 

 static const char *kHelpString =

-    "\nUsage: 7z"

+    "Usage: 7z"

 #ifndef EXTERNAL_CODECS

 #ifdef PROG_VARIANT_R

     "r"

@@ -91,39 +108,59 @@
     "  d : Delete files from archive\n"

     "  e : Extract files from archive (without using directory names)\n"

     "  h : Calculate hash values for files\n"

+    "  i : Show information about supported formats\n"

     "  l : List contents of archive\n"

-//    "  l[a|t][f] : List contents of archive\n"

-//    "    a - with Additional fields\n"

-//    "    t - with all fields\n"

-//    "    f - with Full pathnames\n"

     "  rn : Rename files in archive\n"

     "  t : Test integrity of archive\n"

     "  u : Update files to archive\n"

     "  x : eXtract files with full paths\n"

+    "\n"

     "<Switches>\n"

     "  -- : Stop switches parsing\n"

     "  -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"

     "  -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"

-    "  -bd : Disable percentage indicator\n"

+    "  -ao{a|s|t|u} : set Overwrite mode\n"

+    "  -an : disable archive_name field\n"

+    "  -bb[0-3] : set output log level\n"

+    "  -bd : disable progress indicator\n"

+    "  -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"

+    "  -bt : show execution time statistics\n"

     "  -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"

     "  -m{Parameters} : set compression Method\n"

+    "    -mmt[N] : set number of CPU threads\n"

     "  -o{Directory} : set Output directory\n"

     #ifndef _NO_CRYPTO

     "  -p{Password} : set Password\n"

     #endif

     "  -r[-|0] : Recurse subdirectories\n"

+    "  -sa{a|e|s} : set Archive name mode\n"

+    "  -scc{UTF-8|WIN|DOS} : set charset for for console input/output\n"

     "  -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"

+    "  -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n"

+    "  -sdel : delete files after compression\n"

+    "  -seml[.] : send archive by email\n"

     "  -sfx[{name}] : Create SFX archive\n"

     "  -si[{name}] : read data from stdin\n"

+    "  -slp : set Large Pages mode\n"

     "  -slt : show technical information for l (List) command\n"

+    "  -snh : store hard links as links\n"

+    "  -snl : store symbolic links as links\n"

+    "  -sni : store NT security information\n"

+    "  -sns[-] : store NTFS alternate streams\n"

     "  -so : write data to stdout\n"

+    "  -spd : disable wildcard matching for file names\n"

+    "  -spe : eliminate duplication of root folder for extract command\n"

+    "  -spf : use fully qualified file paths\n"

     "  -ssc[-] : set sensitive case mode\n"

     "  -ssw : compress shared files\n"

+    "  -stl : set archive timestamp from the most recently modified file\n"

+    "  -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"

+    "  -stx{Type} : exclude archive type\n"

     "  -t{Type} : Set type of archive\n"

     "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"

     "  -v{Size}[b|k|m|g] : Create volumes\n"

     "  -w[{path}] : assign Work directory. Empty path means a temporary directory\n"

-    "  -x[r[-|0]]]{@listfile|!wildcard} : eXclude filenames\n"

+    "  -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames\n"

     "  -y : assume Yes on all queries\n";

 

 // ---------------------------

@@ -137,9 +174,10 @@
 

 static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx");

 

-static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)

+static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)

 {

-  s << endl << "Error: " << message << endl;

+  if (g_ErrStream)

+    *g_ErrStream << endl << "ERROR: " << message << endl;

   throw code;

 }

 

@@ -155,48 +193,47 @@
 }

 #endif

 

-static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)

+static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)

 {

-  s << kCopyrightString;

-  // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";

+  if (!so)

+    return;

+  *so << kCopyrightString;

+  // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl;

   if (needHelp)

-    s << kHelpString;

+    *so << kHelpString;

 }

 

-#ifdef EXTERNAL_CODECS

 

-static void PrintString(CStdOutStream &stdStream, const AString &s, int size)

+static void PrintStringRight(CStdOutStream &so, const AString &s, unsigned size)

 {

-  int len = s.Len();

-  for (int i = len; i < size; i++)

-    stdStream << ' ';

-  stdStream << s;

+  unsigned len = s.Len();

+  for (unsigned i = len; i < size; i++)

+    so << ' ';

+  so << s;

 }

 

-static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size)

+static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size)

 {

   char s[16];

   ConvertUInt32ToString(val, s);

-  PrintString(stdStream, s, size);

+  PrintStringRight(so, s, size);

 }

 

-static void PrintLibIndex(CStdOutStream &stdStream, int libIndex)

+static void PrintLibIndex(CStdOutStream &so, int libIndex)

 {

   if (libIndex >= 0)

-    PrintUInt32(stdStream, libIndex, 2);

+    PrintUInt32(so, libIndex, 2);

   else

-    stdStream << "  ";

-  stdStream << ' ';

+    so << "  ";

+  so << ' ';

 }

 

-#endif

-

-static void PrintString(CStdOutStream &stdStream, const UString &s, int size)

+static void PrintString(CStdOutStream &so, const UString &s, unsigned size)

 {

-  int len = s.Len();

-  stdStream << s;

-  for (int i = len; i < size; i++)

-    stdStream << ' ';

+  unsigned len = s.Len();

+  so << s;

+  for (unsigned i = len; i < size; i++)

+    so << ' ';

 }

 

 static inline char GetHex(unsigned val)

@@ -204,82 +241,95 @@
   return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10)));

 }

 

+static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)

+{

+  FOR_VECTOR(i, pc.Paths)

+  {

+    so << pc.Paths[i] << " : ";

+    so << NError::MyFormatMessage(pc.Codes[i]) << endl;

+  }

+  so << "----------------" << endl;

+}

+

 static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,

-    const CErrorInfo &errorInfo, CStdOutStream &stdStream)

+    const CUpdateErrorInfo &errorInfo,

+    CStdOutStream *so,

+    CStdOutStream *se,

+    bool showHeaders)

 {

   int exitCode = NExitCode::kSuccess;

   

-  if (callback.CantFindFiles.Size() > 0)

+  if (callback.ScanErrors.Paths.Size() != 0)

   {

-    stdStream << endl;

-    stdStream << "WARNINGS for files:" << endl << endl;

-    unsigned numErrors = callback.CantFindFiles.Size();

-    for (unsigned i = 0; i < numErrors; i++)

+    if (se)

     {

-      stdStream << callback.CantFindFiles[i] << " : ";

-      stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl;

+      *se << endl;

+      *se << "Scan WARNINGS for files and folders:" << endl << endl;

+      PrintWarningsPaths(callback.ScanErrors, *se);

+      *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();

+      *se << endl;

     }

-    stdStream << "----------------" << endl;

-    stdStream << "WARNING: Cannot find " << numErrors << " file";

-    if (numErrors > 1)

-      stdStream << "s";

-    stdStream << endl;

     exitCode = NExitCode::kWarning;

   }

   

-  if (result != S_OK)

+  if (result != S_OK || errorInfo.ThereIsError())

   {

-    UString message;

-    if (!errorInfo.Message.IsEmpty())

+    if (se)

     {

-      message += errorInfo.Message;

-      message += L"\n";

+      UString message;

+      if (!errorInfo.Message.IsEmpty())

+      {

+        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.FileName.IsEmpty())

-    {

-      message += fs2us(errorInfo.FileName);

-      message += L"\n";

-    }

-    if (!errorInfo.FileName2.IsEmpty())

-    {

-      message += fs2us(errorInfo.FileName2);

-      message += L"\n";

-    }

-    if (errorInfo.SystemError != 0)

-    {

-      message += NError::MyFormatMessage(errorInfo.SystemError);

-      message += L"\n";

-    }

-    if (!message.IsEmpty())

-      stdStream << L"\nError:\n" << message;

 

     // we will work with (result) later

     // throw CSystemException(result);

     return NExitCode::kFatalError;

   }

 

-  unsigned numErrors = callback.FailedFiles.Size();

+  unsigned numErrors = callback.FailedFiles.Paths.Size();

   if (numErrors == 0)

   {

-    if (callback.CantFindFiles.Size() == 0)

-      stdStream << kEverythingIsOk << endl;

+    if (showHeaders)

+      if (callback.ScanErrors.Paths.Size() == 0)

+        if (so)

+        {

+          if (se)

+            se->Flush();

+          *so << kEverythingIsOk << endl;

+        }

   }

   else

   {

-    stdStream << endl;

-    stdStream << "WARNINGS for files:" << endl << endl;

-    for (unsigned i = 0; i < numErrors; i++)

+    if (se)

     {

-      stdStream << callback.FailedFiles[i] << " : ";

-      stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl;

+      *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;

     }

-    stdStream << "----------------" << endl;

-    stdStream << "WARNING: Cannot open " << numErrors << " file";

-    if (numErrors > 1)

-      stdStream << "s";

-    stdStream << endl;

     exitCode = NExitCode::kWarning;

   }

+  

   return exitCode;

 }

 

@@ -413,9 +463,16 @@
   *g_StdStream << endl;

 }

 

+static void PrintHexId(CStdOutStream &so, UInt64 id)

+{

+  char s[32];

+  ConvertUInt64ToHex(id, s);

+  PrintStringRight(so, s, 8);

+}

+

 int Main2(

   #ifndef _WIN32

-  int numArgs, const char *args[]

+  int numArgs, char *args[]

   #endif

 )

 {

@@ -424,6 +481,7 @@
   #endif

 

   UStringVector commandStrings;

+  

   #ifdef _WIN32

   NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);

   #else

@@ -432,7 +490,7 @@
 

   if (commandStrings.Size() == 1)

   {

-    ShowCopyrightAndHelp(g_StdOut, true);

+    ShowCopyrightAndHelp(g_StdStream, true);

     return 0;

   }

 

@@ -444,15 +502,27 @@
 

   parser.Parse1(commandStrings, options);

 

+

+  if (options.Number_for_Out != k_OutStream_stdout)

+    g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL);

+

+  if (options.Number_for_Errors != k_OutStream_stderr)

+    g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL);

+

+  CStdOutStream *percentsStream = NULL;

+  if (options.Number_for_Percents != k_OutStream_disabled)

+    percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;

+  

   if (options.HelpMode)

   {

-    ShowCopyrightAndHelp(g_StdOut, true);

+    ShowCopyrightAndHelp(g_StdStream, true);

     return 0;

   }

 

   #if defined(_WIN32) && !defined(UNDER_CE)

   NSecurity::EnablePrivilege_SymLink();

   #endif

+  

   #ifdef _7ZIP_LARGE_PAGES

   if (options.LargePages)

   {

@@ -463,22 +533,38 @@
   }

   #endif

 

-  CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;

-  g_StdStream = &stdStream;

-

   if (options.EnableHeaders)

-    ShowCopyrightAndHelp(stdStream, false);

+    ShowCopyrightAndHelp(g_StdStream, false);

 

   parser.Parse2(options);

 

-  CCodecs *codecs = new CCodecs;

-  #ifdef EXTERNAL_CODECS

-  CExternalCodecs __externalCodecs;

-  __externalCodecs.GetCodecs = codecs;

-  __externalCodecs.GetHashers = codecs;

-  #else

-  CMyComPtr<IUnknown> compressCodecsInfo = codecs;

-  #endif

+  unsigned percentsNameLevel = 1;

+  if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out)

+    percentsNameLevel = 2;

+

+  unsigned consoleWidth = 80;

+

+  if (percentsStream)

+  {

+    #ifdef _WIN32

+    

+    #if !defined(UNDER_CE)

+    CONSOLE_SCREEN_BUFFER_INFO consoleInfo;

+    if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))

+      consoleWidth = consoleInfo.dwSize.X;

+    #endif

+    

+    #else

+    

+    struct winsize w;

+    if (ioctl(0, TIOCGWINSZ, &w) == )

+      consoleWidth = w.ws_col;

+    

+    #endif

+  }

+

+  CREATE_CODECS_OBJECT

+

   codecs->CaseSensitiveChange = options.CaseSensitiveChange;

   codecs->CaseSensitive = options.CaseSensitive;

   ThrowException_if_Error(codecs->Load());

@@ -489,7 +575,18 @@
         (isExtractGroupCommand

         || options.Command.CommandType == NCommandType::kList

         || options.Command.IsFromUpdateGroup()))

+  {

+    #ifdef EXTERNAL_CODECS

+    if (!codecs->MainDll_ErrorPath.IsEmpty())

+    {

+      UString s = L"Can't load module ";

+      s += fs2us(codecs->MainDll_ErrorPath);

+      throw s;

+    }

+    #endif

+    

     throw kNoFormats;

+  }

 

   CObjectVector<COpenType> types;

   if (!ParseOpenTypes(*codecs, options.ArcType, types))

@@ -511,32 +608,36 @@
   if (isExtractGroupCommand

       || options.Command.CommandType == NCommandType::kHash

       || options.Command.CommandType == NCommandType::kBenchmark)

-    ThrowException_if_Error(__externalCodecs.LoadCodecs());

+    ThrowException_if_Error(__externalCodecs.Load());

   #endif

 

   int retCode = NExitCode::kSuccess;

   HRESULT hresultMain = S_OK;

 

-  bool showStat = true;

+  // bool showStat = options.ShowTime;

+  

+  /*

   if (!options.EnableHeaders ||

       options.TechMode)

     showStat = false;

+  */

   

 

   if (options.Command.CommandType == NCommandType::kInfo)

   {

+    CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);

     unsigned i;

 

     #ifdef EXTERNAL_CODECS

-    stdStream << endl << "Libs:" << endl;

+    so << endl << "Libs:" << endl;

     for (i = 0; i < codecs->Libs.Size(); i++)

     {

-      PrintLibIndex(stdStream, i);

-      stdStream << ' ' << codecs->Libs[i].Path << endl;

+      PrintLibIndex(so, i);

+      so << ' ' << codecs->Libs[i].Path << endl;

     }

     #endif

 

-    stdStream << endl << "Formats:" << endl;

+    so << endl << "Formats:" << endl;

     

     const char *kArcFlags = "KSNFMGOPBELH";

     const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);

@@ -544,26 +645,30 @@
     for (i = 0; i < codecs->Formats.Size(); i++)

     {

       const CArcInfoEx &arc = codecs->Formats[i];

+

       #ifdef EXTERNAL_CODECS

-      PrintLibIndex(stdStream, arc.LibIndex);

+      PrintLibIndex(so, arc.LibIndex);

       #else

-      stdStream << "  ";

+      so << "  ";

       #endif

-      stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');

+

+      so << (char)(arc.UpdateEnabled ? 'C' : ' ');

+      

       for (unsigned b = 0; b < kNumArcFlags; b++)

       {

-        stdStream << (char)

+        so << (char)

           ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' ');

       }

         

-      stdStream << ' ';

-      PrintString(stdStream, arc.Name, 8);

-      stdStream << ' ';

+      so << ' ';

+      PrintString(so, arc.Name, 8);

+      so << ' ';

       UString s;

+      

       FOR_VECTOR (t, arc.Exts)

       {

         if (t != 0)

-          s += L' ';

+          s.Add_Space();

         const CArcExtInfo &ext = arc.Exts[t];

         s += ext.Ext;

         if (!ext.AddExt.IsEmpty())

@@ -573,68 +678,112 @@
           s += L')';

         }

       }

-      PrintString(stdStream, s, 13);

-      stdStream << ' ';

+      

+      PrintString(so, s, 13);

+      so << ' ';

+      

       if (arc.SignatureOffset != 0)

-        stdStream << "offset=" << arc.SignatureOffset << ' ';

+        so << "offset=" << arc.SignatureOffset << ' ';

 

       FOR_VECTOR(si, arc.Signatures)

       {

         if (si != 0)

-          stdStream << "  ||  ";

+          so << "  ||  ";

 

         const CByteBuffer &sig = arc.Signatures[si];

         

         for (size_t j = 0; j < sig.Size(); j++)

         {

           if (j != 0)

-            stdStream << ' ';

+            so << ' ';

           Byte b = sig[j];

           if (b > 0x20 && b < 0x80)

           {

-            stdStream << (char)b;

+            so << (char)b;

           }

           else

           {

-            stdStream << GetHex((b >> 4) & 0xF);

-            stdStream << GetHex(b & 0xF);

+            so << GetHex((b >> 4) & 0xF);

+            so << GetHex(b & 0xF);

           }

         }

       }

-      stdStream << endl;

+      so << endl;

     }

 

+    so << endl << "Codecs:" << endl; //  << "Lib          ID Name" << endl;

+

+    for (i = 0; i < g_NumCodecs; i++)

+    {

+      const CCodecInfo &cod = *g_Codecs[i];

+

+      PrintLibIndex(so, -1);

+

+      if (cod.NumStreams == 1)

+        so << ' ';

+      else

+        so << cod.NumStreams;

+      

+      so << (char)(cod.CreateEncoder ? 'E' : ' ');

+      so << (char)(cod.CreateDecoder ? 'D' : ' ');

+

+      so << ' ';

+      PrintHexId(so, cod.Id);

+      so << ' ' << cod.Name << endl;

+    }

+

+

     #ifdef EXTERNAL_CODECS

 

-    stdStream << endl << "Codecs:" << endl << "Lib         ID  Name" << endl;

     UInt32 numMethods;

-    if (codecs->GetNumberOfMethods(&numMethods) == S_OK)

+    if (codecs->GetNumMethods(&numMethods) == S_OK)

     for (UInt32 j = 0; j < numMethods; j++)

     {

-      PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j));

-      stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');

+      PrintLibIndex(so, codecs->GetCodec_LibIndex(j));

+

+      UInt32 numStreams = codecs->GetCodec_NumStreams(j);

+      if (numStreams == 1)

+        so << ' ';

+      else

+        so << numStreams;

+      

+      so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' ');

+      so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' ');

+

+      so << ' ';

       UInt64 id;

-      stdStream << "  ";

-      HRESULT res = codecs->GetCodecId(j, id);

+      HRESULT res = codecs->GetCodec_Id(j, id);

       if (res != S_OK)

         id = (UInt64)(Int64)-1;

-      char s[32];

-      ConvertUInt64ToHex(id, s);

-      PrintString(stdStream, s, 8);

-      stdStream << "  " << codecs->GetCodecName(j) << endl;

+      PrintHexId(so, id);

+      so << ' ' << codecs->GetCodec_Name(j) << endl;

     }

+

+    #endif

     

-    stdStream << endl << "Hashers:" << endl << " L Size     ID  Name" << endl;

+

+    so << endl << "Hashers:" << endl; //  << " L Size       ID Name" << endl;

+

+    for (i = 0; i < g_NumHashers; i++)

+    {

+      const CHasherInfo &codec = *g_Hashers[i];

+      PrintLibIndex(so, -1);

+      PrintUInt32(so, codec.DigestSize, 4);

+      so << ' ';

+      PrintHexId(so, codec.Id);

+      so << ' ' << codec.Name << endl;

+    }

+

+    #ifdef EXTERNAL_CODECS

+    

     numMethods = codecs->GetNumHashers();

     for (UInt32 j = 0; j < numMethods; j++)

     {

-      PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j));

-      PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4);

-      stdStream << ' ';

-      char s[32];

-      ConvertUInt64ToHex(codecs->GetHasherId(j), s);

-      PrintString(stdStream, s, 6);

-      stdStream << "  " << codecs->GetHasherName(j) << endl;

+      PrintLibIndex(so, codecs->GetHasherLibIndex(j));

+      PrintUInt32(so, codecs->GetHasherDigestSize(j), 4);

+      so << ' ';

+      PrintHexId(so, codecs->GetHasherId(j));

+      so << ' ' << codecs->GetHasherName(j) << endl;

     }

 

     #endif

@@ -642,41 +791,103 @@
   }

   else if (options.Command.CommandType == NCommandType::kBenchmark)

   {

-    hresultMain = BenchCon(EXTERNAL_CODECS_VARS

-        options.Properties, options.NumIterations, (FILE *)stdStream);

+    CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);

+    hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L

+        options.Properties, options.NumIterations, (FILE *)so);

     if (hresultMain == S_FALSE)

     {

-      stdStream << "\nDecoding Error\n";

+      if (g_ErrStream)

+        *g_ErrStream << "\nDecoding ERROR\n";

       retCode = NExitCode::kFatalError;

       hresultMain = S_OK;

     }

   }

   else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)

   {

+    UStringVector ArchivePathsSorted;

+    UStringVector ArchivePathsFullSorted;

+

+    if (options.StdInMode)

+    {

+      ArchivePathsSorted.Add(options.ArcName_for_StdInMode);

+      ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode);

+    }

+    else

+    {

+      CExtractScanConsole scan;

+      

+      scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream);

+      scan.SetWindowWidth(consoleWidth);

+

+      if (g_StdStream && options.EnableHeaders)

+        *g_StdStream << "Scanning the drive for archives:" << endl;

+

+      CDirItemsStat st;

+

+      scan.StartScanning();

+

+      hresultMain = EnumerateDirItemsAndSort(

+          options.arcCensor,

+          NWildcard::k_RelatPath,

+          UString(), // addPathPrefix

+          ArchivePathsSorted,

+          ArchivePathsFullSorted,

+          st,

+          &scan);

+

+      scan.CloseScanning();

+

+      if (hresultMain == S_OK)

+      {

+        if (options.EnableHeaders)

+          scan.PrintStat(st);

+      }

+      else

+      {

+        /*

+        if (res != E_ABORT)

+        {

+          throw CSystemException(res);

+          // errorInfo.Message = "Scanning error";

+        }

+        return res;

+        */

+      }

+    }

+

+    if (hresultMain == S_OK)

     if (isExtractGroupCommand)

     {

       CExtractCallbackConsole *ecs = new CExtractCallbackConsole;

       CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

 

-      ecs->OutStream = &stdStream;

-

       #ifndef _NO_CRYPTO

       ecs->PasswordIsDefined = options.PasswordEnabled;

       ecs->Password = options.Password;

       #endif

 

-      ecs->Init();

+      ecs->Init(g_StdStream, g_ErrStream, percentsStream);

+      ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);

 

+      ecs->LogLevel = options.LogLevel;

+      ecs->PercentsNameLevel = percentsNameLevel;

+      

+      if (percentsStream)

+        ecs->SetWindowWidth(consoleWidth);

+

+      /*

       COpenCallbackConsole openCallback;

-      openCallback.OutStream = &stdStream;

+      openCallback.Init(g_StdStream, g_ErrStream);

 

       #ifndef _NO_CRYPTO

       openCallback.PasswordIsDefined = options.PasswordEnabled;

       openCallback.Password = options.Password;

       #endif

+      */

 

       CExtractOptions eo;

       (CExtractOptionsBase &)eo = options.ExtractOptions;

+      

       eo.StdInMode = options.StdInMode;

       eo.StdOutMode = options.StdOutMode;

       eo.YesToAll = options.YesToAll;

@@ -694,90 +905,115 @@
       if (!options.HashMethods.IsEmpty())

       {

         hashCalc = &hb;

-        ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods));

+        ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));

         hb.Init();

       }

+      

       hresultMain = Extract(

           codecs,

           types,

           excludedFormats,

-          options.ArchivePathsSorted,

-          options.ArchivePathsFullSorted,

+          ArchivePathsSorted,

+          ArchivePathsFullSorted,

           options.Censor.Pairs.Front().Head,

-          eo, &openCallback, ecs, hashCalc, errorMessage, stat);

+          eo, ecs, ecs, hashCalc, errorMessage, stat);

+      

+      ecs->ClosePercents();

+

       if (!errorMessage.IsEmpty())

       {

-        stdStream << endl << "Error: " << errorMessage;

+        if (g_ErrStream)

+          *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl;

         if (hresultMain == S_OK)

           hresultMain = E_FAIL;

       }

 

-      stdStream << endl;

+      CStdOutStream *so = g_StdStream;

 

-      if (ecs->NumTryArcs > 1)

-      {

-        stdStream << "Archives: " << ecs->NumTryArcs << endl;

-        stdStream << "OK archives: " << ecs->NumOkArcs << endl;

-      }

       bool isError = false;

+

+      if (so)

+      {

+        *so << endl;

+        

+        if (ecs->NumTryArcs > 1)

+        {

+          *so << "Archives: " << ecs->NumTryArcs << endl;

+          *so << "OK archives: " << ecs->NumOkArcs << endl;

+        }

+      }

+

       if (ecs->NumCantOpenArcs != 0)

       {

         isError = true;

-        stdStream << "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;

-        stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl;

+        if (so)

+          *so << "Archives with Errors: " << ecs->NumArcsWithError << endl;

       }

-      if (ecs->NumArcsWithWarnings != 0)

-        stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;

       

-      if (ecs->NumOpenArcWarnings != 0)

+      if (so)

       {

-        stdStream << endl;

+        if (ecs->NumArcsWithWarnings != 0)

+          *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;

+        

         if (ecs->NumOpenArcWarnings != 0)

-          stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl;

+        {

+          *so << endl;

+          if (ecs->NumOpenArcWarnings != 0)

+            *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;

+        }

       }

       

       if (ecs->NumOpenArcErrors != 0)

       {

         isError = true;

-        stdStream << endl;

-        if (ecs->NumOpenArcErrors != 0)

-          stdStream << "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)

         {

-          stdStream << endl;

+          *so << endl;

           if (ecs->NumFileErrors != 0)

-            stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;

+            *so << "Sub items Errors: " << ecs->NumFileErrors << endl;

         }

       }

       else if (hresultMain == S_OK)

       {

-     

-      if (stat.NumFolders != 0)

-        stdStream << "Folders: " << stat.NumFolders << endl;

-      if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)

-        stdStream << "Files: " << stat.NumFiles << endl;

-      if (stat.NumAltStreams != 0)

-      {

-        stdStream << "Alternate Streams: " << stat.NumAltStreams << endl;

-        stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;

-      }

-

-      stdStream

-           << "Size:       " << stat.UnpackSize << endl

-           << "Compressed: " << stat.PackSize << endl;

-      if (hashCalc)

-        PrintHashStat(stdStream, hb);

+        if (stat.NumFolders != 0)

+          *so << "Folders: " << stat.NumFolders << endl;

+        if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)

+          *so << "Files: " << stat.NumFiles << endl;

+        if (stat.NumAltStreams != 0)

+        {

+          *so << "Alternate Streams: " << stat.NumAltStreams << endl;

+          *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;

+        }

+        

+        *so

+          << "Size:       " << stat.UnpackSize << endl

+          << "Compressed: " << stat.PackSize << endl;

+        if (hashCalc)

+        {

+          *so << endl;

+          PrintHashStat(*so, hb);

+        }

       }

     }

     else

@@ -792,8 +1028,8 @@
           types,

           excludedFormats,

           options.StdInMode,

-          options.ArchivePathsSorted,

-          options.ArchivePathsFullSorted,

+          ArchivePathsSorted,

+          ArchivePathsFullSorted,

           options.ExtractOptions.NtOptions.AltStreams.Val,

           options.AltStreams.Val, // we don't want to show AltStreams by default

           options.Censor.Pairs.Front().Head,

@@ -806,9 +1042,10 @@
           &options.Properties,

           numErrors, numWarnings);

 

-        if (options.EnableHeaders)

-          if (numWarnings > 0)

-            g_StdOut << endl << "Warnings: " << numWarnings << endl;

+      if (options.EnableHeaders)

+        if (numWarnings > 0)

+          g_StdOut << endl << "Warnings: " << numWarnings << endl;

+      

       if (numErrors > 0)

       {

         if (options.EnableHeaders)

@@ -824,25 +1061,32 @@
       uo.SfxModule = kDefaultSfxModule;

 

     COpenCallbackConsole openCallback;

-    openCallback.OutStream = &stdStream;

+    openCallback.Init(g_StdStream, g_ErrStream, percentsStream);

 

     #ifndef _NO_CRYPTO

     bool passwordIsDefined =

-        options.PasswordEnabled && !options.Password.IsEmpty();

+        (options.PasswordEnabled && !options.Password.IsEmpty());

     openCallback.PasswordIsDefined = passwordIsDefined;

     openCallback.Password = options.Password;

     #endif

 

     CUpdateCallbackConsole callback;

-    callback.EnablePercents = options.EnablePercents;

+    callback.LogLevel = options.LogLevel;

+    callback.PercentsNameLevel = percentsNameLevel;

+

+    if (percentsStream)

+      callback.SetWindowWidth(consoleWidth);

 

     #ifndef _NO_CRYPTO

     callback.PasswordIsDefined = passwordIsDefined;

-    callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();

+    callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty());

     callback.Password = options.Password;

     #endif

+

     callback.StdOutMode = uo.StdOutMode;

-    callback.Init(&stdStream);

+    callback.Init(

+      // NULL,

+      g_StdStream, g_ErrStream, percentsStream);

 

     CUpdateErrorInfo errorInfo;

 

@@ -856,29 +1100,44 @@
         options.Censor,

         uo,

         errorInfo, &openCallback, &callback, true);

-    retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);

+

+    callback.ClosePercents2();

+

+    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)

   {

     const CHashOptions &uo = options.HashOptions;

 

     CHashCallbackConsole callback;

-    callback.EnablePercents = options.EnablePercents;

+    if (percentsStream)

+      callback.SetWindowWidth(consoleWidth);

+  

+    callback.Init(g_StdStream, g_ErrStream, percentsStream);

+    callback.PrintHeaders = options.EnableHeaders;

 

-    callback.Init(&stdStream);

-

-    UString errorInfoString;

-    hresultMain = HashCalc(EXTERNAL_CODECS_VARS

+    AString errorInfoString;

+    hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L

         options.Censor, uo,

         errorInfoString, &callback);

-    CErrorInfo errorInfo;

+    CUpdateErrorInfo errorInfo;

     errorInfo.Message = errorInfoString;

-    retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);

+    CStdOutStream *se = g_StdStream;

+    if (!se)

+      se = g_ErrStream;

+    retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);

   }

   else

-    ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError);

+    ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);

 

-  if (showStat)

+  if (options.ShowTime && g_StdStream)

     PrintStat();

 

   ThrowException_if_Error(hresultMain);

diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
index 0e5cebc..311c575 100644
--- a/CPP/7zip/UI/Console/MainAr.cpp
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -15,36 +15,52 @@
 

 using namespace NWindows;

 

-CStdOutStream *g_StdStream = 0;

+CStdOutStream *g_StdStream = NULL;

+CStdOutStream *g_ErrStream = NULL;

 

 extern int Main2(

   #ifndef _WIN32

-  int numArgs, const char *args[]

+  int numArgs, char *args[]

   #endif

 );

 

-static const char *kException_CmdLine_Error_Message = "\n\nCommand Line Error:\n";

-static const char *kExceptionErrorMessage = "\n\nError:\n";

-static const char *kUserBreak  = "\nBreak signaled\n";

-static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";

-static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";

+static const char *kException_CmdLine_Error_Message = "Command Line Error:";

+static const char *kExceptionErrorMessage = "ERROR:";

+static const char *kUserBreakMessage  = "Break signaled";

+static const char *kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";

+static const char *kUnknownExceptionMessage = "Unknown Error";

 static const char *kInternalExceptionMessage = "\n\nInternal Error #";

 

-#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError;

+static void FlushStreams()

+{

+  if (g_StdStream)

+    g_StdStream->Flush();

+}

+

+static void PrintError(const char *message)

+{

+  FlushStreams();

+  if (g_ErrStream)

+    *g_ErrStream << "\n\n" << message << endl;

+}

+

+#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError;

 

 int MY_CDECL main

 (

   #ifndef _WIN32

-  int numArgs, const char *args[]

+  int numArgs, char *args[]

   #endif

 )

 {

+  g_ErrStream = &g_StdErr;

   g_StdStream = &g_StdOut;

 

   NT_CHECK

 

   NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;

   int res = 0;

+  

   try

   {

     res = Main2(

@@ -55,71 +71,97 @@
   }

   catch(const CNewException &)

   {

-    (*g_StdStream) << kMemoryExceptionMessage;

+    PrintError(kMemoryExceptionMessage);

     return (NExitCode::kMemoryError);

   }

   catch(const NConsoleClose::CCtrlBreakException &)

   {

-    (*g_StdStream) << endl << kUserBreak;

+    PrintError(kUserBreakMessage);

     return (NExitCode::kUserBreak);

   }

   catch(const CArcCmdLineException &e)

   {

-    (*g_StdStream) << kException_CmdLine_Error_Message << e << endl;

+    PrintError(kException_CmdLine_Error_Message);

+    if (g_ErrStream)

+      *g_ErrStream << e << endl;

     return (NExitCode::kUserError);

   }

   catch(const CSystemException &systemError)

   {

     if (systemError.ErrorCode == E_OUTOFMEMORY)

     {

-      (*g_StdStream) << kMemoryExceptionMessage;

+      PrintError(kMemoryExceptionMessage);

       return (NExitCode::kMemoryError);

     }

     if (systemError.ErrorCode == E_ABORT)

     {

-      (*g_StdStream) << endl << kUserBreak;

+      PrintError(kUserBreakMessage);

       return (NExitCode::kUserBreak);

     }

-    (*g_StdStream) << endl << endl << "System error:" << endl <<

-        NError::MyFormatMessage(systemError.ErrorCode) << endl;

+    if (g_ErrStream)

+    {

+      PrintError("System ERROR:");

+      *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;

+    }

     return (NExitCode::kFatalError);

   }

   catch(NExitCode::EEnum &exitCode)

   {

-    (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;

+    FlushStreams();

+    if (g_ErrStream)

+      *g_ErrStream << kInternalExceptionMessage << exitCode << endl;

     return (exitCode);

   }

-  /*

-  catch(const NExitCode::CMultipleErrors &multipleErrors)

-  {

-    (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;

-    return (NExitCode::kFatalError);

-  }

-  */

   catch(const UString &s)

   {

-    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    if (g_ErrStream)

+    {

+      PrintError(kExceptionErrorMessage);

+      *g_ErrStream << s << endl;

+    }

     return (NExitCode::kFatalError);

   }

   catch(const AString &s)

   {

-    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    if (g_ErrStream)

+    {

+      PrintError(kExceptionErrorMessage);

+      *g_ErrStream << s << endl;

+    }

     return (NExitCode::kFatalError);

   }

   catch(const char *s)

   {

-    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    if (g_ErrStream)

+    {

+      PrintError(kExceptionErrorMessage);

+      *g_ErrStream << s << endl;

+    }

+    return (NExitCode::kFatalError);

+  }

+  catch(const wchar_t *s)

+  {

+    if (g_ErrStream)

+    {

+      PrintError(kExceptionErrorMessage);

+      *g_ErrStream << s << endl;

+    }

     return (NExitCode::kFatalError);

   }

   catch(int t)

   {

-    (*g_StdStream) << kInternalExceptionMessage << t << endl;

-    return (NExitCode::kFatalError);

+    if (g_ErrStream)

+    {

+      FlushStreams();

+      *g_ErrStream << kInternalExceptionMessage << t << endl;

+      return (NExitCode::kFatalError);

+    }

   }

   catch(...)

   {

-    (*g_StdStream) << kUnknownExceptionMessage;

+    PrintError(kUnknownExceptionMessage);

     return (NExitCode::kFatalError);

   }

+

   return res;

 }

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
index 6552d5d..f1a1688 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -7,37 +7,89 @@
 #include "ConsoleClose.h"

 #include "UserInputUtils.h"

 

+static HRESULT CheckBreak2()

+{

+  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;

+}

+

 HRESULT COpenCallbackConsole::Open_CheckBreak()

 {

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

+  return CheckBreak2();

+}

+

+HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)

+{

+  if (!MultiArcMode && NeedPercents())

+  {

+    if (files)

+    {

+      _totalFilesDefined = true;

+      // _totalFiles = *files;

+      _percent.Total = *files;

+    }

+    else

+      _totalFilesDefined = false;

+

+    if (bytes)

+    {

+      _totalBytesDefined = true;

+      // _totalBytes = *bytes;

+      if (!files)

+        _percent.Total = *bytes;

+    }

+    else

+      _totalBytesDefined = false;

+  }

+

+  return CheckBreak2();

+}

+

+HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)

+{

+  if (!MultiArcMode && NeedPercents())

+  {

+    if (files)

+    {

+      _percent.Files = *files;

+      if (_totalFilesDefined)

+        _percent.Completed = *files;

+    }

+

+    if (bytes)

+    {

+      if (!_totalFilesDefined)

+        _percent.Completed = *bytes;

+    }

+    _percent.Print();

+  }

+

+  return CheckBreak2();

+}

+

+HRESULT COpenCallbackConsole::Open_Finished()

+{

+  ClosePercents();

   return S_OK;

 }

 

-HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *)

-{

-  return Open_CheckBreak();

-}

 

-HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *)

-{

-  return Open_CheckBreak();

-}

- 

 #ifndef _NO_CRYPTO

 

 HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)

 {

-  PasswordWasAsked = true;

-  RINOK(Open_CheckBreak());

+  *password = NULL;

+  RINOK(CheckBreak2());

+

   if (!PasswordIsDefined)

   {

-    Password = GetPassword(OutStream);

+    ClosePercents();

+    Password = GetPassword(_so);

     PasswordIsDefined = true;

   }

   return StringToBstr(Password, password);

 }

 

+/*

 HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)

 {

   passwordIsDefined = PasswordIsDefined;

@@ -50,9 +102,10 @@
   return PasswordWasAsked;

 }

 

-void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag()

+void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()

 {

   PasswordWasAsked = false;

 }

+*/

 

 #endif

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
index 25d3f72..fd07b98 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.h
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -7,18 +7,58 @@
 

 #include "../Common/ArchiveOpenCallback.h"

 

+#include "PercentPrinter.h"

+

 class COpenCallbackConsole: public IOpenCallbackUI

 {

+protected:

+  CPercentPrinter _percent;

+

+  CStdOutStream *_so;

+  CStdOutStream *_se;

+

+  bool _totalFilesDefined;

+  bool _totalBytesDefined;

+  // UInt64 _totalFiles;

+  // UInt64 _totalBytes;

+

+  bool NeedPercents() const { return _percent._so != NULL; }

+

 public:

+

+  bool MultiArcMode;

+

+  void ClosePercents()

+  {

+    if (NeedPercents())

+      _percent.ClosePrint(true);

+  }

+

+  COpenCallbackConsole():

+      _totalFilesDefined(false),

+      _totalBytesDefined(false),

+      MultiArcMode(false)

+      

+      #ifndef _NO_CRYPTO

+      , PasswordIsDefined(false)

+      // , PasswordWasAsked(false)

+      #endif

+      

+      {}

+  

+  void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)

+  {

+    _so = outStream;

+    _se = errorStream;

+    _percent._so = percentStream;

+  }

+

   INTERFACE_IOpenCallbackUI(;)

   

-  CStdOutStream *OutStream;

-

   #ifndef _NO_CRYPTO

   bool PasswordIsDefined;

-  bool PasswordWasAsked;

+  // bool PasswordWasAsked;

   UString Password;

-  COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}

   #endif

 };

 

diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
index edf88b9..f94d827 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -2,101 +2,180 @@
 

 #include "StdAfx.h"

 

-#include "../../../Common/Defs.h"

 #include "../../../Common/IntToString.h"

 

 #include "PercentPrinter.h"

 

-static const unsigned kPaddingSize = 2;

 static const unsigned kPercentsSize = 4;

-static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;

 

-static void ClearPrev(char *p, unsigned num)

+CPercentPrinter::~CPercentPrinter()

 {

+  ClosePrint(false);

+}

+

+void CPercentPrinterState::ClearCurState()

+{

+  Completed = 0;

+  Total = ((UInt64)(Int64)-1);

+  Files = 0;

+  Command.Empty();

+  FileName.Empty();

+}

+

+void CPercentPrinter::ClosePrint(bool needFlush)

+{

+  unsigned num = _printedString.Len();

+  if (num != 0)

+  {

+

   unsigned i;

-  for (i = 0; i < num; i++) *p++ = '\b';

-  for (i = 0; i < num; i++) *p++ = ' ';

-  for (i = 0; i < num; i++) *p++ = '\b';

-  *p = '\0';

+    

+  /* '\r' in old MAC OS means "new line".

+     So we can't use '\r' in some systems */

+    

+  #ifdef _WIN32

+    char *start = _temp.GetBuf(num  + 2);

+    char *p = start;

+    *p++ = '\r';

+    for (i = 0; i < num; i++) *p++ = ' ';

+    *p++ = '\r';

+  #else

+    char *start = _temp.GetBuf(num * 3);

+    char *p = start;

+    for (i = 0; i < num; i++) *p++ = '\b';

+    for (i = 0; i < num; i++) *p++ = ' ';

+    for (i = 0; i < num; i++) *p++ = '\b';

+  #endif

+    

+  *p = 0;

+  _temp.ReleaseBuf_SetLen((unsigned)(p - start));

+  *_so << _temp;

+  }

+  if (needFlush)

+    _so->Flush();

+  _printedString.Empty();

 }

 

-void CPercentPrinter::ClosePrint()

-{

-  if (m_NumExtraChars == 0)

-    return;

-  char s[kMaxExtraSize * 3 + 1];

-  ClearPrev(s, m_NumExtraChars);

-  (*OutStream) << s;

-  m_NumExtraChars = 0;

-}

-

-void CPercentPrinter::PrintString(const char *s)

-{

-  ClosePrint();

-  (*OutStream) << s;

-}

-

-void CPercentPrinter::PrintString(const wchar_t *s)

-{

-  ClosePrint();

-  (*OutStream) << s;

-}

-

-void CPercentPrinter::PrintNewLine()

-{

-  ClosePrint();

-  (*OutStream) << "\n";

-}

-

-void CPercentPrinter::RePrintRatio()

+void CPercentPrinter::GetPercents()

 {

   char s[32];

   unsigned size;

   {

     char c = '%';

-    UInt64 value = 0;

-    if (m_Total == (UInt64)(Int64)-1)

+    UInt64 val = 0;

+    if (Total == (UInt64)(Int64)-1)

     {

-      value = m_CurValue >> 20;

+      val = Completed >> 20;

       c = 'M';

     }

-    else if (m_Total != 0)

-      value = m_CurValue * 100 / m_Total;

-    ConvertUInt64ToString(value, s);

+    else if (Total != 0)

+      val = Completed * 100 / Total;

+    ConvertUInt64ToString(val, s);

     size = (unsigned)strlen(s);

     s[size++] = c;

-    s[size] = '\0';

+    s[size] = 0;

   }

 

-  unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize);

-  if (extraSize < m_NumExtraChars)

-    extraSize = m_NumExtraChars;

-

-  char fullString[kMaxExtraSize * 3];

-  char *p = fullString;

-  unsigned i;

-  if (m_NumExtraChars == 0)

+  while (size < kPercentsSize)

   {

-    for (i = 0; i < extraSize; i++)

-      *p++ = ' ';

-    m_NumExtraChars = extraSize;

+    _s += ' ';

+    size++;

   }

 

-  for (i = 0; i < m_NumExtraChars; i++)

-    *p++ = '\b';

-  m_NumExtraChars = extraSize;

-  for (; size < extraSize; size++)

-    *p++ = ' ';

-  MyStringCopy(p, s);

-  (*OutStream) << fullString;

-  OutStream->Flush();

-  m_PrevValue = m_CurValue;

+  _s += s;

 }

 

-void CPercentPrinter::PrintRatio()

+void CPercentPrinter::Print()

 {

-  if (m_CurValue < m_PrevValue + m_MinStepSize &&

-      m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)

+  DWORD tick = 0;

+  if (_tickStep != 0)

+    tick = GetTickCount();

+

+  bool onlyPercentsChanged = false;

+

+  if (!_printedString.IsEmpty())

+  {

+    if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)

+      return;

+    

+    CPercentPrinterState &st = *this;

+    if (_printedState.Command == st.Command

+        && _printedState.FileName == st.FileName

+        && _printedState.Files == st.Files)

+    {

+      if (_printedState.Total == st.Total

+          && _printedState.Completed == st.Completed)

+        return;

+      onlyPercentsChanged = true;

+    }

+  }

+

+  _s.Empty();

+

+  GetPercents();

+  

+  if (onlyPercentsChanged && _s == _printedPercents)

     return;

-  RePrintRatio();

+

+  _printedPercents = _s;

+

+  if (Files != 0)

+  {

+    char s[32];

+    ConvertUInt64ToString(Files, s);

+    // unsigned size = (unsigned)strlen(s);

+    // for (; size < 3; size++) _s += ' ';

+    _s += ' ';

+    _s += s;

+    // _s += "f";

+  }

+

+

+  if (!Command.IsEmpty())

+  {

+    _s += ' ';

+    _s += Command;

+  }

+

+  if (!FileName.IsEmpty() && _s.Len() < MaxLen)

+  {

+    _s += ' ';

+

+    StdOut_Convert_UString_to_AString(FileName, _temp);

+    _temp.Replace('\n', ' ');

+    if (_s.Len() + _temp.Len() > MaxLen)

+    {

+      unsigned len = FileName.Len();

+      for (; len != 0;)

+      {

+        unsigned delta = len / 8;

+        if (delta == 0)

+          delta = 1;

+        len -= delta;

+        _tempU = FileName;

+        _tempU.Delete(len / 2, FileName.Len() - len);

+        _tempU.Insert(len / 2, L" . ");

+        StdOut_Convert_UString_to_AString(_tempU, _temp);

+        if (_s.Len() + _temp.Len() <= MaxLen)

+          break;

+      }

+      if (len == 0)

+        _temp.Empty();

+    }

+    _s += _temp;

+  }

+  

+  if (_printedString != _s)

+  {

+    ClosePrint(false);

+    *_so << _s;

+    if (NeedFlush)

+      _so->Flush();

+    _printedString = _s;

+  }

+

+  _printedState = *this;

+

+  if (_tickStep != 0)

+    _prevTick = tick;

 }

diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
index b6b357a..90b4083 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/CPP/7zip/UI/Console/PercentPrinter.h
@@ -5,26 +5,58 @@
 

 #include "../../../Common/StdOutStream.h"

 

-class CPercentPrinter

+struct CPercentPrinterState

 {

-  UInt64 m_MinStepSize;

-  UInt64 m_PrevValue;

-  UInt64 m_CurValue;

-  UInt64 m_Total;

-  unsigned m_NumExtraChars;

-public:

-  CStdOutStream *OutStream;

+  UInt64 Completed;

+  UInt64 Total;

+  

+  UInt64 Files;

 

-  CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),

-      m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {}

-  void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }

-  void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }

-  void PrintString(const char *s);

-  void PrintString(const wchar_t *s);

-  void PrintNewLine();

-  void ClosePrint();

-  void RePrintRatio();

-  void PrintRatio();

+  AString Command;

+  UString FileName;

+

+  void ClearCurState();

+

+  CPercentPrinterState():

+      Completed(0),

+      Total((UInt64)(Int64)-1),

+      Files(0)

+    {}

+};

+

+class CPercentPrinter: public CPercentPrinterState

+{

+  UInt32 _tickStep;

+  DWORD _prevTick;

+

+  AString _s;

+

+  AString _printedString;

+  AString _temp;

+  UString _tempU;

+

+  CPercentPrinterState _printedState;

+  AString _printedPercents;

+

+  void GetPercents();

+

+public:

+  CStdOutStream *_so;

+

+  bool NeedFlush;

+  unsigned MaxLen;

+  

+  CPercentPrinter(UInt32 tickStep = 200):

+      _tickStep(tickStep),

+      _prevTick(0),

+      NeedFlush(true),

+      MaxLen(80 - 1)

+  {}

+

+  ~CPercentPrinter();

+

+  void ClosePrint(bool needFlush);

+  void Print();

 };

 

 #endif

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
index 033d70b..d43a490 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -2,7 +2,10 @@
 

 #include "StdAfx.h"

 

+#include "../../../Common/IntToString.h"

+

 #include "../../../Windows/ErrorMsg.h"

+

 #ifndef _7ZIP_ST

 #include "../../../Windows/Synchronization.h"

 #endif

@@ -22,179 +25,191 @@
 

 static const wchar_t *kEmptyFileAlias = L"[Content]";

 

-static const char *kCreatingArchiveMessage = "Creating archive ";

-static const char *kUpdatingArchiveMessage = "Updating archive ";

-static const char *kScanningMessage = "Scanning";

+static const char *kOpenArchiveMessage = "Open archive: ";

+static const char *kCreatingArchiveMessage = "Creating archive: ";

+static const char *kUpdatingArchiveMessage = "Updating archive: ";

+static const char *kScanningMessage = "Scanning the drive:";

 

+static const char *kError = "ERROR: ";

+static const char *kWarning = "WARNING: ";

 

-HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType)

+static HRESULT CheckBreak2()

 {

-  (*OutStream) << endl;

-  if (result != S_OK)

+  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;

+}

+

+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);

+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);

+

+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);

+

+void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);

+

+HRESULT CUpdateCallbackConsole::OpenResult(

+    const CCodecs *codecs, const CArchiveLink &arcLink,

+    const wchar_t *name, HRESULT result)

+{

+  ClosePercents2();

+

+  FOR_VECTOR (level, arcLink.Arcs)

   {

-    (*OutStream) << "Error: " << name;

-    if (errorArcType)

-      (*OutStream) << " : can not open the file as [" << errorArcType << "] archive";

-    else

-      (*OutStream) << " is not supported archive";

-    (*OutStream) << endl;

+    const CArc &arc = arcLink.Arcs[level];

+    const CArcErrorInfo &er = arc.ErrorInfo;

+    

+    UInt32 errorFlags = er.GetErrorFlags();

+

+    if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())

+    {

+      if (_se)

+      {

+        *_se << endl;

+        if (level != 0)

+          *_se << arc.Path << endl;

+      }

+      

+      if (errorFlags != 0)

+      {

+        if (_se)

+          PrintErrorFlags(*_se, "ERRORS:", errorFlags);

+      }

+      

+      if (!er.ErrorMessage.IsEmpty())

+      {

+        if (_se)

+          *_se << "ERRORS:" << endl << er.ErrorMessage << endl;

+      }

+      

+      if (_se)

+      {

+        *_se << endl;

+        _se->Flush();

+      }

+    }

+    

+    UInt32 warningFlags = er.GetWarningFlags();

+

+    if (warningFlags != 0 || !er.WarningMessage.IsEmpty())

+    {

+      if (_so)

+      {

+        *_so << endl;

+        if (level != 0)

+          *_so << arc.Path << endl;

+      }

+      

+      if (warningFlags != 0)

+      {

+        if (_so)

+          PrintErrorFlags(*_so, "WARNINGS:", warningFlags);

+      }

+      

+      if (!er.WarningMessage.IsEmpty())

+      {

+        if (_so)

+          *_so << "WARNINGS:" << endl << er.WarningMessage << endl;

+      }

+      

+      if (_so)

+      {

+        *_so << endl;

+        if (NeedFlush)

+          _so->Flush();

+      }

+    }

+

+  

+    if (er.ErrorFormatIndex >= 0)

+    {

+      if (_so)

+      {

+        Print_ErrorFormatIndex_Warning(_so, codecs, arc);

+        if (NeedFlush)

+          _so->Flush();

+      }

+    }

   }

+

+  if (result == S_OK)

+  {

+    if (_so)

+    {

+      RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));

+      *_so << endl;

+    }

+  }

+  else

+  {

+    if (_so)

+      _so->Flush();

+    if (_se)

+    {

+      *_se << kError << name << endl;

+      HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);

+      RINOK(res);

+      _se->Flush();

+    }

+  }

+

   return S_OK;

 }

 

 HRESULT CUpdateCallbackConsole::StartScanning()

 {

-  (*OutStream) << kScanningMessage;

+  if (_so)

+    *_so << kScanningMessage << endl;

+  _percent.Command = "Scan ";

   return S_OK;

 }

 

-HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)

+HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)

 {

+  if (NeedPercents())

+  {

+    _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;

+    _percent.Completed = st.GetTotalBytes();

+    _percent.FileName = fs2us(path);

+    _percent.Print();

+  }

+

   return CheckBreak();

 }

 

-HRESULT CCallbackConsoleBase::CanNotFindError_Base(const wchar_t *name, DWORD systemError)

+void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)

 {

-  CantFindFiles.Add(name);

-  CantFindCodes.Add(systemError);

-  // m_PercentPrinter.ClosePrint();

-  if (!m_WarningsMode)

+  ClosePercents2();

+  

+  if (_se)

   {

-    (*OutStream) << endl << endl;

-    m_PercentPrinter.PrintNewLine();

-    m_WarningsMode = true;

+    if (_so)

+      _so->Flush();

+

+    *_se << endl << (isWarning ? kWarning : kError)

+        << NError::MyFormatMessage(systemError)

+        << endl << fs2us(path) << endl << endl;

+    _se->Flush();

   }

-  m_PercentPrinter.PrintString(name);

-  m_PercentPrinter.PrintString(":  WARNING: ");

-  m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError));

-  m_PercentPrinter.PrintNewLine();

-  return S_OK;

 }

 

-HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)

-{

-  return CanNotFindError_Base(name, systemError);

-}

 

-HRESULT CUpdateCallbackConsole::FinishScanning()

-{

-  (*OutStream) << endl << endl;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)

-{

-  if(updating)

-    (*OutStream) << kUpdatingArchiveMessage;

-  else

-    (*OutStream) << kCreatingArchiveMessage;

-  if (name != 0)

-    (*OutStream) << name;

-  else

-    (*OutStream) << "StdOut";

-  (*OutStream) << endl << endl;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::FinishArchive()

-{

-  (*OutStream) << endl;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::CheckBreak()

-{

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::Finilize()

+HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)

 {

   MT_LOCK

-  if (m_NeedBeClosed)

-  {

-    if (EnablePercents)

-    {

-      m_PercentPrinter.ClosePrint();

-    }

-    if (!StdOutMode && m_NeedNewLine)

-    {

-      m_PercentPrinter.PrintNewLine();

-      m_NeedNewLine = false;

-    }

-    m_NeedBeClosed = false;

-  }

+

+  ScanErrors.AddError(path, systemError);

+  CommonError(path, systemError, true);

+

   return S_OK;

 }

 

-HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)

-{

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)

+HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)

 {

   MT_LOCK

-  if (EnablePercents)

-    m_PercentPrinter.SetTotal(size);

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)

-{

-  MT_LOCK

-  if (completeValue != NULL)

-  {

-    if (EnablePercents)

-    {

-      m_PercentPrinter.SetRatio(*completeValue);

-      m_PercentPrinter.PrintRatio();

-      m_NeedBeClosed = true;

-    }

-  }

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)

-{

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)

-{

-  MT_LOCK

-  if (StdOutMode)

-    return S_OK;

-  if(isAnti)

-    m_PercentPrinter.PrintString("Anti item    ");

-  else

-    m_PercentPrinter.PrintString("Compressing  ");

-  if (name[0] == 0)

-    name = kEmptyFileAlias;

-  m_PercentPrinter.PrintString(name);

-  if (EnablePercents)

-    m_PercentPrinter.RePrintRatio();

-  return S_OK;

-}

-

-HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)

-{

-  MT_LOCK

-  FailedCodes.Add(systemError);

-  FailedFiles.Add(name);

+  FailedFiles.AddError(path, systemError);

   /*

   if (systemError == ERROR_SHARING_VIOLATION)

   {

   */

-    m_PercentPrinter.ClosePrint();

-    m_PercentPrinter.PrintNewLine();

-    m_PercentPrinter.PrintString("WARNING: ");

-    m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError));

+    CommonError(path, systemError, true);

     return S_FALSE;

   /*

   }

@@ -202,15 +217,398 @@
   */

 }

 

-HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )

+HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)

 {

-  m_NeedBeClosed = true;

-  m_NeedNewLine = true;

+  MT_LOCK

+  CommonError(path, systemError, false);

+  return HRESULT_FROM_WIN32(systemError);

+}

+

+HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)

+{

+  return ScanError_Base(path, systemError);

+}

+

+

+static void PrintPropPair(AString &s, const char *name, UInt64 val)

+{

+  char temp[32];

+  ConvertUInt64ToString(val, temp);

+  s += name;

+  s += ": ";

+  s += temp;

+}

+

+void PrintSize_bytes_Smart(AString &s, UInt64 val);

+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);

+

+HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)

+{

+  if (NeedPercents())

+  {

+    _percent.ClosePrint(true);

+    _percent.ClearCurState();

+  }

+

+  if (_so)

+  {

+    AString s;

+    Print_DirItemsStat(s, st);

+    *_so << s << endl << endl;

+  }

   return S_OK;

 }

 

+static const char *k_StdOut_ArcName = "StdOut";

+

+HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)

+{

+  if (_so)

+  {

+    *_so << kOpenArchiveMessage;

+    if (name)

+      *_so << name;

+    else

+      *_so << k_StdOut_ArcName;

+    *_so << endl;

+  }

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)

+{

+  if (_so)

+  {

+    *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);

+    if (name != 0)

+      *_so << name;

+    else

+      *_so << k_StdOut_ArcName;

+   *_so << endl << endl;

+  }

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)

+{

+  ClosePercents2();

+

+  if (_so)

+  {

+    AString s;

+    // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);

+    PrintPropPair(s, "Files read from disk", _percent.Files);

+    s.Add_LF();

+    s += "Archive size: ";

+    PrintSize_bytes_Smart(s, st.OutArcFileSize);

+    s.Add_LF();

+    *_so << endl;

+    *_so << s;

+    // *_so << endl;

+  }

+

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)

+{

+  if (_so)

+  {

+    *_so << "Write SFX: ";

+    *_so << name;

+    AString s = " : ";

+    PrintSize_bytes_Smart(s, size);

+    *_so << s << endl;

+  }

+  return S_OK;

+}

+

+

+HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)

+{

+  if (LogLevel > 0 && _so)

+  {

+    ClosePercents_for_so();

+      

+    if (!DeleteMessageWasShown)

+    {

+      if (_so)

+        *_so << endl << ": Removing files after including to archive" << endl;

+    }

+   

+    {

+      {

+        _tempA = "Removing";

+        _tempA.Add_Space();

+        *_so << _tempA;

+        _tempU = fs2us(path);

+        _so->PrintUString(_tempU, _tempA);

+        *_so << endl;

+        if (NeedFlush)

+          _so->Flush();

+      }

+    }

+  }

+

+  if (!DeleteMessageWasShown)

+  {

+    if (NeedPercents())

+    {

+      _percent.ClearCurState();

+    }

+    DeleteMessageWasShown = true;

+  }

+  else

+  {

+    _percent.Files++;

+  }

+

+  if (NeedPercents())

+  {

+    // if (!FullLog)

+    {

+      _percent.Command = "Removing";

+      _percent.FileName = fs2us(path);

+    }

+    _percent.Print();

+  }

+

+  return S_OK;

+}

+

+

+HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()

+{

+  ClosePercents2();

+  if (_so && DeleteMessageWasShown)

+    *_so << endl;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::CheckBreak()

+{

+  return CheckBreak2();

+}

+

+/*

+HRESULT CUpdateCallbackConsole::Finalize()

+{

+  // MT_LOCK

+  return S_OK;

+}

+*/

+

+HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems)

+{

+  if (_so)

+  {

+    ClosePercents_for_so();

+    AString s;

+    PrintPropPair(s, "Items to compress", numItems);

+    *_so << s << endl << endl;

+  }

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)

+{

+  MT_LOCK

+  if (NeedPercents())

+  {

+    _percent.Total = size;

+    _percent.Print();

+  }

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)

+{

+  MT_LOCK

+  if (completeValue)

+  {

+    if (NeedPercents())

+    {

+      _percent.Completed = *completeValue;

+      _percent.Print();

+    }

+  }

+  return CheckBreak2();

+}

+

+HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)

+{

+  return CheckBreak2();

+}

+

+HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)

+{

+  MT_LOCK

+  

+  bool show2 = (showInLog && _so);

+

+  if (show2)

+  {

+    ClosePercents_for_so();

+    

+    _tempA = command;

+    if (name)

+      _tempA.Add_Space();

+    *_so << _tempA;

+

+    _tempU.Empty();

+    if (name)

+      _tempU = name;

+    _so->PrintUString(_tempU, _tempA);

+    *_so << endl;

+    if (NeedFlush)

+      _so->Flush();

+  }

+

+  if (NeedPercents())

+  {

+    if (PercentsNameLevel >= 1)

+    {

+      _percent.FileName.Empty();

+      _percent.Command.Empty();

+      if (PercentsNameLevel > 1 || !show2)

+      {

+        _percent.Command = command;

+        if (name)

+          _percent.FileName = name;

+      }

+    }

+    _percent.Print();

+  }

+  

+  return CheckBreak2();

+}

+

+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)

+{

+  if (StdOutMode)

+    return S_OK;

+  

+  if (!name || name[0] == 0)

+    name = kEmptyFileAlias;

+

+  unsigned requiredLevel = 1;

+  

+  const char *s;

+  if (mode == NUpdateNotifyOp::kAdd ||

+      mode == NUpdateNotifyOp::kUpdate)

+  {

+    if (isAnti)

+      s = "Anti";

+    else if (mode == NUpdateNotifyOp::kAdd)

+      s = "+";

+    else

+      s = "U";

+  }

+  else

+  {

+    requiredLevel = 3;

+    if (mode == NUpdateNotifyOp::kAnalyze)

+      s = "A";

+    else

+      s = "Reading";

+  }

+  

+  return PrintProgress(name, s, LogLevel >= requiredLevel);

+}

+

+HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)

+{

+  return OpenFileError_Base(path, systemError);

+}

+

+HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)

+{

+  return ReadingFileError_Base(path, systemError);

+}

+

+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)

+{

+  MT_LOCK

+  _percent.Files++;

+  return S_OK;

+}

+

+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);

+

+HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)

+{

+  // if (StdOutMode) return S_OK;

+

+  if (opRes != NArchive::NExtract::NOperationResult::kOK)

+  {

+    ClosePercents2();

+    

+    if (_se)

+    {

+      if (_so)

+        _so->Flush();

+

+      AString s;

+      SetExtractErrorMessage(opRes, isEncrypted, s);

+      *_se << s << " : " << endl << name << endl << endl;

+      _se->Flush();

+    }

+    return S_OK;

+  }

+  return S_OK;

+}

+

+

+HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)

+{

+  // if (StdOutMode) return S_OK;

+

+  char temp[16];

+  const char *s;

+  

+  unsigned requiredLevel = 1;

+  

+  switch (op)

+  {

+    case NUpdateNotifyOp::kAdd:       s = "+"; break;

+    case NUpdateNotifyOp::kUpdate:    s = "U"; break;

+    case NUpdateNotifyOp::kAnalyze:   s = "A"; requiredLevel = 3; break;

+    case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;

+    case NUpdateNotifyOp::kRepack:    s = "R"; requiredLevel = 2; break;

+    case NUpdateNotifyOp::kSkip:      s = "."; requiredLevel = 2; break;

+    case NUpdateNotifyOp::kDelete:    s = "D"; requiredLevel = 3; break;

+    case NUpdateNotifyOp::kHeader:    s = "Header creation"; requiredLevel = 100; break;

+    default:

+    {

+      temp[0] = 'o';

+      temp[1] = 'p';

+      ConvertUInt64ToString(op, temp + 2);

+      s = temp;

+    }

+  }

+

+  return PrintProgress(name, s, LogLevel >= requiredLevel);

+}

+

+/*

+HRESULT CUpdateCallbackConsole::SetPassword(const UString &

+    #ifndef _NO_CRYPTO

+    password

+    #endif

+    )

+{

+  #ifndef _NO_CRYPTO

+  PasswordIsDefined = true;

+  Password = password;

+  #endif

+  return S_OK;

+}

+*/

+

 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)

 {

+  COM_TRY_BEGIN

+

   *password = NULL;

 

   #ifdef _NO_CRYPTO

@@ -224,7 +622,7 @@
   {

     if (AskPassword)

     {

-      Password = GetPassword(OutStream);

+      Password = GetPassword(_so);

       PasswordIsDefined = true;

     }

   }

@@ -232,10 +630,14 @@
   return StringToBstr(Password, password);

   

   #endif

+

+  COM_TRY_END

 }

 

 HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)

 {

+  COM_TRY_BEGIN

+  

   *password = NULL;

 

   #ifdef _NO_CRYPTO

@@ -247,30 +649,26 @@
   if (!PasswordIsDefined)

   {

     {

-      Password = GetPassword(OutStream);

+      Password = GetPassword(_so);

       PasswordIsDefined = true;

     }

   }

   return StringToBstr(Password, password);

   

   #endif

+  COM_TRY_END

 }

 

-/*

-HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name)

+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)

 {

-  // MT_LOCK

   if (StdOutMode)

     return S_OK;

-  RINOK(Finilize());

-  m_PercentPrinter.PrintString("Deleting  ");

-  if (name[0] == 0)

-    name = kEmptyFileAlias;

-  m_PercentPrinter.PrintString(name);

-  if (EnablePercents)

-    m_PercentPrinter.RePrintRatio();

-  m_NeedBeClosed = true;

-  m_NeedNewLine = true;

+  

+  if (LogLevel > 7)

+  {

+    if (!name || name[0] == 0)

+      name = kEmptyFileAlias;

+    return PrintProgress(name, "D", true);

+  }

   return S_OK;

 }

-*/

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
index c73de67..6765db6 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -9,44 +9,91 @@
 

 #include "PercentPrinter.h"

 

+struct CErrorPathCodes

+{

+  FStringVector Paths;

+  CRecordVector<DWORD> Codes;

+

+  void AddError(const FString &path, DWORD systemError)

+  {

+    Paths.Add(path);

+    Codes.Add(systemError);

+  }

+  void Clear()

+  {

+    Paths.Clear();

+    Codes.Clear();

+  }

+};

+

 class CCallbackConsoleBase

 {

-  bool m_WarningsMode;

 protected:

-  CPercentPrinter m_PercentPrinter;

+  CPercentPrinter _percent;

 

-  CStdOutStream *OutStream;

-  HRESULT CanNotFindError_Base(const wchar_t *name, DWORD systemError);

+  CStdOutStream *_so;

+  CStdOutStream *_se;

+

+  void CommonError(const FString &path, DWORD systemError, bool isWarning);

+  

+  HRESULT ScanError_Base(const FString &path, DWORD systemError);

+  HRESULT OpenFileError_Base(const FString &name, DWORD systemError);

+  HRESULT ReadingFileError_Base(const FString &name, DWORD systemError);

+

 public:

-  bool EnablePercents;

+  bool NeedPercents() const { return _percent._so != NULL; };

+

   bool StdOutMode;

 

+  bool NeedFlush;

+  unsigned PercentsNameLevel;

+  unsigned LogLevel;

+

+  AString _tempA;

+  UString _tempU;

+

   CCallbackConsoleBase():

-      m_PercentPrinter(1 << 16),

       StdOutMode(false),

-      EnablePercents(true),

-      m_WarningsMode(false)

+      NeedFlush(false),

+      PercentsNameLevel(1),

+      LogLevel(0)

       {}

   

-  void Init(CStdOutStream *outStream)

+  void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }

+

+  void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)

   {

     FailedFiles.Clear();

-    FailedCodes.Clear();

-    OutStream = outStream;

-    m_PercentPrinter.OutStream = outStream;

+

+    _so = outStream;

+    _se = errorStream;

+    _percent._so = percentStream;

   }

 

-  UStringVector FailedFiles;

-  CRecordVector<HRESULT> FailedCodes;

+  void ClosePercents2()

+  {

+    if (NeedPercents())

+      _percent.ClosePrint(true);

+  }

 

-  UStringVector CantFindFiles;

-  CRecordVector<HRESULT> CantFindCodes;

+  void ClosePercents_for_so()

+  {

+    if (NeedPercents() && _so == _percent._so)

+      _percent.ClosePrint(false);

+  }

+

+

+  CErrorPathCodes FailedFiles;

+  CErrorPathCodes ScanErrors;

+

+  HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog);

+

 };

 

 class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase

 {

-  bool m_NeedBeClosed;

-  bool m_NeedNewLine;

+  // void PrintPropPair(const char *name, const wchar_t *val);

+

 public:

   #ifndef _NO_CRYPTO

   bool PasswordIsDefined;

@@ -54,21 +101,23 @@
   bool AskPassword;

   #endif

 

+  bool DeleteMessageWasShown;

+

   CUpdateCallbackConsole()

+      : DeleteMessageWasShown(false)

       #ifndef _NO_CRYPTO

-      :

-      PasswordIsDefined(false),

-      AskPassword(false)

+      , PasswordIsDefined(false)

+      , AskPassword(false)

       #endif

       {}

   

+  /*

   void Init(CStdOutStream *outStream)

   {

-    m_NeedBeClosed = false;

-    m_NeedNewLine = false;

     CCallbackConsoleBase::Init(outStream);

   }

-  ~CUpdateCallbackConsole() { Finilize(); }

+  */

+  // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); }

   INTERFACE_IUpdateCallbackUI2(;)

 };

 

diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
index b060fb0..d45e840 100644
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -14,7 +14,7 @@
 static const char kAutoRenameAll = 'u';

 static const char kQuit = 'q';

 

-static const char *kFirstQuestionMessage = "?\n";

+static const char *kFirstQuestionMessage = "? ";

 static const char *kHelpQuestionMessage =

   "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";

 

@@ -22,15 +22,19 @@
 

 NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)

 {

-  (*outStream) << kFirstQuestionMessage;

+  if (outStream)

+    *outStream << kFirstQuestionMessage;

   for (;;)

   {

-    (*outStream) << kHelpQuestionMessage;

-    outStream->Flush();

+    if (outStream)

+    {

+      *outStream << kHelpQuestionMessage;

+      outStream->Flush();

+    }

     AString scannedString = g_StdIn.ScanStringUntilNewLine();

     scannedString.Trim();

     if (!scannedString.IsEmpty())

-      switch(::MyCharLower_Ascii(scannedString[0]))

+      switch (::MyCharLower_Ascii(scannedString[0]))

       {

         case kYes:    return NUserAnswerMode::kYes;

         case kNo:     return NUserAnswerMode::kNo;

@@ -50,14 +54,18 @@
 

 UString GetPassword(CStdOutStream *outStream)

 {

-  (*outStream) << "\nEnter password"

+  if (outStream)

+  {

+    *outStream << "\nEnter password"

       #ifdef MY_DISABLE_ECHO

       " (will not be echoed)"

       #endif

       ":";

-  outStream->Flush();

+    outStream->Flush();

+  }

 

   #ifdef MY_DISABLE_ECHO

+  

   HANDLE console = GetStdHandle(STD_INPUT_HANDLE);

   bool wasChanged = false;

   DWORD mode = 0;

@@ -67,10 +75,16 @@
   UString res = g_StdIn.ScanUStringUntilNewLine();

   if (wasChanged)

     SetConsoleMode(console, mode);

-  (*outStream) << "\n";

-  outStream->Flush();

+  if (outStream)

+  {

+    *outStream << endl;

+    outStream->Flush();

+  }

   return res;

+  

   #else

+  

   return g_StdIn.ScanUStringUntilNewLine();

+  

   #endif

 }

diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
index 0181c52..31bc5c2 100644
--- a/CPP/7zip/UI/Console/makefile
+++ b/CPP/7zip/UI/Console/makefile
@@ -7,8 +7,6 @@
 CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE

 !ENDIF

 

-CURRENT_OBJS = \

-

 COMMON_OBJS = \

   $O\CommandLineParser.obj \

   $O\CRC.obj \

diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index fb63835..703754f 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"

@@ -77,7 +81,7 @@
   UString s = HResultToMessage(errorCode);

   if (name)

   {

-    s += L'\n';

+    s.Add_LF();

     s += name;

   }

   MessageBox_Error_Global(wnd, s);

@@ -106,7 +110,7 @@
   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

@@ -193,9 +197,11 @@
   #endif

 

   #ifndef _SFX

-  if (ReadSingleClick())

+  CFmSettings st;

+  st.Load();

+  if (st.SingleClick)

     _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);

-  _showDots = ReadShowDots();

+  _showDots = st.ShowDots;

   #endif

 

   {

@@ -209,7 +215,7 @@
       FOR_VECTOR (i, Filters)

       {

         if (i != 0)

-          s += L' ';

+          s.Add_Space();

         s += Filters[i];

       }

     }

@@ -256,14 +262,16 @@
   _topDirPrefix.Empty();

   {

     int rootSize = GetRootPrefixSize(FilePath);

+    #if defined(_WIN32) && !defined(UNDER_CE)

     // We can go up from root folder to drives list

-    if (NName::IsDrivePath(FilePath))

+    if (IsDrivePath(FilePath))

       rootSize = 0;

     else if (IsSuperPath(FilePath))

     {

-      if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize]))

+      if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))

         rootSize = kSuperPathPrefixSize;

     }

+    #endif

     _topDirPrefix.SetFrom(FilePath, rootSize);

   }

 

@@ -271,7 +279,7 @@
   if (!GetParentPath(FilePath, DirPrefix, name))

     DirPrefix = _topDirPrefix;

 

-  for(;;)

+  for (;;)

   {

     UString baseFolder = DirPrefix;

     if (Reload(baseFolder, name) == S_OK)

@@ -293,7 +301,7 @@
   #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();

@@ -466,7 +474,7 @@
     return false;

   if (s.Back() == WCHAR_PATH_SEPARATOR)

     return false;

-  int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);

+  int pos = s.ReverseFind_PathSepar();

   parentPrefix.SetFrom(s, pos + 1);

   name = s.Ptr(pos + 1);

   return true;

@@ -856,7 +864,7 @@
       return false;

     {

       UString s = errorMessage;

-      s += L"\n";

+      s.Add_LF();

       s += path;

       MessageBox_Error_Global(owner, s);

     }

@@ -904,27 +912,32 @@
   result.Empty();

 

   UString path = path2;

-  path.Replace('/', WCHAR_PATH_SEPARATOR);

+  path.Replace(L'/', WCHAR_PATH_SEPARATOR);

   unsigned start = 0;

   UString base;

-  if (NName::IsAbsolutePath(path))

+  

+  if (IsAbsolutePath(path))

   {

+    #if defined(_WIN32) && !defined(UNDER_CE)

     if (IsSuperOrDevicePath(path))

     {

       result = path;

       return true;

     }

+    #endif

     int pos = GetRootPrefixSize(path);

     if (pos > 0)

       start = pos;

   }

   else

   {

+    #if defined(_WIN32) && !defined(UNDER_CE)

     if (IsSuperOrDevicePath(relBase))

     {

       result = path;

       return true;

     }

+    #endif

     base = relBase;

   }

 

@@ -954,6 +967,7 @@
   result += path.Left(start);

   bool checkExist = true;

   UString cur;

+

   for (;;)

   {

     if (start == path.Len())

@@ -979,7 +993,7 @@
     result += cur;

     if (slashPos < 0)

       break;

-    result += WCHAR_PATH_SEPARATOR;

+    result.Add_PathSepar();

     start = slashPos + 1;

   }

   

@@ -987,11 +1001,13 @@
 }

 

 #else

+

 bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result)

 {

   result = path;

   return true;

 }

+

 #endif

 

 bool Dlg_CreateFolder(HWND wnd, UString &destName)

diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h
index 306d19f..be51085 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.h
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.h
@@ -9,7 +9,7 @@
 bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);

 

 /* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)

-   But it doesn't change "bad" name in any of the following caes:

+   But it doesn't change "bad" name in any of the following cases:

      - path is Super Path (with \\?\ prefix)

      - path is relative and relBase is Super Path

      - there is file or dir in filesystem with specified "bad" name */

diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index bb14e52..1c3141c 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -22,6 +22,7 @@
 #endif

 

 #include "../GUI/ExtractRes.h"

+#include "resourceGui.h"

 

 #include "ExtractCallback.h"

 #include "FormatUtils.h"

@@ -30,6 +31,7 @@
 #ifndef _NO_CRYPTO

 #include "PasswordDialog.h"

 #endif

+#include "PropertyName.h"

 

 using namespace NWindows;

 using namespace NFile;

@@ -39,6 +41,10 @@
 

 void CExtractCallbackImp::Init()

 {

+  _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING);

+  _lang_Testing = LangString(IDS_PROGRESS_TESTING);

+  _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING);

+

   NumArchiveErrors = 0;

   ThereAreMessageErrors = false;

   #ifndef _SFX

@@ -85,15 +91,50 @@
   return ProgressDialog->Sync.CheckStop();

 }

 

-HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)

 {

-  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles);

-  return S_OK;

+  HRESULT res = S_OK;

+  if (!MultiArcMode)

+  {

+    if (files)

+    {

+      _totalFilesDefined = true;

+      // res = ProgressDialog->Sync.Set_NumFilesTotal(*files);

+    }

+    else

+      _totalFilesDefined = false;

+

+    if (bytes)

+    {

+      _totalBytesDefined = true;

+      ProgressDialog->Sync.Set_NumBytesTotal(*bytes);

+    }

+    else

+      _totalBytesDefined = false;

+  }

+

+  return res;

 }

 

-HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)

 {

-  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles);

+  if (!MultiArcMode)

+  {

+    if (files)

+    {

+      ProgressDialog->Sync.Set_NumFilesCur(*files);

+    }

+

+    if (bytes)

+    {

+    }

+  }

+

+  return ProgressDialog->Sync.CheckStop();

+}

+

+HRESULT CExtractCallbackImp::Open_Finished()

+{

   return ProgressDialog->Sync.CheckStop();

 }

 

@@ -104,6 +145,7 @@
   return CryptoGetTextPassword(password);

 }

 

+/*

 HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)

 {

   passwordIsDefined = PasswordIsDefined;

@@ -116,10 +158,11 @@
   return PasswordWasAsked;

 }

 

-void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()

+void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()

 {

   PasswordWasAsked = false;

 }

+*/

 

 #endif

 

@@ -179,10 +222,21 @@
 }

 

 

-STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)

+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)

 {

-  _isFolder = isFolder;

-  return SetCurrentFilePath2(name);

+  _isFolder = IntToBool(isFolder);

+  _currentFilePath = name;

+

+  const UString *msg = &_lang_Empty;

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;

+    case NArchive::NExtract::NAskMode::kTest:    msg = &_lang_Testing; break;

+    case NArchive::NExtract::NAskMode::kSkip:    msg = &_lang_Skipping; break;

+    // default: s = "Unknown operation";

+  }

+

+  return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder));

 }

 

 STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s)

@@ -208,7 +262,98 @@
 

 #endif

 

-STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted)

+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s)

+{

+  s.Empty();

+

+  if (opRes == NArchive::NExtract::NOperationResult::kOK)

+    return;

+

+  UINT messageID = 0;

+  UINT id = 0;

+

+  switch (opRes)

+  {

+    case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

+      messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;

+      id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;

+      break;

+    case NArchive::NExtract::NOperationResult::kDataError:

+      messageID = encrypted ?

+          IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:

+          IDS_EXTRACT_MESSAGE_DATA_ERROR;

+      id = IDS_EXTRACT_MSG_DATA_ERROR;

+      break;

+    case NArchive::NExtract::NOperationResult::kCRCError:

+      messageID = encrypted ?

+          IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:

+          IDS_EXTRACT_MESSAGE_CRC_ERROR;

+      id = IDS_EXTRACT_MSG_CRC_ERROR;

+      break;

+    case NArchive::NExtract::NOperationResult::kUnavailable:

+      id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;

+      break;

+    case NArchive::NExtract::NOperationResult::kUnexpectedEnd:

+      id = IDS_EXTRACT_MSG_UEXPECTED_END;

+      break;

+    case NArchive::NExtract::NOperationResult::kDataAfterEnd:

+      id = IDS_EXTRACT_MSG_DATA_AFTER_END;

+      break;

+    case NArchive::NExtract::NOperationResult::kIsNotArc:

+      id = IDS_EXTRACT_MSG_IS_NOT_ARC;

+      break;

+    case NArchive::NExtract::NOperationResult::kHeadersError:

+      id = IDS_EXTRACT_MSG_HEADERS_ERROR;

+      break;

+    case NArchive::NExtract::NOperationResult::kWrongPassword:

+      id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM;

+      break;

+    /*

+    default:

+      messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;

+      break;

+    */

+  }

+

+  UString msg;

+  UString msgOld;

+

+  #ifndef _SFX

+  if (id != 0)

+    LangString_OnlyFromLangFile(id, msg);

+  if (messageID != 0 && msg.IsEmpty())

+    LangString_OnlyFromLangFile(messageID, msgOld);

+  #endif

+

+  if (msg.IsEmpty() && !msgOld.IsEmpty())

+    s = MyFormatNew(msgOld, fileName);

+  else

+  {

+    if (msg.IsEmpty() && id != 0)

+      LangString(id, msg);

+    if (!msg.IsEmpty())

+      s += msg;

+    else

+    {

+      char temp[16];

+      ConvertUInt32ToString(opRes, temp);

+      s.AddAscii("Error #");

+      s.AddAscii(temp);

+    }

+

+    if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)

+    {

+      // s.AddAscii(" : ");

+      // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);

+      s.AddAscii(" : ");

+      AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);

+    }

+    s.AddAscii(" : ");

+    s += fileName;

+  }

+}

+

+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)

 {

   switch (opRes)

   {

@@ -216,93 +361,9 @@
       break;

     default:

     {

-      UINT messageID = 0;

-      UINT id = 0;

-

-      switch (opRes)

-      {

-        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

-          messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;

-          id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;

-          break;

-        case NArchive::NExtract::NOperationResult::kDataError:

-          messageID = encrypted ?

-              IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:

-              IDS_EXTRACT_MESSAGE_DATA_ERROR;

-          id = IDS_EXTRACT_MSG_DATA_ERROR;

-          break;

-        case NArchive::NExtract::NOperationResult::kCRCError:

-          messageID = encrypted ?

-              IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:

-              IDS_EXTRACT_MESSAGE_CRC_ERROR;

-          id = IDS_EXTRACT_MSG_CRC_ERROR;

-          break;

-        case NArchive::NExtract::NOperationResult::kUnavailable:

-          id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;

-          break;

-        case NArchive::NExtract::NOperationResult::kUnexpectedEnd:

-          id = IDS_EXTRACT_MSG_UEXPECTED_END;

-          break;

-        case NArchive::NExtract::NOperationResult::kDataAfterEnd:

-          id = IDS_EXTRACT_MSG_DATA_AFTER_END;

-          break;

-        case NArchive::NExtract::NOperationResult::kIsNotArc:

-          id = IDS_EXTRACT_MSG_IS_NOT_ARC;

-          break;

-        case NArchive::NExtract::NOperationResult::kHeadersError:

-          id = IDS_EXTRACT_MSG_HEADERS_ERROR;

-          break;

-        /*

-        default:

-          messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;

-          break;

-        */

-      }

-      if (_needWriteArchivePath)

-      {

-        if (!_currentArchivePath.IsEmpty())

-          AddError_Message(_currentArchivePath);

-        _needWriteArchivePath = false;

-      }

-

-      UString msg;

-      UString msgOld;

-

-      #ifndef _SFX

-      if (id != 0)

-        LangString_OnlyFromLangFile(id, msg);

-      if (messageID != 0 && msg.IsEmpty())

-        LangString_OnlyFromLangFile(messageID, msgOld);

-      #endif

-

       UString s;

-      if (msg.IsEmpty() && !msgOld.IsEmpty())

-        s = MyFormatNew(msgOld, _currentFilePath);

-      else

-      {

-        if (msg.IsEmpty())

-          LangString(id, msg);

-        if (!msg.IsEmpty())

-          s += msg;

-        else

-        {

-          wchar_t temp[16];

-          ConvertUInt32ToString(opRes, temp);

-          s += L"Error #";

-          s += temp;

-        }

-

-        if (encrypted)

-        {

-          // s += L" : ";

-          // s += LangString(IDS_EXTRACT_MSG_ENCRYPTED);

-          s += L" : ";

-          s += LangString(IDS_EXTRACT_MSG_WRONG_PSW);

-        }

-        s += L" : ";

-        s += _currentFilePath;

-      }

-

+      SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);

+      Add_ArchiveName_Error();

       AddError_Message(s);

     }

   }

@@ -318,10 +379,22 @@
   return S_OK;

 }

 

+STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)

+{

+  if (opRes != NArchive::NExtract::NOperationResult::kOK)

+  {

+    UString s;

+    SetExtractErrorMessage(opRes, encrypted, name, s);

+    Add_ArchiveName_Error();

+    AddError_Message(s);

+  }

+  return S_OK;

+}

+

 ////////////////////////////////////////

 // IExtractCallbackUI

 

-HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)

+HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)

 {

   #ifndef _SFX

   RINOK(ProgressDialog->Sync.CheckStop());

@@ -357,27 +430,6 @@
 

 UString HResultToMessage(HRESULT errorCode);

 

-HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted)

-{

-  if (result != S_OK)

-  {

-    UString s;

-    if (result == S_FALSE)

-      s = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, name);

-    else

-    {

-      s = name;

-      s += L": ";

-      s += HResultToMessage(result);

-    }

-    MessageError(s);

-    NumArchiveErrors++;

-  }

-  _currentArchivePath = name;

-  _needWriteArchivePath = true;

-  return S_OK;

-}

-

 static const UInt32 k_ErrorFlagsIds[] =

 {

   IDS_EXTRACT_MSG_IS_NOT_ARC,

@@ -393,9 +445,16 @@
   IDS_EXTRACT_MSG_CRC_ERROR

 };

 

+static void AddNewLineString(UString &s, const UString &m)

+{

+  s += m;

+  s.Add_LF();

+}

+

 UString GetOpenArcErrorMessage(UInt32 errorFlags)

 {

   UString s;

+

   for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++)

   {

     UInt32 f = ((UInt32)1 << i);

@@ -407,14 +466,15 @@
       continue;

     if (f == kpv_ErrorFlags_EncryptedHeadersError)

     {

-      m += L" : ";

-      m += LangString(IDS_EXTRACT_MSG_WRONG_PSW);

+      m.AddAscii(" : ");

+      AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);

     }

     if (!s.IsEmpty())

-      s += L'\n';

+      s.Add_LF();

     s += m;

     errorFlags &= ~f;

   }

+  

   if (errorFlags != 0)

   {

     char sz[16];

@@ -422,74 +482,151 @@
     sz[1] = 'x';

     ConvertUInt32ToHex(errorFlags, sz + 2);

     if (!s.IsEmpty())

-      s += L'\n';

-    s += GetUnicodeString(AString(sz));

+      s.Add_LF();

+    s.AddAscii(sz);

   }

+  

   return s;

 }

 

-HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name,

-    UInt32 errorFlags, const wchar_t *errors,

-    UInt32 warningFlags, const wchar_t *warnings)

+static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)

 {

-  NumArchiveErrors++;

+  UInt32 errorFlags = er.GetErrorFlags();

+  UInt32 warningFlags = er.GetWarningFlags();

 

+  if (errorFlags != 0)

+    AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));

+      

+  if (!er.ErrorMessage.IsEmpty())

+    AddNewLineString(s, er.ErrorMessage);

+  

+  if (warningFlags != 0)

+  {

+    s += GetNameOfProperty(kpidWarningFlags, L"Warnings");

+    s.AddAscii(":");

+    s.Add_LF();

+    AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));

+  }

+  

+  if (!er.WarningMessage.IsEmpty())

+  {

+    s += GetNameOfProperty(kpidWarning, L"Warning");

+    s.AddAscii(": ");

+    s += er.WarningMessage;

+    s.Add_LF();

+  }

+}

+

+static UString GetBracedType(const wchar_t *type)

+{

+  UString s = L'[';

+  s += type;

+  s += L']';

+  return s;

+}

+

+void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)

+{

+  FOR_VECTOR (level, arcLink.Arcs)

+  {

+    const CArc &arc = arcLink.Arcs[level];

+    const CArcErrorInfo &er = arc.ErrorInfo;

+

+    if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)

+      continue;

+

+    if (s.IsEmpty())

+    {

+      s += name;

+      s.Add_LF();

+    }

+    

+    if (level != 0)

+    {

+      AddNewLineString(s, arc.Path);

+    }

+      

+    ErrorInfo_Print(s, er);

+

+    if (er.ErrorFormatIndex >= 0)

+    {

+      AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning"));

+      if (arc.FormatIndex == er.ErrorFormatIndex)

+      {

+        AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET));

+      }

+      else

+      {

+        AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex))));

+        AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex))));

+      }

+    }

+  }

+

+  if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)

+  {

+    s += name;

+    s.Add_LF();

+    if (!arcLink.Arcs.IsEmpty())

+      AddNewLineString(s, arcLink.NonOpen_ArcPath);

+    

+    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE)

+    {

+      UINT id = IDS_CANT_OPEN_ARCHIVE;

+      UString param;

+      if (arcLink.PasswordWasAsked)

+        id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE;

+      else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+      {

+        id = IDS_CANT_OPEN_AS_TYPE;

+        param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex));

+      }

+      UString s2 = MyFormatNew(id, param);

+      s2.Replace(L" ''", L"");

+      s2.Replace(L"''", L"");

+      s += s2;

+    }

+    else

+      s += HResultToMessage(result);

+

+    s.Add_LF();

+    ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo);

+  }

+

+  if (!s.IsEmpty() && s.Back() == '\n')

+    s.DeleteBack();

+}

+

+HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)

+{

+  _currentArchivePath = name;

+  _needWriteArchivePath = true;

+

+  UString s;

+  OpenResult_GUI(s, codecs, arcLink, name, result);

+  if (!s.IsEmpty())

+  {

+    NumArchiveErrors++;

+    AddError_Message(s);

+    _needWriteArchivePath = false;

+  }

+

+  return S_OK;

+}

+

+HRESULT CExtractCallbackImp::ThereAreNoFiles()

+{

+  return S_OK;

+}

+

+void CExtractCallbackImp::Add_ArchiveName_Error()

+{

   if (_needWriteArchivePath)

   {

     if (!_currentArchivePath.IsEmpty())

       AddError_Message(_currentArchivePath);

     _needWriteArchivePath = false;

   }

-

-  if (level != 0)

-  {

-    UString s;

-    s += name;

-    s += L": ";

-    MessageError(s);

-  }

-

-  if (errorFlags != 0)

-    MessageError(GetOpenArcErrorMessage(errorFlags));

-

-  if (errors && wcslen(errors) != 0)

-    MessageError(errors);

-

-  if (warningFlags != 0)

-    MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags));

-

-  if (warnings && wcslen(warnings) != 0)

-    MessageError((UString)L"Warnings: " + warnings);

-

-  return S_OK;

-}

-

-HRESULT CExtractCallbackImp::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)

-{

-  UString s = L"Warning:\n";

-  s += name;

-  s += L"\n";

-  if (wcscmp(okType, errorType) == 0)

-  {

-    s += L"The archive is open with offset";

-  }

-  else

-  {

-    s += L"Can not open the file as [";

-    s += errorType;

-    s += L"] archive\n";

-    s += L"The file is open as [";

-    s += okType;

-    s += L"] archive";

-  }

-  MessageError(s);

-  NumArchiveErrors++;

-  return S_OK;

-}

-  

-HRESULT CExtractCallbackImp::ThereAreNoFiles()

-{

-  return S_OK;

 }

 

 HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)

@@ -499,7 +636,10 @@
   NumArchiveErrors++;

   if (result == E_ABORT || result == ERROR_DISK_FULL)

     return result;

-  MessageError(_currentFilePath);

+

+  Add_ArchiveName_Error();

+  if (!_currentFilePath.IsEmpty())

+    MessageError(_currentFilePath);

   MessageError(NError::MyFormatMessage(result));

   return S_OK;

 }

@@ -564,7 +704,7 @@
     {

       if (!destFileInfo.IsDir())

       {

-        RINOK(MessageError("can not replace file with folder with same name: ", destPathSys));

+        RINOK(MessageError("can not replace file with folder with same name", destPathSys));

         return E_ABORT;

       }

       *writeAnswer = BoolToInt(false);

@@ -573,8 +713,9 @@
   

     if (destFileInfo.IsDir())

     {

-      RINOK(MessageError("can not replace folder with file with same name: ", destPathSys));

-      return E_FAIL;

+      RINOK(MessageError("can not replace folder with file with same name", destPathSys));

+      *writeAnswer = BoolToInt(false);

+      return S_OK;

     }

 

     switch (OverwriteMode)

@@ -583,13 +724,9 @@
         return S_OK;

       case NExtract::NOverwriteMode::kAsk:

       {

-        Int32 overwiteResult;

+        Int32 overwriteResult;

         UString destPathSpec = destPath;

-        int slashPos = destPathSpec.ReverseFind(L'/');

-        #ifdef _WIN32

-        int slash1Pos = destPathSpec.ReverseFind(L'\\');

-        slashPos = MyMax(slashPos, slash1Pos);

-        #endif

+        int slashPos = destPathSpec.ReverseFind_PathSepar();

         destPathSpec.DeleteFrom(slashPos + 1);

         destPathSpec += fs2us(destFileInfo.Name);

 

@@ -598,9 +735,9 @@
             &destFileInfo.MTime, &destFileInfo.Size,

             srcPath,

             srcTime, srcSize,

-            &overwiteResult));

+            &overwriteResult));

         

-        switch (overwiteResult)

+        switch (overwriteResult)

         {

           case NOverwriteAnswer::kCancel: return E_ABORT;

           case NOverwriteAnswer::kNo: return S_OK;

@@ -618,7 +755,7 @@
     {

       if (!AutoRenamePath(destPathSys))

       {

-        RINOK(MessageError("can not create name for file: ", destPathSys));

+        RINOK(MessageError("can not create name for file", destPathSys));

         return E_ABORT;

       }

       destPathResultTemp = fs2us(destPathSys);

@@ -626,7 +763,7 @@
     else

       if (!NDir::DeleteFileAlways(destPathSys))

       {

-        RINOK(MessageError("can not delete output file: ", destPathSys));

+        RINOK(MessageError("can not delete output file", destPathSys));

         return E_ABORT;

       }

   }

@@ -783,7 +920,7 @@
   COM_TRY_END

 }

 

-STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted)

+STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted)

 {

   COM_TRY_BEGIN

   if (VirtFileSystem && _newVirtFileWasAdded)

@@ -865,7 +1002,7 @@
   while (_numFlushed < Files.Size())

   {

     const CVirtFile &file = Files[_numFlushed];

-    const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name));

+    const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));

     if (!_fileIsOpen)

     {

       if (!_outFileStreamSpec->Create(path, false))

diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
index fea83d6..a6d5ae3 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.h
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -36,8 +36,7 @@
   Byte *_items;

   size_t _size;

 

-  CGrowBuf(const CGrowBuf &buffer);

-  void operator=(const CGrowBuf &buffer);

+  CLASS_NO_COPY(CGrowBuf);

 

 public:

   bool ReAlloc_KeepData(size_t newSize, size_t keepSize)

@@ -45,7 +44,8 @@
     void *buf = MyAlloc(newSize);

     if (!buf)

       return false;

-    memcpy(buf, _items, keepSize);

+    if (keepSize != 0)

+      memcpy(buf, _items, keepSize);

     MyFree(_items);

     _items = (Byte *)buf;

     _size = newSize;

@@ -55,8 +55,8 @@
   CGrowBuf(): _items(0), _size(0) {}

   ~CGrowBuf() { MyFree(_items); }

 

-  operator Byte *() { return _items; };

-  operator const Byte *() const { return _items; };

+  operator Byte *() { return _items; }

+  operator const Byte *() const { return _items; }

   size_t Size() const { return _size; }

 };

 

@@ -135,10 +135,11 @@
   {

     if (_fileMode)

       return false;

-    if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir)

+    if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)

       return false;

     return true;

   }

+

   size_t GetMemStreamWrittenSize() const { return _pos; }

 

   CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}

@@ -165,6 +166,7 @@
 class CExtractCallbackImp:

   public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback

   public IOpenCallbackUI,

+  public IFolderArchiveExtractCallback2,

   #ifndef _SFX

   public IFolderOperationsExtractCallback,

   public IFolderExtractToStreamCallback,

@@ -176,8 +178,10 @@
   public CMyUnknownImp

 {

   HRESULT MessageError(const char *message, const FString &path);

+  void Add_ArchiveName_Error();

 public:

   MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)

+  MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)

   #ifndef _SFX

   MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)

   MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)

@@ -191,33 +195,12 @@
 

   INTERFACE_IProgress(;)

   INTERFACE_IOpenCallbackUI(;)

-

-  // IFolderArchiveExtractCallback

+  INTERFACE_IFolderArchiveExtractCallback(;)

+  INTERFACE_IFolderArchiveExtractCallback2(;)

   // STDMETHOD(SetTotalFiles)(UInt64 total);

   // STDMETHOD(SetCompletedFiles)(const UInt64 *value);

-  STDMETHOD(AskOverwrite)(

-      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

-      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

-      Int32 *answer);

-  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);

 

-  STDMETHOD(MessageError)(const wchar_t *message);

-  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);

-

-  // IExtractCallbackUI

-  

-  HRESULT BeforeOpen(const wchar_t *name);

-  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);

-  HRESULT SetError(int level, const wchar_t *name,

-      UInt32 errorFlags, const wchar_t *errors,

-      UInt32 warningFlags, const wchar_t *warnings);

-  HRESULT ThereAreNoFiles();

-  HRESULT ExtractResult(HRESULT result);

-  HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);

-

-  #ifndef _NO_CRYPTO

-  HRESULT SetPassword(const UString &password);

-  #endif

+  INTERFACE_IExtractCallbackUI(;)

 

   #ifndef _SFX

   // IFolderOperationsExtractCallback

@@ -295,6 +278,16 @@
   UString Password;

   #endif

 

+

+  UString _lang_Extracting;

+  UString _lang_Testing;

+  UString _lang_Skipping;

+  UString _lang_Empty;

+

+  bool _totalFilesDefined;

+  bool _totalBytesDefined;

+  bool MultiArcMode;

+

   CExtractCallbackImp():

     #ifndef _NO_CRYPTO

     PasswordIsDefined(false),

@@ -302,7 +295,12 @@
     #endif

     OverwriteMode(NExtract::NOverwriteMode::kAsk),

     StreamMode(false),

-    ProcessAltStreams(true)

+    ProcessAltStreams(true),

+    

+    _totalFilesDefined(false),

+    _totalBytesDefined(false),

+    MultiArcMode(false)

+    

     #ifndef _SFX

     , _hashCalc(NULL)

     #endif

diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h
index d1d1477..c694423 100644
--- a/CPP/7zip/UI/FileManager/LangUtils.h
+++ b/CPP/7zip/UI/FileManager/LangUtils.h
@@ -25,13 +25,15 @@
 void LangSetWindowText(HWND window, UInt32 langID);

 

 UString LangString(UInt32 langID);

+void AddLangString(UString &s, UInt32 langID);

 void LangString(UInt32 langID, UString &dest);

 void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);

-

+ 

 #else

 

 inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }

 inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }

+inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }

 

 #endif

 

diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
index d945945..c5191d0 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -50,7 +50,7 @@
     sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));

 

   const UString &fileName = fileInfo.Name;

-  int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);

+  int slashPos = fileName.ReverseFind_PathSepar();

   UString s1 = fileName.Left(slashPos + 1);

   UString s2 = fileName.Ptr(slashPos + 1);

 

@@ -58,18 +58,18 @@
   ReduceString(s2);

   

   UString s = s1;

-  s += L'\n';

+  s.Add_LF();

   s += s2;

-  s += L'\n';

+  s.Add_LF();

   s += sizeString;

-  s += L'\n';

+  s.Add_LF();

 

   if (fileInfo.TimeIsDefined)

   {

     FILETIME localFileTime;

     if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))

       throw 4190402;

-    s += LangString(IDS_PROP_MTIME);

+    AddLangString(s, IDS_PROP_MTIME);

     s += L": ";

     wchar_t t[32];

     ConvertFileTimeToString(localFileTime, t);

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
index 798b1a4..820e409 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -132,7 +132,7 @@
 

 bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

 {

-  switch(message)

+  switch (message)

   {

     case kCloseMessage:

     {

@@ -158,7 +158,7 @@
 

 bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

 {

-  switch(buttonID)

+  switch (buttonID)

   {

     case IDCANCEL:

     {

@@ -184,7 +184,7 @@
 {

   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 9c6702f..2a9d26d 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -152,7 +152,7 @@
   {

     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 aea37a4..dd3b493 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -8,13 +8,14 @@
 #include "../../../Windows/Control/Static.h"

 #include "../../../Windows/ErrorMsg.h"

 

-#include "ProgressDialog2.h"

-#include "DialogSize.h"

-

-#include "ProgressDialog2Res.h"

-

 #include "../GUI/ExtractRes.h"

 

+#include "LangUtils.h"

+

+#include "DialogSize.h"

+#include "ProgressDialog2.h"

+#include "ProgressDialog2Res.h"

+

 using namespace NWindows;

 

 extern HINSTANCE g_hInstance;

@@ -28,7 +29,7 @@
   #ifdef UNDER_CE

   500

   #else

-  100

+  200

   #endif

   ;

 

@@ -42,8 +43,6 @@
 

 static const DWORD kPauseSleepTime = 100;

 

-#include "LangUtils.h"

-

 #ifdef LANG

 

 static const UInt32 kLangIDs[] =

@@ -104,13 +103,13 @@
   }

 }

 

-HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir)

+HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)

 {

   {

     CRITICAL_LOCK

     _totalFiles = numFiles;

     _totalBytes = totalSize;

-    _filePath = fileName;

+    _filePath = fs2us(fileName);

     _isDir = isDir;

     // _completedBytes = 0;

     CHECK_STOP

@@ -118,10 +117,14 @@
   return CheckStop();

 }

 

-void CProgressSync::Set_NumFilesTotal(UInt64 val)

+HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)

 {

-  CRITICAL_LOCK

-  _totalFiles = val;

+  {

+    CRITICAL_LOCK

+    _totalFiles = val;

+    CHECK_STOP

+  }

+  return CheckStop();

 }

 

 void CProgressSync::Set_NumBytesTotal(UInt64 val)

@@ -171,16 +174,34 @@
   CRITICAL_LOCK

   _titleFileName = fileName;

 }

+

 void CProgressSync::Set_Status(const UString &s)

 {

   CRITICAL_LOCK

   _status = s;

 }

 

-void CProgressSync::Set_FilePath(const UString &path, bool isDir)

+HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir)

+{

+  {

+    CRITICAL_LOCK

+    _status = s;

+    if (path)

+      _filePath = path;

+    else

+      _filePath.Empty();

+    _isDir = isDir;

+  }

+  return CheckStop();

+}

+

+void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir)

 {

   CRITICAL_LOCK

-  _filePath = path;

+  if (path)

+    _filePath = path;

+  else

+    _filePath.Empty();

   _isDir = isDir;

 }

 

@@ -199,7 +220,7 @@
   if (message && *message != 0 )

   {

     if (!s.IsEmpty())

-      s += L'\n';

+      s.Add_LF();

     s += message;

     if (!s.IsEmpty() && s.Back() == L'\n')

       s.DeleteBack();

@@ -633,7 +654,6 @@
   if (high == 0)

     return GetPower32((UInt32)val);

   return GetPower32(high) + 32;

-

 }

 

 static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)

@@ -684,10 +704,9 @@
 

   UInt32 curTime = ::GetTickCount();

 

+  const UInt64 progressTotal = bytesProgressMode ? total : totalFiles;

+  const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;

   {

-    UInt64 progressTotal = bytesProgressMode ? total : totalFiles;

-    UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;

-    

     if (IS_UNDEFINED_VAL(progressTotal))

     {

       // SetPos(0);

@@ -736,9 +755,9 @@
       }

     }

 

-    if (completed != 0)

+    if (progressCompleted != 0)

     {

-      if (IS_UNDEFINED_VAL(total))

+      if (IS_UNDEFINED_VAL(progressTotal))

       {

         if (IS_DEFINED_VAL(_prevRemainingSec))

         {

@@ -749,8 +768,8 @@
       else

       {

         UInt64 remainingTime = 0;

-        if (completed < total)

-          remainingTime = MyMultAndDiv(_elapsedTime, total - completed, completed);

+        if (progressCompleted < progressTotal)

+          remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);

         UInt64 remainingSec = remainingTime / 1000;

         if (remainingSec != _prevRemainingSec)

         {

@@ -762,7 +781,7 @@
       }

       {

         UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;

-        UInt64 v = (completed * 1000) / elapsedTime;

+        UInt64 v = (progressCompleted * 1000) / elapsedTime;

         Byte c = 0;

         unsigned moveBits = 0;

              if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }

@@ -790,11 +809,11 @@
     {

       UInt64 percent = 0;

       {

-        if (IS_DEFINED_VAL(total))

+        if (IS_DEFINED_VAL(progressTotal))

         {

-          percent = completed * 100;

-          if (total != 0)

-            percent /= total;

+          percent = progressCompleted * 100;

+          if (progressTotal != 0)

+            percent /= progressTotal;

         }

       }

       if (percent != _prevPercentValue)

@@ -867,7 +886,7 @@
       s1 = _filePath;

     else

     {

-      int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);

+      int slashPos = _filePath.ReverseFind_PathSepar();

       if (slashPos >= 0)

       {

         s1.SetFrom(_filePath, slashPos + 1);

@@ -878,7 +897,7 @@
     }

     ReduceString(s1, _numReduceSymbols);

     ReduceString(s2, _numReduceSymbols);

-    s1 += L'\n';

+    s1.Add_LF();

     s1 += s2;

     SetItemText(IDT_PROGRESS_FILE_NAME, s1);

   }

@@ -920,8 +939,8 @@
       CWaitCursor waitCursor;

       HANDLE h[] = { thread, _createDialogEvent };

       

-      WRes res = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay);

-      if (res == WAIT_OBJECT_0 && !Sync.ThereIsMessage())

+      WRes res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay);

+      if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage())

         return 0;

     }

     _title = title;

@@ -1025,22 +1044,22 @@
   if (Sync.Get_Paused())

   {

     s += _paused_String;

-    s += L' ';

+    s.Add_Space();

   }

   if (IS_DEFINED_VAL(_prevPercentValue))

   {

-    wchar_t temp[32];

+    char temp[32];

     ConvertUInt64ToString(_prevPercentValue, temp);

-    s += temp;

+    s.AddAscii(temp);

     s += L'%';

   }

   if (!_foreground)

   {

-    s += L' ';

+    s.Add_Space();

     s += _backgrounded_String;

   }

 

-  s += L' ';

+  s.Add_Space();

   #ifndef _SFX

   {

     unsigned len = s.Len();

@@ -1055,7 +1074,7 @@
   {

     UString fileName = _titleFileName;

     ReduceString(fileName, kTitleFileNameSizeLimit);

-    s += L' ';

+    s.Add_Space();

     s += fileName;

   }

   SetText(s);

@@ -1208,7 +1227,7 @@
 {

   if (_needClose)

   {

-    PostMessage(kCloseMessage);

+    PostMsg(kCloseMessage);

     _needClose = false;

   }

 }

@@ -1220,7 +1239,7 @@
     WaitCreating();

   

   if (_wasCreated)

-    PostMessage(kCloseMessage);

+    PostMsg(kCloseMessage);

   else

     _needClose = true;

 }

@@ -1239,7 +1258,7 @@
   if (!src.IsEmpty())

   {

     if (!dest.IsEmpty())

-      dest += L'\n';

+      dest.Add_LF();

     dest += src;

   }

 }

@@ -1266,8 +1285,15 @@
       m = HResultToMessage(Result);

   }

   AddMessageToString(m, FinalMessage.ErrorMessage.Message);

-  AddMessageToString(m, fs2us(ErrorPath1));

-  AddMessageToString(m, fs2us(ErrorPath2));

+

+  {

+    FOR_VECTOR(i, ErrorPaths)

+    {

+      if (i >= 32)

+        break;

+      AddMessageToString(m, fs2us(ErrorPaths[i]));

+    }

+  }

 

   CProgressSync &sync = ProgressDialog.Sync;

   NSynchronization::CCriticalSectionLock lock(sync._cs);

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
index 35e0f17..0e2f2ce 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -80,9 +80,9 @@
   }

   

   HRESULT CheckStop();

-  HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false);

+  HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);

 

-  void Set_NumFilesTotal(UInt64 val);

+  HRESULT Set_NumFilesTotal(UInt64 val);

   void Set_NumBytesTotal(UInt64 val);

   void Set_NumFilesCur(UInt64 val);

   HRESULT Set_NumBytesCur(const UInt64 *val);

@@ -91,7 +91,8 @@
 

   void Set_TitleFileName(const UString &fileName);

   void Set_Status(const UString &s);

-  void Set_FilePath(const UString &path, bool isDir = false);

+  HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false);

+  void Set_FilePath(const wchar_t *path, bool isDir = false);

 

   void AddError_Message(const wchar_t *message);

   void AddError_Message_Name(const wchar_t *message, const wchar_t *name);

@@ -274,9 +275,8 @@
 

 class CProgressThreadVirt

 {

-  FString ErrorPath1;

-  FString ErrorPath2;

 protected:

+  FStringVector ErrorPaths;

   CProgressFinalMessage FinalMessage;

 

   // error if any of HRESULT, ErrorMessage, ErrorPath

@@ -299,8 +299,7 @@
     return 0;

   }

 

-  void SetErrorPath1(const FString &path) { ErrorPath1 = path; }

-  void SetErrorPath2(const FString &path) { ErrorPath2 = path; }

+  void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }

 

   HRESULT Create(const UString &title, HWND parentWindow = 0);

   CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}

diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp
new file mode 100644
index 0000000..a955241
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyName.cpp
@@ -0,0 +1,23 @@
+// PropertyName.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+

+#include "LangUtils.h"

+#include "PropertyName.h"

+

+UString GetNameOfProperty(PROPID propID, const wchar_t *name)

+{

+  if (propID < 1000)

+  {

+    UString s = LangString(1000 + propID);

+    if (!s.IsEmpty())

+      return s;

+  }

+  if (name)

+    return name;

+  wchar_t temp[16];

+  ConvertUInt32ToString(propID, temp);

+  return temp;

+}

diff --git a/CPP/7zip/UI/FileManager/PropertyName.h b/CPP/7zip/UI/FileManager/PropertyName.h
new file mode 100644
index 0000000..a1061b7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyName.h
@@ -0,0 +1,10 @@
+// PropertyName.h

+

+#ifndef __PROPERTY_NAME_H

+#define __PROPERTY_NAME_H

+

+#include "../../../Common/MyString.h"

+

+UString GetNameOfProperty(PROPID propID, const wchar_t *name);

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
index 67c9b6e..1315b89 100644
--- a/CPP/7zip/UI/FileManager/PropertyNameRes.h
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -90,3 +90,6 @@
 #define IDS_PROP_HARD_LINK        1090

 #define IDS_PROP_INODE            1091

 #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/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
index 4cc99ec..2100e82 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

@@ -250,4 +252,4 @@
 {

   return GetIconIndex(attrib, fileName, NULL);

 }

-*/
\ No newline at end of file
+*/

diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
index 5655c76..2eedc4b 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/resource.h b/CPP/7zip/UI/FileManager/resource.h
index bffdc97..0b282b0 100644
--- a/CPP/7zip/UI/FileManager/resource.h
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -45,6 +45,10 @@
 #define IDM_CREATE_FILE          556

 // #define IDM_EXIT                 557

 #define IDM_LINK                 558

+#define IDM_ALT_STREAMS          559

+

+#define IDM_OPEN_INSIDE_ONE      590

+#define IDM_OPEN_INSIDE_PARSER   591

 

 #define IDM_SELECT_ALL           600

 #define IDM_DESELECT_ALL         601

diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc
index 5fb2b3a..6bda89e 100644
--- a/CPP/7zip/UI/GUI/Extract.rc
+++ b/CPP/7zip/UI/GUI/Extract.rc
@@ -11,8 +11,14 @@
   IDS_CANT_OPEN_ENCRYPTED_ARCHIVE  "Can not open encrypted archive '{0}'. Wrong password?"

   IDS_UNSUPPORTED_ARCHIVE_TYPE  "Unsupported archive type"

 

+  IDS_CANT_OPEN_AS_TYPE   "Can not open the file as {0} archive"

+  IDS_IS_OPEN_AS_TYPE     "The file is open as {0} archive"

+  IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset"

+

   IDS_PROGRESS_EXTRACTING "Extracting"

 

+  IDS_PROGRESS_SKIPPING   "Skipping"

+

   IDS_EXTRACT_SET_FOLDER  "Specify a location for extracted files."

 

   IDS_EXTRACT_PATHS_FULL    "Full pathnames"

@@ -32,7 +38,7 @@
   IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?"

   IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED  "CRC failed in encrypted file '{0}'. Wrong password?"

 

-  IDS_EXTRACT_MSG_WRONG_PSW            "Wrong password?"

+  IDS_EXTRACT_MSG_WRONG_PSW_GUESS      "Wrong password?"

   // IDS_EXTRACT_MSG_ENCRYPTED            "Encrypted file"

 

   IDS_EXTRACT_MSG_UNSUPPORTED_METHOD   "Unsupported compression method"

@@ -43,6 +49,7 @@
   IDS_EXTRACT_MSG_DATA_AFTER_END       "There are some data after the end of the payload data"  

   IDS_EXTRACT_MSG_IS_NOT_ARC           "Is not archive"  

   IDS_EXTRACT_MSG_HEADERS_ERROR        "Headers Error"

+  IDS_EXTRACT_MSG_WRONG_PSW_CLAIM      "Wrong password"

 

   IDS_OPEN_MSG_UNAVAILABLE_START  "Unavailable start of archive"

   IDS_OPEN_MSG_UNCONFIRMED_START  "Unconfirmed start of archive"

diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
index bb0a655..283713d 100644
--- a/CPP/7zip/UI/GUI/ExtractDialog.cpp
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -143,7 +143,7 @@
       GetText(s);

     if (!ArcPath.IsEmpty())

     {

-      s += L" : ";

+      s.AddAscii(" : ");

       s += ArcPath;

     }

     SetText(s);

@@ -253,7 +253,7 @@
 

 bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

 {

-  switch(buttonID)

+  switch (buttonID)

   {

     case IDB_EXTRACT_SET_PATH:

       OnButtonSetPath();

@@ -289,7 +289,7 @@
 void AddUniqueString(UStringVector &list, const UString &s)

 {

   FOR_VECTOR (i, list)

-    if (s.IsEqualToNoCase(list[i]))

+    if (s.IsEqualTo_NoCase(list[i]))

       return;

   list.Add(s);

 }

diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h
index 61737e4..e198796 100644
--- a/CPP/7zip/UI/GUI/ExtractDialogRes.h
+++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h
@@ -18,7 +18,7 @@
 

 #define IDX_EXTRACT_ELIM_DUP        3430

 #define IDX_EXTRACT_NT_SECUR        3431

-// #define IDX_EXTRACT_ALT_STREAMS	    3432

+// #define IDX_EXTRACT_ALT_STREAMS     3432

 

 #define IDX_PASSWORD_SHOW           3803

 #define IDG_PASSWORD                3807

diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
index ff78648..f3b08c2 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.cpp
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -40,20 +40,20 @@
 

 static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)

 {

-  wchar_t sz[32];

-  s += LangString(resourceID);

+  AddLangString(s, resourceID);

   if (addColon)

     s += L':';

-  s += L' ';

+  s.Add_Space();

+  char sz[32];

   ConvertUInt64ToString(value, sz);

-  s += sz;

-  s += L'\n';

+  s.AddAscii(sz);

+  s.Add_LF();

 }

 

 static void AddSizePair(UString &s, UINT resourceID, UInt64 value)

 {

   wchar_t sz[32];

-  s += LangString(resourceID);

+  AddLangString(s, resourceID);

   s += L": ";

   ConvertUInt64ToString(value, sz);

   s += MyFormatNew(IDS_FILE_SIZE, sz);

@@ -65,7 +65,7 @@
     s += sz;

     s += L" MB)";

   }

-  s += L'\n';

+  s.Add_LF();

 }

 

 #endif

@@ -122,7 +122,7 @@
       AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);

       if (Stat.NumAltStreams != 0)

       {

-        s += L'\n';

+        s.Add_LF();

         AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);

         AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);

       }

@@ -130,12 +130,12 @@
     

     if (HashBundle)

     {

-      s += L'\n';

+      s.Add_LF();

       AddHashBundleRes(s, *HashBundle, UString());

     }

     

-    s += L'\n';

-    s += LangString(IDS_MESSAGE_NO_ERRORS);

+    s.Add_LF();

+    AddLangString(s, IDS_MESSAGE_NO_ERRORS);

     

     FinalMessage.OkMessage.Title = Title;

     FinalMessage.OkMessage.Message = s;

@@ -229,7 +229,7 @@
     NName::NormalizeDirPathPrefix(options.OutputDir);

     

     /*

-    if(!CreateComplexDirectory(options.OutputDir))

+    if (!CreateComplexDirectory(options.OutputDir))

     {

       UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));

       UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,

@@ -237,7 +237,9 @@
       0x02000603,

       #endif

       options.OutputDir);

-      MyMessageBox(s2 + UString(L'\n') + s);

+      s2.Add_LF();

+      s2 += s;

+      MyMessageBox(s2);

       return E_FAIL;

     }

     */

diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h
index 407ad19..6437d95 100644
--- a/CPP/7zip/UI/GUI/ExtractRes.h
+++ b/CPP/7zip/UI/GUI/ExtractRes.h
@@ -6,8 +6,14 @@
 #define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006

 #define IDS_UNSUPPORTED_ARCHIVE_TYPE    3007

 

+#define IDS_CANT_OPEN_AS_TYPE           3017

+#define IDS_IS_OPEN_AS_TYPE             3018

+#define IDS_IS_OPEN_WITH_OFFSET         3019

+

 #define IDS_PROGRESS_EXTRACTING         3300

 

+#define IDS_PROGRESS_SKIPPING           3325

+

 #define IDS_EXTRACT_SET_FOLDER          3402

 

 #define IDS_EXTRACT_PATHS_FULL          3411

@@ -27,7 +33,7 @@
 #define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED  3703

 #define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED   3704

 

-#define IDS_EXTRACT_MSG_WRONG_PSW            3710

+#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS      3710

 // #define IDS_EXTRACT_MSG_ENCRYPTED            3711

 

 #define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD   3721

@@ -38,6 +44,7 @@
 #define IDS_EXTRACT_MSG_DATA_AFTER_END       3726

 #define IDS_EXTRACT_MSG_IS_NOT_ARC           3727

 #define IDS_EXTRACT_MSG_HEADERS_ERROR        3728

+#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM      3729

 

 #define IDS_OPEN_MSG_UNAVAILABLE_START       3763

 #define IDS_OPEN_MSG_UNCONFIRMED_START       3764

diff --git a/CPP/Build.mak b/CPP/Build.mak
index 70c9c48..1935ff0 100644
--- a/CPP/Build.mak
+++ b/CPP/Build.mak
@@ -42,7 +42,7 @@
 COMPL_ASM = $(MY_ML) -c -Fo$O/ $**

 !ENDIF

 

-CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR-

+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF

 

 !IFDEF MY_STATIC_LINK

 !IFNDEF MY_SINGLE_THREAD

diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
index 01269c8..42edd8d 100644
--- a/CPP/Common/CommandLineParser.cpp
+++ b/CPP/Common/CommandLineParser.cpp
@@ -11,7 +11,7 @@
     char c = *a;

     if (c == 0)

       return true;

-    if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))

+    if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))

       return false;

     a++;

     u++;

@@ -135,24 +135,28 @@
   switch (form.Type)

   {

     case NSwitchType::kMinus:

-      if (rem != 0)

+      if (rem == 1)

       {

         sw.WithMinus = (s[pos] == '-');

         if (sw.WithMinus)

-          pos++;

+          return true;

+        ErrorMessage = "Incorrect switch postfix:";

+        return false;

       }

       break;

       

     case NSwitchType::kChar:

-      if (rem != 0)

+      if (rem == 1)

       {

         wchar_t c = s[pos];

         if (c <= 0x7F)

         {

           sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);

           if (sw.PostCharIndex >= 0)

-            pos++;

+            return true;

         }

+        ErrorMessage = "Incorrect switch postfix:";

+        return false;

       }

       break;

       

@@ -160,6 +164,7 @@
       sw.PostStrings.Add((const wchar_t *)s + pos);

       return true;

   }

+

   if (pos != s.Len())

   {

     ErrorMessage = "Too long switch:";

diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
index cfa1996..1d9d009 100644
--- a/CPP/Common/CrcReg.cpp
+++ b/CPP/Common/CrcReg.cpp
@@ -7,22 +7,17 @@
 

 #include "../Common/MyCom.h"

 

-#include "../7zip/ICoder.h"

 #include "../7zip/Common/RegisterCodec.h"

 

 EXTERN_C_BEGIN

 

 typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);

 

+UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);

+

 extern CRC_FUNC g_CrcUpdate;

-

-#ifdef MY_CPU_X86_OR_AMD64

-  UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);

-#endif

-

-#ifndef MY_CPU_BE

-  UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);

-#endif

+extern CRC_FUNC g_CrcUpdateT8;

+extern CRC_FUNC g_CrcUpdateT4;

 

 EXTERN_C_END

 

@@ -33,62 +28,42 @@
 {

   UInt32 _crc;

   CRC_FUNC _updateFunc;

+  Byte mtDummy[1 << 7];

+  

   bool SetFunctions(UInt32 tSize);

 public:

   CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }

 

-  MY_UNKNOWN_IMP1(ICompressSetCoderProperties)

-

-  STDMETHOD_(void, Init)();

-  STDMETHOD_(void, Update)(const void *data, UInt32 size);

-  STDMETHOD_(void, Final)(Byte *digest);

-  STDMETHOD_(UInt32, GetDigestSize)();

+  MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties)

+  INTERFACE_IHasher(;)

   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

 };

 

-STDMETHODIMP_(void) CCrcHasher::Init()

-{

-  _crc = CRC_INIT_VAL;

-}

-

-STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size)

-{

-  _crc = _updateFunc(_crc, data, size, g_CrcTable);

-}

-

-STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest)

-{

-  UInt32 val = CRC_GET_DIGEST(_crc);

-  SetUi32(digest, val);

-}

-

-STDMETHODIMP_(UInt32) CCrcHasher::GetDigestSize()

-{

-  return 4;

-}

-

 bool CCrcHasher::SetFunctions(UInt32 tSize)

 {

   _updateFunc = g_CrcUpdate;

-  if (tSize == 4)

+  

+  if (tSize == 1)

+    _updateFunc = CrcUpdateT1;

+  else if (tSize == 4)

   {

-    #ifndef MY_CPU_BE

-    _updateFunc = CrcUpdateT4;

-    #endif

+    if (g_CrcUpdateT4)

+      _updateFunc = g_CrcUpdateT4;

+    else

+      return false;

   }

   else if (tSize == 8)

   {

-    #ifdef MY_CPU_X86_OR_AMD64

-      _updateFunc = CrcUpdateT8;

-    #else

+    if (g_CrcUpdateT8)

+      _updateFunc = g_CrcUpdateT8;

+    else

       return false;

-    #endif

   }

+  

   return true;

 }

 

-STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs,

-    const PROPVARIANT *coderProps, UInt32 numProps)

+STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)

 {

   for (UInt32 i = 0; i < numProps; i++)

   {

@@ -104,8 +79,20 @@
   return S_OK;

 }

 

-static IHasher *CreateHasher() { return new CCrcHasher(); }

+STDMETHODIMP_(void) CCrcHasher::Init() throw()

+{

+  _crc = CRC_INIT_VAL;

+}

 

-static CHasherInfo g_HasherInfo = { CreateHasher, 0x1, L"CRC32", 4 };

+STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) throw()

+{

+  _crc = _updateFunc(_crc, data, size, g_CrcTable);

+}

 

-REGISTER_HASHER(Crc32)

+STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) throw()

+{

+  UInt32 val = CRC_GET_DIGEST(_crc);

+  SetUi32(digest, val);

+}

+

+REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)

diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
index 69b8ece..9416098 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/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
index 92abf99..16c9250 100644
--- a/CPP/Common/DynamicBuffer.h
+++ b/CPP/Common/DynamicBuffer.h
@@ -26,7 +26,8 @@
     }

 

     T *newBuffer = new T[newCap];

-    memcpy(newBuffer, _items, _pos * sizeof(T));

+    if (_pos != 0)

+      memcpy(newBuffer, _items, _pos * sizeof(T));

     delete []_items;

     _items = newBuffer;

     _size = newCap;

@@ -34,8 +35,8 @@
 

 public:

   CDynamicBuffer(): _items(0), _size(0), _pos(0) {}

-  // operator T *() { return _items; };

-  operator const T *() const { return _items; };

+  // operator T *() { return _items; }

+  operator const T *() const { return _items; }

   ~CDynamicBuffer() { delete []_items; }

 

   T *GetCurPtrAndGrow(size_t addSize)

@@ -48,6 +49,11 @@
     return res;

   }

 

+  void AddData(const T *data, size_t size)

+  {

+    memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));

+  }

+

   const size_t GetPos() const { return _pos; }

 

   // void Empty() { _pos = 0; }

diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
index 9850e19..1288216 100644
--- a/CPP/Common/Lang.h
+++ b/CPP/Common/Lang.h
@@ -14,7 +14,7 @@
   bool OpenFromString(const AString &s);

 public:

   CLang(): _text(0) {}

-  ~CLang() { Clear(); };

+  ~CLang() { Clear(); }

   bool Open(CFSTR fileName, const wchar_t *id);

   void Clear() throw();

   const wchar_t *Get(UInt32 id) const throw();

diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
index b0e80b1..b4b84cf 100644
--- a/CPP/Common/ListFileUtils.cpp
+++ b/CPP/Common/ListFileUtils.cpp
@@ -48,7 +48,7 @@
       return false;

     file.Close();

     unsigned num = (unsigned)fileSize / 2;

-    wchar_t *p = u.GetBuffer(num);

+    wchar_t *p = u.GetBuf(num);

     if (codePage == MY__CP_UTF16)

       for (unsigned i = 0; i < num; i++)

       {

@@ -65,20 +65,20 @@
           return false;

         p[i] = c;

       }

-    u.ReleaseBuffer(num);

+    p[num] = 0;

+    u.ReleaseBuf_SetLen(num);

   }

   else

   {

     AString s;

-    char *p = s.GetBuffer((unsigned)fileSize);

+    char *p = s.GetBuf((unsigned)fileSize);

     UInt32 processed;

     if (!file.Read(p, (UInt32)fileSize, processed))

       return false;

     if (processed != fileSize)

       return false;

     file.Close();

-    p[processed] = 0;

-    s.ReleaseBuffer();

+    s.ReleaseBuf_CalcLen((unsigned)processed);

     if (s.Len() != processed)

       return false;

     

diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
index dabdea6..2b5e946 100644
--- a/CPP/Common/MyBuffer.h
+++ b/CPP/Common/MyBuffer.h
@@ -10,15 +10,6 @@
   T *_items;

   size_t _size;

 

-  void CopyToEmpty(const CBuffer &buffer)

-  {

-    if (buffer._size > 0)

-    {

-      _items = new T[buffer._size];

-      memcpy(_items, buffer._items, buffer._size * sizeof(T));

-      _size = buffer._size;

-    }

-  }

 public:

   void Free()

   {

@@ -32,11 +23,21 @@
   

   CBuffer(): _items(0), _size(0) {};

   CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; }

-  CBuffer(const CBuffer &buffer): _items(0), _size(0) { CopyToEmpty(buffer); }

+  CBuffer(const CBuffer &buffer): _items(0), _size(0)

+  {

+    size_t size = buffer._size;

+    if (size != 0)

+    {

+      _items = new T[size];

+      memcpy(_items, buffer._items, size * sizeof(T));

+      _size = size;

+    }

+  }

+

   ~CBuffer() { delete []_items; }

 

-  operator       T *()       { return _items; };

-  operator const T *() const { return _items; };

+  operator       T *()       { return _items; }

+  operator const T *() const { return _items; }

   size_t Size() const { return _size; }

 

   void Alloc(size_t size)

@@ -65,7 +66,8 @@
   void CopyFrom(const T *data, size_t size)

   {

     Alloc(size);

-    memcpy(_items, data, size * sizeof(T));

+    if (size != 0)

+      memcpy(_items, data, size * sizeof(T));

   }

 

   void ChangeSize_KeepData(size_t newSize, size_t keepSize)

@@ -73,11 +75,13 @@
     if (newSize == _size)

       return;

     T *newBuffer = NULL;

-    if (newSize > 0)

+    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;

@@ -86,8 +90,8 @@
 

   CBuffer& operator=(const CBuffer &buffer)

   {

-    Free();

-    CopyToEmpty(buffer);

+    if (&buffer != this)

+      CopyFrom(buffer, buffer._size);

     return *this;

   }

 };

@@ -98,6 +102,8 @@
   size_t size1 = b1.Size();

   if (size1 != b2.Size())

     return false;

+  if (size1 == 0)

+    return true;

   return memcmp(b1, b2, size1 * sizeof(T)) == 0;

 }

 

@@ -105,14 +111,16 @@
 bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)

 {

   size_t size1 = b1.Size();

-  if (size1 == b2.Size())

+  if (size1 != b2.Size())

+    return true;

+  if (size1 == 0)

     return false;

   return memcmp(b1, b2, size1 * sizeof(T)) != 0;

 }

 

 

 typedef CBuffer<char> CCharBuffer;

-typedef CBuffer<wchar_t> CWCharBuffer;

+// typedef CBuffer<wchar_t> CWCharBuffer;

 typedef CBuffer<unsigned char> CByteBuffer;

 

 

@@ -134,8 +142,8 @@
   CObjArray(): _items(0) {};

   ~CObjArray() { delete []_items; }

   

-  operator       T *()       { return _items; };

-  operator const T *() const { return _items; };

+  operator       T *()       { return _items; }

+  operator const T *() const { return _items; }

   

   void Alloc(size_t newSize)

   {

@@ -148,12 +156,11 @@
 typedef CObjArray<unsigned char> CByteArr;

 typedef CObjArray<bool> CBoolArr;

 typedef CObjArray<int> CIntArr;

+typedef CObjArray<unsigned> CUIntArr;

 

-// #define CRecArray CObjArray

 

 template <class T> class CObjArray2

 {

-// protected:

   T *_items;

   unsigned _size;

 

@@ -172,7 +179,7 @@
   CObjArray2(const CObjArray2 &buffer): _items(0), _size(0)

   {

     size_t newSize = buffer._size;

-    if (newSize > 0)

+    if (newSize != 0)

     {

       T *newBuffer = new T[newSize];;

       _items = newBuffer;

@@ -196,8 +203,8 @@
 

   ~CObjArray2() { delete []_items; }

   

-  operator       T *()       { return _items; };

-  operator const T *() const { return _items; };

+  operator       T *()       { return _items; }

+  operator const T *() const { return _items; }

   

   unsigned Size() const { return (unsigned)_size; }

   bool IsEmpty() const { return _size == 0; }

@@ -208,7 +215,7 @@
     if (size == _size)

       return;

     T *newBuffer = NULL;

-    if (size > 0)

+    if (size != 0)

       newBuffer = new T[size];

     delete []_items;

     _items = newBuffer;

@@ -220,7 +227,7 @@
   {

     Free();

     size_t newSize = buffer._size;

-    if (newSize > 0)

+    if (newSize != 0)

     {

       T *newBuffer = new T[newSize];;

       _items = newBuffer;

diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
index 614a083..3e3f8ce 100644
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -76,19 +76,28 @@
 inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)

 {

   *bstr = ::SysAllocString(src);

-  return (*bstr != NULL) ? S_OK : E_OUTOFMEMORY;

+  return (*bstr) ? S_OK : E_OUTOFMEMORY;

 }

 

 class CMyComBSTR

 {

   BSTR m_str;

+

 public:

-  

   CMyComBSTR(): m_str(NULL) {}

+  ~CMyComBSTR() { ::SysFreeString(m_str); }

+  BSTR* operator&() { return &m_str; }

+  operator LPCOLESTR() const { return m_str; }

+  // operator bool() const { return m_str != NULL; }

+  // bool operator!() const { return m_str == NULL; }

+private:

+  // operator BSTR() const { return m_str; }

+

   CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }

   // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }

   // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }

   CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }

+  

   /*

   CMyComBSTR(REFGUID src)

   {

@@ -98,7 +107,7 @@
     CoTaskMemFree(szGuid);

   }

   */

-  ~CMyComBSTR() { ::SysFreeString(m_str); }

+  

   CMyComBSTR& operator=(const CMyComBSTR& src)

   {

     if (m_str != src.m_str)

@@ -109,22 +118,29 @@
     }

     return *this;

   }

+  

   CMyComBSTR& operator=(LPCOLESTR src)

   {

     ::SysFreeString(m_str);

     m_str = ::SysAllocString(src);

     return *this;

   }

-  // unsigned Len() const { return ::SysStringLen(m_str); }

-  operator BSTR() const { return m_str; }

-  BSTR* operator&() { return &m_str; }

+  

+  unsigned Len() const { return ::SysStringLen(m_str); }

+

   BSTR MyCopy() const

   {

-    int byteLen = ::SysStringByteLen(m_str);

+    // We don't support Byte BSTRs here

+    return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));

+    /*

+    UINT byteLen = ::SysStringByteLen(m_str);

     BSTR res = ::SysAllocStringByteLen(NULL, byteLen);

-    memcpy(res, m_str, byteLen);

+    if (res && byteLen != 0 && m_str)

+      memcpy(res, m_str, byteLen);

     return res;

+    */

   }

+  

   /*

   void Attach(BSTR src) { m_str = src; }

   BSTR Detach()

@@ -134,12 +150,12 @@
     return s;

   }

   */

+

   void Empty()

   {

     ::SysFreeString(m_str);

     m_str = NULL;

   }

-  bool operator!() const { return (m_str == NULL); }

 };

 

 //////////////////////////////////////////////////////////

@@ -149,6 +165,8 @@
 public:

   ULONG __m_RefCount;

   CMyUnknownImp(): __m_RefCount(0) {}

+

+  // virtual ~CMyUnknownImp() {};

 };

 

 #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \

@@ -164,7 +182,7 @@
     MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \

     MY_QUERYINTERFACE_ENTRY(i)

 

-#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; AddRef(); return S_OK; }

+#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }

 

 #define MY_ADDREF_RELEASE \

 STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \

@@ -239,4 +257,6 @@
   MY_QUERYINTERFACE_ENTRY(i7) \

   )

 

+const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;

+

 #endif

diff --git a/CPP/Common/MyLinux.h b/CPP/Common/MyLinux.h
new file mode 100644
index 0000000..b4e7605
--- /dev/null
+++ b/CPP/Common/MyLinux.h
@@ -0,0 +1,42 @@
+// MyLinux.h

+

+#ifndef __MY_LIN_LINUX_H

+#define __MY_LIN_LINUX_H

+

+#define MY_LIN_S_IFMT  00170000

+#define MY_LIN_S_IFSOCK 0140000

+#define MY_LIN_S_IFLNK  0120000

+#define MY_LIN_S_IFREG  0100000

+#define MY_LIN_S_IFBLK  0060000

+#define MY_LIN_S_IFDIR  0040000

+#define MY_LIN_S_IFCHR  0020000

+#define MY_LIN_S_IFIFO  0010000

+

+#define MY_LIN_S_ISLNK(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK)

+#define MY_LIN_S_ISREG(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG)

+#define MY_LIN_S_ISDIR(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR)

+#define MY_LIN_S_ISCHR(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR)

+#define MY_LIN_S_ISBLK(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK)

+#define MY_LIN_S_ISFIFO(m)  (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO)

+#define MY_LIN_S_ISSOCK(m)  (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK)

+

+#define MY_LIN_S_ISUID 0004000

+#define MY_LIN_S_ISGID 0002000

+#define MY_LIN_S_ISVTX 0001000

+

+#define MY_LIN_S_IRWXU 00700

+#define MY_LIN_S_IRUSR 00400

+#define MY_LIN_S_IWUSR 00200

+#define MY_LIN_S_IXUSR 00100

+

+#define MY_LIN_S_IRWXG 00070

+#define MY_LIN_S_IRGRP 00040

+#define MY_LIN_S_IWGRP 00020

+#define MY_LIN_S_IXGRP 00010

+

+#define MY_LIN_S_IRWXO 00007

+#define MY_LIN_S_IROTH 00004

+#define MY_LIN_S_IWOTH 00002

+#define MY_LIN_S_IXOTH 00001

+

+#endif

diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index 747a181..75b9326 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>

@@ -65,6 +64,17 @@
 }

 */

 

+void MyStringLower_Ascii(char *s) throw()

+{

+  for (;;)

+  {

+    char c = *s;

+    if (c == 0)

+      return;

+    *s++ = MyCharLower_Ascii(c);

+  }

+}

+

 void MyStringLower_Ascii(wchar_t *s) throw()

 {

   for (;;)

@@ -272,6 +282,17 @@
   }

 }

 

+bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()

+{

+  for (;;)

+  {

+    wchar_t c2 = *s2++; if (c2 == 0) return true;

+    wchar_t c1 = *s1++;

+    if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))

+      return false;

+  }

+}

+

 // NTFS order: uses upper case

 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()

 {

@@ -290,7 +311,8 @@
   }

 }

 

-int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw()

+/*

+int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)

 {

   for (; num != 0; num--)

   {

@@ -307,7 +329,7 @@
   }

   return 0;

 }

-

+*/

 

 // ---------- AString ----------

 

@@ -317,15 +339,27 @@
   MoveItems(index + size, index);

 }

 

+#define k_Alloc_Len_Limit 0x40000000

+

 void AString::ReAlloc(unsigned newLimit)

 {

-  if (newLimit < _len || newLimit >= 0x20000000) throw 20130220;

+  if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;

   // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);

   char *newBuf = MY_STRING_NEW(char, newLimit + 1);

   memcpy(newBuf, _chars, (size_t)(_len + 1)); \

   MY_STRING_DELETE(_chars);

   _chars = newBuf;

+  _limit = newLimit;

+}

 

+void AString::ReAlloc2(unsigned newLimit)

+{

+  if (newLimit >= k_Alloc_Len_Limit) throw 20130220;

+  // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);

+  char *newBuf = MY_STRING_NEW(char, newLimit + 1);

+  newBuf[0] = 0;

+  MY_STRING_DELETE(_chars);

+  _chars = newBuf;

   _limit = newLimit;

 }

 

@@ -477,6 +511,63 @@
   return *this;

 }

 

+void AString::SetFromWStr_if_Ascii(const wchar_t *s)

+{

+  unsigned len = 0;

+  {

+    for (;; len++)

+    {

+      wchar_t c = s[len];

+      if (c == 0)

+        break;

+      if (c >= 0x80)

+        return;

+    }

+  }

+  if (len > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  char *dest = _chars;

+  unsigned i;

+  for (i = 0; i < len; i++)

+    dest[i] = (char)s[i];

+  dest[i] = 0;

+}

+

+/*

+void AString::SetFromBstr_if_Ascii(BSTR s)

+{

+  unsigned len = ::SysStringLen(s);

+  {

+    for (unsigned i = 0; i < len; i++)

+      if (s[i] <= 0 || s[i] >= 0x80)

+        return;

+  }

+  if (len > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  char *dest = _chars;

+  unsigned i;

+  for (i = 0; i < len; i++)

+    dest[i] = (char)s[i];

+  dest[i] = 0;

+}

+*/

+

+void AString::Add_Space() { operator+=(' '); }

+void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }

+void AString::Add_LF() { operator+=('\n'); }

+

 AString &AString::operator+=(const char *s)

 {

   unsigned len = MyStringLen(s);

@@ -503,25 +594,50 @@
     _chars = newBuf;

     _limit = len;

   }

-  memcpy(_chars, s, len);

+  if (len != 0)

+    memcpy(_chars, s, len);

   _chars[len] = 0;

   _len = len;

 }

 

-int AString::Find(const AString &s, unsigned startIndex) const throw()

+void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check

 {

-  if (s.IsEmpty())

+  unsigned i;

+  for (i = 0; i < len; i++)

+    if (s[i] == 0)

+      break;

+  SetFrom(s, i);

+}

+

+int AString::Find(const char *s, unsigned startIndex) const throw()

+{

+  const char *fs = strstr(_chars + startIndex, s);

+  if (!fs)

+    return -1;

+  return (int)(fs - _chars);

+

+  /*

+  if (s[0] == 0)

     return startIndex;

-  for (; startIndex < _len; startIndex++)

+  unsigned len = MyStringLen(s);

+  const char *p = _chars + startIndex;

+  for (;; p++)

   {

-    unsigned j;

-    for (j = 0; j < s._len && startIndex + j < _len; j++)

-      if (_chars[startIndex + j] != s._chars[j])

+    const char c = *p;

+    if (c != s[0])

+    {

+      if (c == 0)

+        return -1;

+      continue;

+    }

+    unsigned i;

+    for (i = 1; i < len; i++)

+      if (p[i] != s[i])

         break;

-    if (j == s._len)

-      return (int)startIndex;

+    if (i == len)

+      return (int)(p - _chars);

   }

-  return -1;

+  */

 }

 

 int AString::ReverseFind(char c) const throw()

@@ -539,6 +655,22 @@
   }

 }

 

+int AString::ReverseFind_PathSepar() const throw()

+{

+  if (_len == 0)

+    return -1;

+  const char *p = _chars + _len - 1;

+  for (;;)

+  {

+    char c = *p;

+    if (IS_PATH_SEPAR(c))

+      return (int)(p - _chars);

+    if (p == _chars)

+      return -1;

+    p--;

+  }

+}

+

 void AString::TrimLeft() throw()

 {

   const char *p = _chars;

@@ -559,15 +691,14 @@
 void AString::TrimRight() throw()

 {

   const char *p = _chars;

-  int i;

-  for (i = _len - 1; i >= 0; i--)

+  unsigned i;

+  for (i = _len; i != 0; i--)

   {

-    char c = p[i];

+    char c = p[i - 1];

     if (c != ' ' && c != '\n' && c != '\t')

       break;

   }

-  i++;

-  if ((unsigned)i != _len)

+  if (i != _len)

   {

     _chars[i] = 0;

     _len = i;

@@ -616,19 +747,28 @@
 

 void AString::RemoveChar(char ch) throw()

 {

-  int pos = Find(ch);

-  if (pos < 0)

-    return;

-  const char *src = _chars;

-  char *dest = _chars + pos;

-  pos++;

-  unsigned len = _len;

-  for (; (unsigned)pos < len; pos++)

+  char *src = _chars;

+  

+  for (;;)

   {

-    char c = src[(unsigned)pos];

+    char c = *src++;

+    if (c == 0)

+      return;

+    if (c == ch)

+      break;

+  }

+

+  char *dest = src - 1;

+  

+  for (;;)

+  {

+    char c = *src++;

+    if (c == 0)

+      break;

     if (c != ch)

       *dest++ = c;

   }

+  

   *dest = 0;

   _len = (unsigned)(dest - _chars);

 }

@@ -645,7 +785,7 @@
     pos = Find(oldChar, pos);

     if (pos < 0)

       break;

-    _chars[pos] = newChar;

+    _chars[(unsigned)pos] = newChar;

     pos++;

     // number++;

   }

@@ -753,13 +893,23 @@
 

 void UString::ReAlloc(unsigned newLimit)

 {

-  if (newLimit < _len || newLimit >= 0x20000000) throw 20130221;

+  if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;

   // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);

   wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);

   wmemcpy(newBuf, _chars, _len + 1);

   MY_STRING_DELETE(_chars);

   _chars = newBuf;

+  _limit = newLimit;

+}

 

+void UString::ReAlloc2(unsigned newLimit)

+{

+  if (newLimit >= k_Alloc_Len_Limit) throw 20130221;

+  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);

+  wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);

+  newBuf[0] = 0;

+  MY_STRING_DELETE(_chars);

+  _chars = newBuf;

   _limit = newLimit;

 }

 

@@ -854,14 +1004,15 @@
 

 UString::UString(const wchar_t *s)

 {

-  SetStartLen(MyStringLen(s));

-  MyStringCopy(_chars, s);

+  unsigned len = MyStringLen(s);

+  SetStartLen(len);

+  wmemcpy(_chars, s, len + 1);

 }

 

 UString::UString(const UString &s)

 {

   SetStartLen(s._len);

-  MyStringCopy(_chars, s._chars);

+  wmemcpy(_chars, s._chars, s._len + 1);

 }

 

 UString &UString::operator=(wchar_t c)

@@ -890,7 +1041,7 @@
     _limit = len;

   }

   _len = len;

-  MyStringCopy(_chars, s);

+  wmemcpy(_chars, s, len + 1);

   return *this;

 }

 

@@ -907,15 +1058,44 @@
     _limit = len;

   }

   _len = len;

-  MyStringCopy(_chars, s._chars);

+  wmemcpy(_chars, s._chars, len + 1);

   return *this;

 }

 

+void UString::SetFromBstr(BSTR s)

+{

+  unsigned len = ::SysStringLen(s);

+  if (len > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  // if (s)

+    wmemcpy(_chars, s, len + 1);

+}

+

+void UString::Add_Space() { operator+=(L' '); }

+void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }

+

+void UString::Add_LF()

+{

+  if (_limit == _len)

+    Grow_1();

+  unsigned len = _len;

+  wchar_t *chars = _chars;

+  chars[len++] = L'\n';

+  chars[len] = 0;

+  _len = len;

+}

+

 UString &UString::operator+=(const wchar_t *s)

 {

   unsigned len = MyStringLen(s);

   Grow(len);

-  MyStringCopy(_chars + _len, s);

+  wmemcpy(_chars + _len, s, len + 1);

   _len += len;

   return *this;

 }

@@ -923,7 +1103,7 @@
 UString &UString::operator+=(const UString &s)

 {

   Grow(s._len);

-  MyStringCopy(_chars + _len, s._chars);

+  wmemcpy(_chars + _len, s._chars, s._len + 1);

   _len += s._len;

   return *this;

 }

@@ -937,7 +1117,8 @@
     _chars = newBuf;

     _limit = len;

   }

-  wmemcpy(_chars, s, len);

+  if (len != 0)

+    wmemcpy(_chars, s, len);

   _chars[len] = 0;

   _len = len;

 }

@@ -954,38 +1135,53 @@
   }

   wchar_t *chars = _chars;

   for (unsigned i = 0; i < len; i++)

-    chars[i] = s[i];

+    chars[i] = (unsigned char)s[i];

   chars[len] = 0;

   _len = len;

 }

 

-void UString::AddAsciiStr(const char *s)

+void UString::AddAscii(const char *s)

 {

   unsigned len = MyStringLen(s);

   Grow(len);

   wchar_t *chars = _chars + _len;

   for (unsigned i = 0; i < len; i++)

-    chars[i] = s[i];

+    chars[i] = (unsigned char)s[i];

   chars[len] = 0;

   _len += len;

 }

 

 

 

-int UString::Find(const UString &s, unsigned startIndex) const throw()

+int UString::Find(const wchar_t *s, unsigned startIndex) const throw()

 {

-  if (s.IsEmpty())

+  const wchar_t *fs = wcsstr(_chars + startIndex, s);

+  if (!fs)

+    return -1;

+  return (int)(fs - _chars);

+

+  /*

+  if (s[0] == 0)

     return startIndex;

-  for (; startIndex < _len; startIndex++)

+  unsigned len = MyStringLen(s);

+  const wchar_t *p = _chars + startIndex;

+  for (;; p++)

   {

-    unsigned j;

-    for (j = 0; j < s._len && startIndex + j < _len; j++)

-      if (_chars[startIndex + j] != s._chars[j])

+    const wchar_t c = *p;

+    if (c != s[0])

+    {

+      if (c == 0)

+        return -1;

+      continue;

+    }

+    unsigned i;

+    for (i = 1; i < len; i++)

+      if (p[i] != s[i])

         break;

-    if (j == s._len)

-      return (int)startIndex;

+    if (i == len)

+      return (int)(p - _chars);

   }

-  return -1;

+  */

 }

 

 int UString::ReverseFind(wchar_t c) const throw()

@@ -1003,6 +1199,22 @@
   }

 }

 

+int UString::ReverseFind_PathSepar() const throw()

+{

+  if (_len == 0)

+    return -1;

+  const wchar_t *p = _chars + _len - 1;

+  for (;;)

+  {

+    wchar_t c = *p;

+    if (IS_PATH_SEPAR(c))

+      return (int)(p - _chars);

+    if (p == _chars)

+      return -1;

+    p--;

+  }

+}

+

 void UString::TrimLeft() throw()

 {

   const wchar_t *p = _chars;

@@ -1023,15 +1235,14 @@
 void UString::TrimRight() throw()

 {

   const wchar_t *p = _chars;

-  int i;

-  for (i = _len - 1; i >= 0; i--)

+  unsigned i;

+  for (i = _len; i != 0; i--)

   {

-    wchar_t c = p[i];

+    wchar_t c = p[i - 1];

     if (c != ' ' && c != '\n' && c != '\t')

       break;

   }

-  i++;

-  if ((unsigned)i != _len)

+  if (i != _len)

   {

     _chars[i] = 0;

     _len = i;

@@ -1080,19 +1291,28 @@
 

 void UString::RemoveChar(wchar_t ch) throw()

 {

-  int pos = Find(ch);

-  if (pos < 0)

-    return;

-  const wchar_t *src = _chars;

-  wchar_t *dest = _chars + pos;

-  pos++;

-  unsigned len = _len;

-  for (; (unsigned)pos < len; pos++)

+  wchar_t *src = _chars;

+  

+  for (;;)

   {

-    wchar_t c = src[(unsigned)pos];

+    wchar_t c = *src++;

+    if (c == 0)

+      return;

+    if (c == ch)

+      break;

+  }

+

+  wchar_t *dest = src - 1;

+  

+  for (;;)

+  {

+    wchar_t c = *src++;

+    if (c == 0)

+      break;

     if (c != ch)

       *dest++ = c;

   }

+  

   *dest = 0;

   _len = (unsigned)(dest - _chars);

 }

@@ -1109,7 +1329,7 @@
     pos = Find(oldChar, pos);

     if (pos < 0)

       break;

-    _chars[pos] = newChar;

+    _chars[(unsigned)pos] = newChar;

     pos++;

     // number++;

   }

@@ -1166,6 +1386,135 @@
 }

 

 

+// ---------- UString2 ----------

+

+void UString2::ReAlloc2(unsigned newLimit)

+{

+  if (newLimit >= k_Alloc_Len_Limit) throw 20130221;

+  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);

+  _chars = MY_STRING_NEW(wchar_t, newLimit + 1);

+}

+

+void UString2::SetStartLen(unsigned len)

+{

+  _chars = 0;

+  _chars = MY_STRING_NEW(wchar_t, len + 1);

+  _len = len;

+}

+

+

+/*

+UString2::UString2(wchar_t c)

+{

+  SetStartLen(1);

+  _chars[0] = c;

+  _chars[1] = 0;

+}

+*/

+

+UString2::UString2(const wchar_t *s)

+{

+  unsigned len = MyStringLen(s);

+  SetStartLen(len);

+  wmemcpy(_chars, s, len + 1);

+}

+

+UString2::UString2(const UString2 &s): _chars(NULL), _len(0)

+{

+  if (s._chars)

+  {

+    SetStartLen(s._len);

+    wmemcpy(_chars, s._chars, s._len + 1);

+  }

+}

+

+/*

+UString2 &UString2::operator=(wchar_t c)

+{

+  if (1 > _len)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);

+    if (_chars)

+      MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+  }

+  _len = 1;

+  _chars[0] = c;

+  _chars[1] = 0;

+  return *this;

+}

+*/

+

+UString2 &UString2::operator=(const wchar_t *s)

+{

+  unsigned len = MyStringLen(s);

+  if (len > _len)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    if (_chars)

+      MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+  }

+  _len = len;

+  MyStringCopy(_chars, s);

+  return *this;

+}

+

+void UString2::SetFromAscii(const char *s)

+{

+  unsigned len = MyStringLen(s);

+  if (len > _len)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    if (_chars)

+      MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+  }

+  wchar_t *chars = _chars;

+  for (unsigned i = 0; i < len; i++)

+    chars[i] = (unsigned char)s[i];

+  chars[len] = 0;

+  _len = len;

+}

+

+UString2 &UString2::operator=(const UString2 &s)

+{

+  if (&s == this)

+    return *this;

+  unsigned len = s._len;

+  if (len > _len)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    if (_chars)

+      MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+  }

+  _len = len;

+  MyStringCopy(_chars, s._chars);

+  return *this;

+}

+

+bool operator==(const UString2 &s1, const UString2 &s2)

+{

+  return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);

+}

+

+bool operator==(const UString2 &s1, const wchar_t *s2)

+{

+  if (s1.IsEmpty())

+    return (*s2 == 0);

+  return wcscmp(s1.GetRawPtr(), s2) == 0;

+}

+

+bool operator==(const wchar_t *s1, const UString2 &s2)

+{

+  if (s2.IsEmpty())

+    return (*s1 == 0);

+  return wcscmp(s1, s2.GetRawPtr()) == 0;

+}

+

+

+

 // ----------------------------------------

 

 /*

diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index 018acce..be848e4 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -10,9 +10,19 @@
 #include <wchar.h>

 #endif

 

+#include "MyWindows.h"

 #include "MyTypes.h"

 #include "MyVector.h"

 

+#ifdef _WIN32

+#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')

+#else

+#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)

+#endif

+

+inline bool IsPathSepar(char    c) { return IS_PATH_SEPAR(c); }

+inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }

+

 inline unsigned MyStringLen(const char *s)

 {

   unsigned i;

@@ -50,6 +60,21 @@
   while ((*dest++ = *src++) != 0);

 }

 

+/*

+inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)

+{

+  for (;;)

+  {

+    wchar_t c = *src;

+    *dest = c;

+    if (c == 0)

+      return dest;

+    src++;

+    dest++;

+  }

+}

+*/

+

 int FindCharPosInString(const char *s, char c) throw();

 int FindCharPosInString(const wchar_t *s, wchar_t c) throw();

 

@@ -81,7 +106,7 @@
 inline char MyCharLower_Ascii(char c)

 {

   if (c >= 'A' && c <= 'Z')

-    return (char)(c + 0x20);

+    return (char)((unsigned char)c + 0x20);

   return c;

 }

 

@@ -134,6 +159,7 @@
 // char *MyStringLower(char *s) throw();

 

 // void MyStringUpper_Ascii(wchar_t *s) throw();

+void MyStringLower_Ascii(char *s) throw();

 void MyStringLower_Ascii(wchar_t *s) throw();

 // wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;

 // wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;

@@ -142,9 +168,10 @@
 

 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();

 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();

+bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();

 

 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();

-int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();

+// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();

 

 // ---------- ASCII ----------

 // char values in ASCII strings must be less then 128

@@ -170,6 +197,7 @@
   void InsertSpace(unsigned &index, unsigned size);

   

   void ReAlloc(unsigned newLimit);

+  void ReAlloc2(unsigned newLimit);

   void SetStartLen(unsigned len);

   void Grow_1();

   void Grow(unsigned n);

@@ -186,6 +214,17 @@
   friend AString operator+(const AString &s1, const char    *s2);

   friend AString operator+(const char    *s1, const AString &s2);

 

+  // ---------- forbidden functions ----------

+  AString &operator+=(wchar_t c);

+  AString &operator=(wchar_t c);

+  AString(wchar_t c);

+  void Find(wchar_t c) const;

+  void Find(wchar_t c, unsigned startIndex) const;

+  void ReverseFind(wchar_t c) const;

+  void InsertAtFront(wchar_t c);

+  void RemoveChar(wchar_t ch);

+  void Replace(wchar_t oldChar, wchar_t newChar);

+

 public:

   AString();

   AString(char c);

@@ -205,20 +244,39 @@
 

   void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }

 

-  // The minimum size of the character buffer in characters.

-  // This value does not include space for a null terminator.

-  char *GetBuffer(unsigned minBufLen)

+  /* GetBuf(minLen): provides the buffer that can store

+     at least (minLen) characters and additional null terminator.

+     9.35: GetBuf doesn't preserve old characters and terminator */

+  char *GetBuf(unsigned minLen)

   {

-    if (minBufLen > _limit)

-      ReAlloc(minBufLen);

+    if (minLen > _limit)

+      ReAlloc2(minLen);

     return _chars;

   }

-  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }

-  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

+  char *GetBuf_SetEnd(unsigned minLen)

+  {

+    if (minLen > _limit)

+      ReAlloc2(minLen);

+    char *chars = _chars;

+    chars[minLen] = 0;

+    _len = minLen;

+    return chars;

+  }

+

+  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }

+  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

+  void ReleaseBuf_CalcLen(unsigned maxLen)

+  {

+    char *chars = _chars;

+    chars[maxLen] = 0;

+    _len = MyStringLen(chars);

+  }

 

   AString &operator=(char c);

   AString &operator=(const char *s);

   AString &operator=(const AString &s);

+  void SetFromWStr_if_Ascii(const wchar_t *s);

+  // void SetFromBstr_if_Ascii(BSTR s);

 

   AString &operator+=(char c)

   {

@@ -231,18 +289,30 @@
     _len = len;

     return *this;

   }

+  

+  void Add_Space();

+  void Add_Space_if_NotEmpty();

+  void Add_LF();

+  void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }

 

   AString &operator+=(const char *s);

   AString &operator+=(const AString &s);

+  void AddAscii(const char *s) { operator+=(s); }

 

   void SetFrom(const char *s, unsigned len); // no check

-  // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }

+  void SetFrom_CalcLen(const char *s, unsigned len);

+  // void SetFromAscii(const char *s) { operator+=(s); }

+

+  AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }

   AString Left(unsigned count) const { return AString(count, *this); }

 

   // void MakeUpper() { MyStringUpper(_chars); }

   // void MakeLower() { MyStringLower(_chars); }

+  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }

 

 

+  bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }

+  bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }

   // int Compare(const char *s) const { return MyStringCompare(_chars, s); }

   // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }

   // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }

@@ -250,16 +320,29 @@
   bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }

   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();

  

+  bool IsAscii() const

+  {

+    unsigned len = Len();

+    const char *s = _chars;

+    for (unsigned i = 0; i < len; i++)

+      if ((unsigned char)s[i] >= 0x80)

+        return false;

+    return true;

+  }

   int Find(char c) const { return FindCharPosInString(_chars, c); }

   int Find(char c, unsigned startIndex) const

   {

     int pos = FindCharPosInString(_chars + startIndex, c);

     return pos < 0 ? -1 : (int)startIndex + pos;

   }

+  

   int ReverseFind(char c) const throw();

-  int Find(const AString &s) const { return Find(s, 0); }

-  int Find(const AString &s, unsigned startIndex) const throw();

+  int ReverseFind_Dot() const throw() { return ReverseFind('.'); }

+  int ReverseFind_PathSepar() const throw();

 

+  int Find(const char *s) const { return Find(s, 0); }

+  int Find(const char *s, unsigned startIndex) const throw();

+  

   void TrimLeft() throw();

   void TrimRight() throw();

   void Trim()

@@ -274,9 +357,10 @@
   void Insert(unsigned index, const AString &s);

 

   void RemoveChar(char ch) throw();

+  

   void Replace(char oldChar, char newChar) throw();

   void Replace(const AString &oldString, const AString &newString);

-  

+

   void Delete(unsigned index) throw();

   void Delete(unsigned index, unsigned count) throw();

   void DeleteFrontal(unsigned num) throw();

@@ -312,6 +396,19 @@
 inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }

 inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }

 

+// ---------- forbidden functions ----------

+

+void operator==(char c1, const AString &s2);

+void operator==(const AString &s1, char c2);

+

+void operator+(char c, const AString &s); // this function can be OK, but we don't use it

+

+void operator+(const AString &s, int c);

+void operator+(const AString &s, unsigned c);

+void operator+(int c, const AString &s);

+void operator+(unsigned c, const AString &s);

+void operator-(const AString &s, int c);

+void operator-(const AString &s, unsigned c);

 

 

 class UString

@@ -328,6 +425,7 @@
   void InsertSpace(unsigned index, unsigned size);

   

   void ReAlloc(unsigned newLimit);

+  void ReAlloc2(unsigned newLimit);

   void SetStartLen(unsigned len);

   void Grow_1();

   void Grow(unsigned n);

@@ -344,6 +442,27 @@
   friend UString operator+(const UString &s1, const wchar_t *s2);

   friend UString operator+(const wchar_t *s1, const UString &s2);

 

+  // ---------- forbidden functions ----------

+  

+  UString &operator+=(char c);

+  UString &operator+=(unsigned char c);

+  UString &operator=(char c);

+  UString &operator=(unsigned char c);

+  UString(char c);

+  UString(unsigned char c);

+  void Find(char c) const;

+  void Find(unsigned char c) const;

+  void Find(char c, unsigned startIndex) const;

+  void Find(unsigned char c, unsigned startIndex) const;

+  void ReverseFind(char c) const;

+  void ReverseFind(unsigned char c) const;

+  void InsertAtFront(char c);

+  void InsertAtFront(unsigned char c);

+  void RemoveChar(char ch);

+  void RemoveChar(unsigned char ch);

+  void Replace(char oldChar, char newChar);

+  void Replace(unsigned char oldChar, unsigned char newChar);

+

 public:

   UString();

   UString(wchar_t c);

@@ -363,20 +482,35 @@
 

   void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }

 

-  // The minimum size of the character buffer in characters.

-  // This value does not include space for a null terminator.

-  wchar_t *GetBuffer(unsigned minBufLen)

+  wchar_t *GetBuf(unsigned minLen)

   {

-    if (minBufLen > _limit)

-      ReAlloc(minBufLen);

+    if (minLen > _limit)

+      ReAlloc2(minLen);

     return _chars;

   }

-  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }

-  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

+  wchar_t *GetBuf_SetEnd(unsigned minLen)

+  {

+    if (minLen > _limit)

+      ReAlloc2(minLen);

+    wchar_t *chars = _chars;

+    chars[minLen] = 0;

+    _len = minLen;

+    return chars;

+  }

+

+  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }

+  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

+  void ReleaseBuf_CalcLen(unsigned maxLen)

+  {

+    wchar_t *chars = _chars;

+    chars[maxLen] = 0;

+    _len = MyStringLen(chars);

+  }

 

   UString &operator=(wchar_t c);

   UString &operator=(const wchar_t *s);

   UString &operator=(const UString &s);

+  void SetFromBstr(BSTR s);

 

   UString &operator+=(wchar_t c)

   {

@@ -390,13 +524,18 @@
     return *this;

   }

 

+  void Add_Space();

+  void Add_Space_if_NotEmpty();

+  void Add_LF();

+  void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }

+

   UString &operator+=(const wchar_t *s);

   UString &operator+=(const UString &s);

 

   void SetFrom(const wchar_t *s, unsigned len); // no check

 

   void SetFromAscii(const char *s);

-  void AddAsciiStr(const char *s);

+  void AddAscii(const char *s);

 

   UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }

   UString Left(unsigned count) const { return UString(count, *this); }

@@ -407,23 +546,38 @@
   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }

 

   bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }

-  bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }

+  bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }

+  bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }

   int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }

   // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }

   // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }

   // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }

-  bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); };

+  bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }

+  bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }

   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();

 

+  bool IsAscii() const

+  {

+    unsigned len = Len();

+    const wchar_t *s = _chars;

+    for (unsigned i = 0; i < len; i++)

+      if (s[i] >= 0x80)

+        return false;

+    return true;

+  }

   int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }

   int Find(wchar_t c, unsigned startIndex) const

   {

     int pos = FindCharPosInString(_chars + startIndex, c);

     return pos < 0 ? -1 : (int)startIndex + pos;

   }

-  int Find(const UString &s) const { return Find(s, 0); }

-  int Find(const UString &s, unsigned startIndex) const throw();

+

   int ReverseFind(wchar_t c) const throw();

+  int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }

+  int ReverseFind_PathSepar() const throw();

+

+  int Find(const wchar_t *s) const { return Find(s, 0); }

+  int Find(const wchar_t *s, unsigned startIndex) const throw();

 

   void TrimLeft() throw();

   void TrimRight() throw();

@@ -439,9 +593,10 @@
   void Insert(unsigned index, const UString &s);

 

   void RemoveChar(wchar_t ch) throw();

+  

   void Replace(wchar_t oldChar, wchar_t newChar) throw();

   void Replace(const UString &oldString, const UString &newString);

-  

+

   void Delete(unsigned index) throw();

   void Delete(unsigned index, unsigned count) throw();

   void DeleteFrontal(unsigned num) throw();

@@ -468,6 +623,110 @@
 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }

 

 

+// ---------- forbidden functions ----------

+

+void operator==(wchar_t c1, const UString &s2);

+void operator==(const UString &s1, wchar_t c2);

+

+void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it

+

+void operator+(const UString &s, char c);

+void operator+(const UString &s, unsigned char c);

+void operator+(char c, const UString &s);

+void operator+(unsigned char c, const UString &s);

+void operator-(const UString &s1, wchar_t c);

+

+#ifdef _WIN32

+// can we forbid these functions, if wchar_t is 32-bit ?

+void operator+(const UString &s, int c);

+void operator+(const UString &s, unsigned c);

+void operator+(int c, const UString &s);

+void operator+(unsigned c, const UString &s);

+void operator-(const UString &s1, int c);

+void operator-(const UString &s1, unsigned c);

+#endif

+

+

+

+

+

+

+

+class UString2

+{

+  wchar_t *_chars;

+  unsigned _len;

+

+  void ReAlloc2(unsigned newLimit);

+  void SetStartLen(unsigned len);

+

+  // ---------- forbidden functions ----------

+  

+  UString2 &operator=(char c);

+  UString2 &operator=(unsigned char c);

+  UString2 &operator=(wchar_t c);

+  UString2(char c);

+  UString2(unsigned char c);

+

+public:

+  UString2(): _chars(NULL), _len(0) {}

+  // UString2(wchar_t c);

+  UString2(const wchar_t *s);

+  UString2(const UString2 &s);

+  ~UString2() { if (_chars) MY_STRING_DELETE(_chars); }

+

+  unsigned Len() const { return _len; }

+  bool IsEmpty() const { return _len == 0; }

+  // void Empty() { _len = 0; _chars[0] = 0; }

+

+  // operator const wchar_t *() const { return _chars; }

+  const wchar_t *GetRawPtr() const { return _chars; }

+

+  wchar_t *GetBuf(unsigned minLen)

+  {

+    if (!_chars || minLen > _len)

+      ReAlloc2(minLen);

+    return _chars;

+  }

+  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }

+

+  UString2 &operator=(const wchar_t *s);

+  UString2 &operator=(const UString2 &s);

+  void SetFromAscii(const char *s);

+};

+

+bool operator==(const UString2 &s1, const UString2 &s2);

+bool operator==(const UString2 &s1, const wchar_t *s2);

+bool operator==(const wchar_t *s1, const UString2 &s2);

+

+inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }

+inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }

+inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }

+

+

+// ---------- forbidden functions ----------

+

+void operator==(wchar_t c1, const UString2 &s2);

+void operator==(const UString2 &s1, wchar_t c2);

+bool operator<(const UString2 &s1, const UString2 &s2);

+bool operator>(const UString2 &s1, const UString2 &s2);

+

+void operator+(const UString2 &s1, const UString2 &s2);

+void operator+(const UString2 &s1, const wchar_t *s2);

+void operator+(const wchar_t *s1, const UString2 &s2);

+void operator+(wchar_t c, const UString2 &s);

+void operator+(const UString2 &s, wchar_t c);

+void operator+(const UString2 &s, char c);

+void operator+(const UString2 &s, unsigned char c);

+void operator+(char c, const UString2 &s);

+void operator+(unsigned char c, const UString2 &s);

+void operator-(const UString2 &s1, wchar_t c);

+

+

+

+

+

+

 typedef CObjectVector<AString> AStringVector;

 typedef CObjectVector<UString> UStringVector;

 

diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
index f49739c..6e73aca 100644
--- a/CPP/Common/MyTypes.h
+++ b/CPP/Common/MyTypes.h
@@ -27,4 +27,9 @@
   }

 };

 

+#define CLASS_NO_COPY(cls) \

+  private: \

+  cls(const cls &); \

+  cls &operator=(const cls &);

+

 #endif

diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
index 7935124..b1d476f 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 521aa23..4bc91d5 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

 {

@@ -12,7 +14,7 @@
   

   void MoveItems(unsigned destIndex, unsigned srcIndex)

   {

-    memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * (size_t)sizeof(T));

+    memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));

   }

 

   void ReserveOnePosition()

@@ -21,7 +23,8 @@
     {

       unsigned newCapacity = _capacity + (_capacity >> 2) + 1;

       T *p = new T[newCapacity];

-      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      if (_size != 0)

+        memcpy(p, _items, (size_t)_size * sizeof(T));

       delete []_items;

       _items = p;

       _capacity = newCapacity;

@@ -40,7 +43,7 @@
       _items = new T[size];

       _size = size;

       _capacity = size;

-      memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));

+      memcpy(_items, v._items, (size_t)size * sizeof(T));

     }

   }

   

@@ -61,7 +64,8 @@
     if (newCapacity > _capacity)

     {

       T *p = new T[newCapacity];

-      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      if (_size != 0)

+        memcpy(p, _items, (size_t)_size * sizeof(T));

       delete []_items;

       _items = p;

       _capacity = newCapacity;

@@ -92,7 +96,8 @@
     if (newSize > _capacity)

     {

       T *p = new T[newSize];

-      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      if (_size != 0)

+        memcpy(p, _items, (size_t)_size * sizeof(T));

       delete []_items;

       _items = p;

       _capacity = newSize;

@@ -108,7 +113,7 @@
     if (_size != 0)

     {

       p = new T[_size];

-      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      memcpy(p, _items, (size_t)_size * sizeof(T));

     }

     delete []_items;

     _items = p;

@@ -163,6 +168,8 @@
 

   CRecordVector& operator=(const CRecordVector &v)

   {

+    if (&v == this)

+      return *this;

     unsigned size = v.Size();

     if (size > _capacity)

     {

@@ -174,7 +181,8 @@
       _capacity = size;

     }

     _size = size;

-    memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));

+    if (size != 0)

+      memcpy(_items, v._items, (size_t)size * sizeof(T));

     return *this;

   }

 

@@ -182,7 +190,8 @@
   {

     unsigned size = v.Size();

     Reserve(_size + size);

-    memcpy(_items + _size, v._items, (size_t)size * (size_t)sizeof(T));

+    if (size != 0)

+      memcpy(_items + _size, v._items, (size_t)size * sizeof(T));

     _size += size;

     return *this;

   }

@@ -212,7 +221,7 @@
     if (index != 0)

     {

       T temp = _items[index];

-      memmove(_items + 1, _items, (size_t)index * (size_t)sizeof(T));

+      memmove(_items + 1, _items, (size_t)index * sizeof(T));

       _items[0] = temp;

     }

   }

@@ -421,6 +430,8 @@
   }

   CObjectVector& operator=(const CObjectVector &v)

   {

+    if (&v == this)

+      return *this;

     Clear();

     unsigned size = v.Size();

     _v.Reserve(size);

diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
index f004889..2dfa289 100644
--- a/CPP/Common/NewHandler.cpp
+++ b/CPP/Common/NewHandler.cpp
@@ -31,7 +31,8 @@
 void * my_Realloc(void *p, size_t newSize, size_t oldSize)

 {

   void *newBuf = my_new(newSize);

-  memcpy(newBuf, p, oldSize);

+  if (oldSize != 0)

+    memcpy(newBuf, p, oldSize);

   my_delete(p);

   return newBuf;

 }

@@ -108,7 +109,7 @@
   }

   if (p == 0)

     throw CNewException();

-  printf("Alloc %6d, size = %8d\n", numAllocs, size);

+  printf("Alloc %6d, size = %8u\n", numAllocs, (unsigned)size);

   return p;

 }

 

diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
index d1f4a14..f6ca552 100644
--- a/CPP/Common/NewHandler.h
+++ b/CPP/Common/NewHandler.h
@@ -21,6 +21,7 @@
 Also we declare delete(void *p) throw() that creates smaller code.

 */

 

+#include <stddef.h>

 

 class CNewException {};

 

diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp
index eaab65c..14a3652 100644
--- a/CPP/Common/Sha256Reg.cpp
+++ b/CPP/Common/Sha256Reg.cpp
@@ -6,7 +6,6 @@
 

 #include "../Common/MyCom.h"

 

-#include "../7zip/ICoder.h"

 #include "../7zip/Common/RegisterCodec.h"

 

 class CSha256Hasher:

@@ -14,39 +13,28 @@
   public CMyUnknownImp

 {

   CSha256 _sha;

+  Byte mtDummy[1 << 7];

+

 public:

-  CSha256Hasher() { Init(); };

+  CSha256Hasher() { Sha256_Init(&_sha); }

 

-  MY_UNKNOWN_IMP

-

-  STDMETHOD_(void, Init)();

-  STDMETHOD_(void, Update)(const void *data, UInt32 size);

-  STDMETHOD_(void, Final)(Byte *digest);

-  STDMETHOD_(UInt32, GetDigestSize)();

+  MY_UNKNOWN_IMP1(IHasher)

+  INTERFACE_IHasher(;)

 };

 

-STDMETHODIMP_(void) CSha256Hasher::Init()

+STDMETHODIMP_(void) CSha256Hasher::Init() throw()

 {

   Sha256_Init(&_sha);

 }

 

-STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size)

+STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw()

 {

   Sha256_Update(&_sha, (const Byte *)data, size);

 }

 

-STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest)

+STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw()

 {

   Sha256_Final(&_sha, digest);

 }

 

-STDMETHODIMP_(UInt32) CSha256Hasher::GetDigestSize()

-{

-  return SHA256_DIGEST_SIZE;

-}

-

-static IHasher *CreateHasher() { return new CSha256Hasher; }

-

-static CHasherInfo g_HasherInfo = { CreateHasher, 0xA, L"SHA256", SHA256_DIGEST_SIZE };

-

-REGISTER_HASHER(Sha256)

+REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)

diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
index 4ade958..45738b2 100644
--- a/CPP/Common/StdOutStream.h
+++ b/CPP/Common/StdOutStream.h
@@ -39,7 +39,7 @@
 

   CStdOutStream & operator<<(char c) throw()

   {

-    fputc(c, _stream);

+    fputc((unsigned char)c, _stream);

     return *this;

   }

 

diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
index 825b16f..ae66d14 100644
--- a/CPP/Common/StringConvert.cpp
+++ b/CPP/Common/StringConvert.cpp
@@ -8,158 +8,306 @@
 #include <stdlib.h>

 #endif

 

+static const char k_DefultChar = '_';

+

 #ifdef _WIN32

-UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)

-{

-  UString resultString;

-  if (!srcString.IsEmpty())

-  {

-    int numChars = MultiByteToWideChar(codePage, 0, srcString,

-        srcString.Len(), resultString.GetBuffer(srcString.Len()),

-        srcString.Len() + 1);

-    if (numChars == 0)

-      throw 282228;

-    resultString.ReleaseBuffer(numChars);

-  }

-  return resultString;

-}

 

-void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage)

+/*

+MultiByteToWideChar(CodePage, DWORD dwFlags,

+    LPCSTR lpMultiByteStr, int cbMultiByte,

+    LPWSTR lpWideCharStr, int cchWideChar)

+

+  if (cbMultiByte == 0)

+    return: 0. ERR: ERROR_INVALID_PARAMETER

+

+  if (cchWideChar == 0)

+    return: the required buffer size in characters.

+

+  if (supplied buffer size was not large enough)

+    return: 0. ERR: ERROR_INSUFFICIENT_BUFFER

+    The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)

+

+  If there are illegal characters:

+    if MB_ERR_INVALID_CHARS is set in dwFlags:

+      - the function stops conversion on illegal character.

+      - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.

+    

+    if MB_ERR_INVALID_CHARS is NOT set in dwFlags:

+      before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.

+      in Vista+:    illegal character is not dropped (MSDN). Undocumented: illegal

+                    character is converted to U+FFFD, which is REPLACEMENT CHARACTER.

+*/

+

+

+void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)

 {

   dest.Empty();

-  if (!srcString.IsEmpty())

+  if (src.IsEmpty())

+    return;

   {

-    wchar_t *destBuf = dest.GetBuffer(srcString.Len());

-    const char *sp = (const char *)srcString;

+    /*

+    wchar_t *d = dest.GetBuf(src.Len());

+    const char *s = (const char *)src;

     unsigned i;

+    

     for (i = 0;;)

     {

-      char c = sp[i];

-      if ((Byte)c >= 0x80 || c == 0)

-        break;

-      destBuf[i++] = (wchar_t)c;

-    }

-

-    if (i != srcString.Len())

-    {

-      unsigned numChars = MultiByteToWideChar(codePage, 0, sp + i,

-          srcString.Len() - i, destBuf + i,

-          srcString.Len() + 1 - i);

-      if (numChars == 0)

-        throw 282228;

-      i += numChars;

-    }

-    dest.ReleaseBuffer(i);

-  }

-}

-

-void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

-{

-  dest.Empty();

-  defaultCharWasUsed = false;

-  if (!s.IsEmpty())

-  {

-    unsigned numRequiredBytes = s.Len() * 2;

-    char *destBuf = dest.GetBuffer(numRequiredBytes);

-    unsigned i;

-    const wchar_t *sp = (const wchar_t *)s;

-    for (i = 0;;)

-    {

-      wchar_t c = sp[i];

+      Byte c = (Byte)s[i];

       if (c >= 0x80 || c == 0)

         break;

-      destBuf[i++] = (char)c;

+      d[i++] = (wchar_t)c;

     }

-    defaultCharWasUsed = false;

-    if (i != s.Len())

+

+    if (i != src.Len())

     {

-      BOOL defUsed;

-      unsigned numChars = WideCharToMultiByte(codePage, 0, sp + i, s.Len() - i,

-          destBuf + i, numRequiredBytes + 1 - i,

-          &defaultChar, &defUsed);

-      defaultCharWasUsed = (defUsed != FALSE);

-      if (numChars == 0)

-        throw 282229;

-      i += numChars;

+      unsigned len = MultiByteToWideChar(codePage, 0, s + i,

+          src.Len() - i, d + i,

+          src.Len() + 1 - i);

+      if (len == 0)

+        throw 282228;

+      i += len;

     }

-    dest.ReleaseBuffer(i);

+

+    d[i] = 0;

+    dest.ReleaseBuf_SetLen(i);

+    */

+    unsigned len = MultiByteToWideChar(codePage, 0, src, src.Len(), NULL, 0);

+    if (len == 0)

+    {

+      if (GetLastError() != 0)

+        throw 282228;

+    }

+    else

+    {

+      len = MultiByteToWideChar(codePage, 0, src, src.Len(), dest.GetBuf(len), len);

+      if (len == 0)

+        throw 282228;

+      dest.ReleaseBuf_SetEnd(len);

+    }

   }

 }

 

-void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage)

+/*

+  int WideCharToMultiByte(

+      UINT CodePage, DWORD dwFlags,

+      LPCWSTR lpWideCharStr, int cchWideChar,

+      LPSTR lpMultiByteStr, int cbMultiByte,

+      LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);

+

+if (lpDefaultChar == NULL),

+  - it uses system default value.

+

+if (CodePage == CP_UTF7 || CodePage == CP_UTF8)

+  if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)

+    return: 0. ERR: ERROR_INVALID_PARAMETER.

+

+The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)

+

+*/

+

+static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

 {

-  bool defaultCharWasUsed;

-  UnicodeStringToMultiByte2(dest, srcString, codePage, '_', defaultCharWasUsed);

+  dest.Empty();

+  defaultCharWasUsed = false;

+  if (src.IsEmpty())

+    return;

+  {

+    /*

+    unsigned numRequiredBytes = src.Len() * 2;

+    char *d = dest.GetBuf(numRequiredBytes);

+    const wchar_t *s = (const wchar_t *)src;

+    unsigned i;

+    

+    for (i = 0;;)

+    {

+      wchar_t c = s[i];

+      if (c >= 0x80 || c == 0)

+        break;

+      d[i++] = (char)c;

+    }

+    

+    if (i != src.Len())

+    {

+      BOOL defUsed = FALSE;

+      defaultChar = defaultChar;

+

+      bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);

+      unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,

+          d + i, numRequiredBytes + 1 - i,

+          (isUtf ? NULL : &defaultChar),

+          (isUtf ? NULL : &defUsed));

+      defaultCharWasUsed = (defUsed != FALSE);

+      if (len == 0)

+        throw 282229;

+      i += len;

+    }

+

+    d[i] = 0;

+    dest.ReleaseBuf_SetLen(i);

+    */

+

+    /*

+    if (codePage != CP_UTF7)

+    {

+      const wchar_t *s = (const wchar_t *)src;

+      unsigned i;

+      for (i = 0;; i++)

+      {

+        wchar_t c = s[i];

+        if (c >= 0x80 || c == 0)

+          break;

+      }

+      

+      if (s[i] == 0)

+      {

+        char *d = dest.GetBuf(src.Len());

+        for (i = 0;;)

+        {

+          wchar_t c = s[i];

+          if (c == 0)

+            break;

+          d[i++] = (char)c;

+        }

+        d[i] = 0;

+        dest.ReleaseBuf_SetLen(i);

+        return;

+      }

+    }

+    */

+

+    unsigned len = WideCharToMultiByte(codePage, 0, src, src.Len(), NULL, 0, NULL, NULL);

+    if (len == 0)

+    {

+      if (GetLastError() != 0)

+        throw 282228;

+    }

+    else

+    {

+      BOOL defUsed = FALSE;

+      bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);

+      // defaultChar = defaultChar;

+      len = WideCharToMultiByte(codePage, 0, src, src.Len(),

+          dest.GetBuf(len), len,

+          (isUtf ? NULL : &defaultChar),

+          (isUtf ? NULL : &defUsed)

+          );

+      if (!isUtf)

+        defaultCharWasUsed = (defUsed != FALSE);

+      if (len == 0)

+        throw 282228;

+      dest.ReleaseBuf_SetEnd(len);

+    }

+  }

 }

 

-AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

+/*

+#ifndef UNDER_CE

+AString SystemStringToOemString(const CSysString &src)

 {

   AString dest;

-  defaultCharWasUsed = false;

-  if (!s.IsEmpty())

-  {

-    unsigned numRequiredBytes = s.Len() * 2;

-    BOOL defUsed;

-    int numChars = WideCharToMultiByte(codePage, 0, s, s.Len(),

-        dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1,

-        &defaultChar, &defUsed);

-    defaultCharWasUsed = (defUsed != FALSE);

-    if (numChars == 0)

-      throw 282229;

-    dest.ReleaseBuffer(numChars);

-  }

+  const unsigned len = src.Len() * 2;

+  CharToOem(src, dest.GetBuf(len));

+  dest.ReleaseBuf_CalcLen(len);

   return dest;

 }

-

-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)

-{

-  bool defaultCharWasUsed;

-  return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed);

-}

-

-#ifndef UNDER_CE

-AString SystemStringToOemString(const CSysString &srcString)

-{

-  AString result;

-  CharToOem(srcString, result.GetBuffer(srcString.Len() * 2));

-  result.ReleaseBuffer();

-  return result;

-}

 #endif

+*/

 

 #else

 

-UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)

+void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePage */)

 {

-  UString resultString;

-  for (unsigned i = 0; i < srcString.Len(); i++)

-    resultString += (wchar_t)srcString[i];

-  /*

-  if (!srcString.IsEmpty())

+  dest.Empty();

+  if (src.IsEmpty())

+    return;

+

+  size_t limit = ((size_t)src.Len() + 1) * 2;

+  wchar_t *d = dest.GetBuf((unsigned)limit);

+  size_t len = mbstowcs(d, src, limit);

+  if (len != (size_t)-1)

   {

-    int numChars = mbstowcs(resultString.GetBuffer(srcString.Len()), srcString, srcString.Len() + 1);

-    if (numChars < 0) throw "Your environment does not support UNICODE";

-    resultString.ReleaseBuffer(numChars);

+    dest.ReleaseBuf_SetEnd((unsigned)len);

+    return;

   }

-  */

-  return resultString;

+  

+  {

+    unsigned i;

+    const char *s = (const char *)src;

+    for (i = 0;;)

+    {

+      Byte c = (Byte)s[i];

+      if (c == 0)

+        break;

+      d[i++] = (wchar_t)c;

+    }

+    d[i] = 0;

+    dest.ReleaseBuf_SetLen(i);

+  }

 }

 

-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)

+static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT /* codePage */, char defaultChar, bool &defaultCharWasUsed)

 {

-  AString resultString;

-  for (unsigned i = 0; i < srcString.Len(); i++)

-    resultString += (char)srcString[i];

-  /*

-  if (!srcString.IsEmpty())

+  dest.Empty();

+  defaultCharWasUsed = false;

+  if (src.IsEmpty())

+    return;

+

+  size_t limit = ((size_t)src.Len() + 1) * 6;

+  char *d = dest.GetBuf((unsigned)limit);

+  size_t len = wcstombs(d, src, limit);

+  if (len != (size_t)-1)

   {

-    int numRequiredBytes = srcString.Len() * 6 + 1;

-    int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);

-    if (numChars < 0) throw "Your environment does not support UNICODE";

-    resultString.ReleaseBuffer(numChars);

+    dest.ReleaseBuf_SetEnd((unsigned)len);

+    return;

   }

-  */

-  return resultString;

+

+  {

+    const wchar_t *s = (const wchar_t *)src;

+    unsigned i;

+    for (i = 0;;)

+    {

+      wchar_t c = s[i];

+      if (c == 0)

+        break;

+      if (c >= 0x100)

+      {

+        c = defaultChar;

+        defaultCharWasUsed = true;

+      }

+      d[i++] = (char)c;

+    }

+    d[i] = 0;

+    dest.ReleaseBuf_SetLen(i);

+  }

 }

 

 #endif

+

+

+UString MultiByteToUnicodeString(const AString &src, UINT codePage)

+{

+  UString dest;

+  MultiByteToUnicodeString2(dest, src, codePage);

+  return dest;

+}

+

+void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)

+{

+  bool defaultCharWasUsed;

+  UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);

+}

+

+AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

+{

+  AString dest;

+  UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);

+  return dest;

+}

+

+AString UnicodeStringToMultiByte(const UString &src, UINT codePage)

+{

+  AString dest;

+  bool defaultCharWasUsed;

+  UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);

+  return dest;

+}

diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
index d5518eb..7f387b1 100644
--- a/CPP/Common/StringConvert.h
+++ b/CPP/Common/StringConvert.h
@@ -10,7 +10,7 @@
 

 // optimized versions that work faster for ASCII strings

 void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP);

-void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);

+// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);

 void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage);

 

 AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);

diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
index f9d483e..295816e 100644
--- a/CPP/Common/StringToInt.cpp
+++ b/CPP/Common/StringToInt.cpp
@@ -8,12 +8,12 @@
 static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);

 // static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;

 

-#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType) \

+#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \

   uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \

     if (end) *end = s; \

     uintType res = 0; \

     for (;; s++) { \

-      charType c = *s; \

+      charTypeUnsigned c = (charTypeUnsigned)*s; \

       if (c < '0' || c > '9') { if (end) *end = s; return res; } \

       if (res > (k_ ## uintType ## _max) / 10) return 0; \

       res *= 10; \

@@ -21,10 +21,10 @@
       if (res > (k_ ## uintType ## _max) - v) return 0; \

       res += v; }}

 

-CONVERT_STRING_TO_UINT_FUNC(UInt32, char)

-CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t)

-CONVERT_STRING_TO_UINT_FUNC(UInt64, char)

-CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t)

+CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)

+CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)

+CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)

+CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)

 

 Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()

 {

@@ -58,7 +58,7 @@
   UInt32 res = 0;

   for (;; s++)

   {

-    char c = *s;

+    unsigned c = (unsigned char)*s;

     if (c < '0' || c > '7')

     {

       if (end)

@@ -79,7 +79,7 @@
   UInt64 res = 0;

   for (;; s++)

   {

-    char c = *s;

+    unsigned c = (unsigned char)*s;

     if (c < '0' || c > '7')

     {

       if (end)

@@ -100,7 +100,7 @@
   UInt32 res = 0;

   for (;; s++)

   {

-    char c = *s;

+    unsigned c = (Byte)*s;

     unsigned v;

     if (c >= '0' && c <= '9') v = (c - '0');

     else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');

@@ -125,7 +125,7 @@
   UInt64 res = 0;

   for (;; s++)

   {

-    char c = *s;

+    unsigned c = (Byte)*s;

     unsigned v;

     if (c >= '0' && c <= '9') v = (c - '0');

     else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');

diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
index a77e770..f6b7008 100644
--- a/CPP/Common/TextConfig.cpp
+++ b/CPP/Common/TextConfig.cpp
@@ -87,8 +87,8 @@
         break;

       if (c == '\\')

       {

-        char c = s[pos++];

-        switch(c)

+        c = s[pos++];

+        switch (c)

         {

           case 'n': message += '\n'; break;

           case 't': message += '\t'; break;

diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h
index 9281fcf..fd9605c 100644
--- a/CPP/Common/TextConfig.h
+++ b/CPP/Common/TextConfig.h
@@ -17,5 +17,3 @@
 UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id);

 

 #endif

-

-

diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
index 0d3ff68..b09bbcd 100644
--- a/CPP/Common/UTFConvert.cpp
+++ b/CPP/Common/UTFConvert.cpp
@@ -5,56 +5,91 @@
 #include "MyTypes.h"

 #include "UTFConvert.h"

 

-static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

+#ifdef _WIN32

+#define _WCHART_IS_16BIT 1

+#endif

 

-bool CheckUTF8(const char *src) throw()

+/*

+  _UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte

+  

+  n : _UTF8_START(n) : Bits of code point

+

+  0 : 0x80 :    : unused

+  1 : 0xC0 : 11 :

+  2 : 0xE0 : 16 : Basic Multilingual Plane

+  3 : 0xF0 : 21 : Unicode space

+  3 : 0xF8 : 26 :

+  5 : 0xFC : 31 : UCS-4

+  6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value

+  7 : 0xFF :

+*/

+

+#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))

+

+#define _UTF8_HEAD_PARSE2(n) if (c < _UTF8_START((n) + 1)) { numBytes = (n); c -= _UTF8_START(n); }

+

+#define _UTF8_HEAD_PARSE \

+         _UTF8_HEAD_PARSE2(1) \

+    else _UTF8_HEAD_PARSE2(2) \

+    else _UTF8_HEAD_PARSE2(3) \

+    else _UTF8_HEAD_PARSE2(4) \

+    else _UTF8_HEAD_PARSE2(5) \

+

+    // else _UTF8_HEAD_PARSE2(6)

+

+bool CheckUTF8(const char *src, bool allowReduced) throw()

 {

   for (;;)

   {

-    Byte c;

-    unsigned numAdds;

-    c = *src++;

+    Byte c = *src++;

     if (c == 0)

       return true;

 

     if (c < 0x80)

       continue;

-    if (c < 0xC0)

+    if (c < 0xC0)   // (c < 0xC0 + 2) // if we support only optimal encoding chars

       return false;

-    for (numAdds = 1; numAdds < 5; numAdds++)

-      if (c < kUtf8Limits[numAdds])

-        break;

-    UInt32 value = (c - kUtf8Limits[numAdds - 1]);

+    

+    unsigned numBytes;

+    _UTF8_HEAD_PARSE

+    else

+      return false;

+    

+    UInt32 val = c;

 

     do

     {

       Byte c2 = *src++;

       if (c2 < 0x80 || c2 >= 0xC0)

-        return false;

-      value <<= 6;

-      value |= (c2 - 0x80);

+        return allowReduced && c2 == 0;

+      val <<= 6;

+      val |= (c2 - 0x80);

     }

-    while (--numAdds);

+    while (--numBytes);

     

-    if (value >= 0x110000)

+    if (val >= 0x110000)

       return false;

   }

 }

 

 

-static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) throw()

+#define _ERROR_UTF8 \

+  { if (dest) dest[destPos] = (wchar_t)0xFFFD; destPos++; ok = false; continue; }

+

+static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim) throw()

 {

-  size_t destPos = 0, srcPos = 0;

+  size_t destPos = 0;

+  bool ok = true;

+

   for (;;)

   {

     Byte c;

-    unsigned numAdds;

-    if (srcPos == srcLen)

+    if (src == srcLim)

     {

       *destLen = destPos;

-      return True;

+      return ok;

     }

-    c = (Byte)src[srcPos++];

+    c = *src++;

 

     if (c < 0x80)

     {

@@ -64,113 +99,190 @@
       continue;

     }

     if (c < 0xC0)

-      break;

-    for (numAdds = 1; numAdds < 5; numAdds++)

-      if (c < kUtf8Limits[numAdds])

-        break;

-    UInt32 value = (c - kUtf8Limits[numAdds - 1]);

+      _ERROR_UTF8

+

+    unsigned numBytes;

+    _UTF8_HEAD_PARSE

+    else

+      _ERROR_UTF8

+    

+    UInt32 val = c;

 

     do

     {

       Byte c2;

-      if (srcPos == srcLen)

+      if (src == srcLim)

         break;

-      c2 = (Byte)src[srcPos++];

+      c2 = *src;

       if (c2 < 0x80 || c2 >= 0xC0)

         break;

-      value <<= 6;

-      value |= (c2 - 0x80);

+      src++;

+      val <<= 6;

+      val |= (c2 - 0x80);

     }

-    while (--numAdds);

-    

-    if (value < 0x10000)

+    while (--numBytes);

+

+    if (numBytes != 0)

+      _ERROR_UTF8

+

+    if (val < 0x10000)

     {

       if (dest)

-        dest[destPos] = (wchar_t)value;

+        dest[destPos] = (wchar_t)val;

       destPos++;

     }

     else

     {

-      value -= 0x10000;

-      if (value >= 0x100000)

-        break;

+      val -= 0x10000;

+      if (val >= 0x100000)

+        _ERROR_UTF8

       if (dest)

       {

-        dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10));

-        dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF));

+        dest[destPos + 0] = (wchar_t)(0xD800 + (val >> 10));

+        dest[destPos + 1] = (wchar_t)(0xDC00 + (val & 0x3FF));

       }

       destPos += 2;

     }

   }

-  *destLen = destPos;

-  return False;

 }

 

-static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen)

+#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))

+

+#define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n)))))

+#define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F)))

+

+static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim)

 {

-  size_t destPos = 0, srcPos = 0;

+  size_t size = srcLim - src;

   for (;;)

   {

-    unsigned numAdds;

-    UInt32 value;

-    if (srcPos == srcLen)

+    if (src == srcLim)

+      return size;

+    

+    UInt32 val = *src++;

+   

+    if (val < 0x80)

+      continue;

+

+    if (val < _UTF8_RANGE(1))

     {

-      *destLen = destPos;

-      return True;

-    }

-    value = src[srcPos++];

-    if (value < 0x80)

-    {

-      if (dest)

-        dest[destPos] = (char)value;

-      destPos++;

+      size++;

       continue;

     }

-    if (value >= 0xD800 && value < 0xE000)

+

+    if (val >= 0xD800 && val < 0xDC00 && src != srcLim)

     {

-      UInt32 c2;

-      if (value >= 0xDC00 || srcPos == srcLen)

-        break;

-      c2 = src[srcPos++];

-      if (c2 < 0xDC00 || c2 >= 0xE000)

-        break;

-      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;

+      UInt32 c2 = *src;

+      if (c2 >= 0xDC00 && c2 < 0xE000)

+      {

+        src++;

+        size += 2;

+        continue;

+      }

     }

-    for (numAdds = 1; numAdds < 5; numAdds++)

-      if (value < (((UInt32)1) << (numAdds * 5 + 6)))

-        break;

-    if (dest)

-      dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));

-    destPos++;

+

+    #ifdef _WCHART_IS_16BIT

+    

+    size += 2;

+    

+    #else

+

+         if (val < _UTF8_RANGE(2)) size += 2;

+    else if (val < _UTF8_RANGE(3)) size += 3;

+    else if (val < _UTF8_RANGE(4)) size += 4;

+    else if (val < _UTF8_RANGE(5)) size += 5;

+    else                           size += 6;

+    

+    #endif

+  }

+}

+

+static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim)

+{

+  for (;;)

+  {

+    if (src == srcLim)

+      return dest;

+    

+    UInt32 val = *src++;

+    

+    if (val < 0x80)

+    {

+      *dest++ = (char)val;

+      continue;

+    }

+

+    if (val < _UTF8_RANGE(1))

+    {

+      dest[0] = _UTF8_HEAD(1, val);

+      dest[1] = _UTF8_CHAR(0, val);

+      dest += 2;

+      continue;

+    }

+

+    if (val >= 0xD800 && val < 0xDC00 && src != srcLim)

+    {

+      UInt32 c2 = *src;

+      if (c2 >= 0xDC00 && c2 < 0xE000)

+      {

+        src++;

+        val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;

+        dest[0] = _UTF8_HEAD(3, val);

+        dest[1] = _UTF8_CHAR(2, val);

+        dest[2] = _UTF8_CHAR(1, val);

+        dest[3] = _UTF8_CHAR(0, val);

+        dest += 4;

+        continue;

+      }

+    }

+    

+    #ifndef _WCHART_IS_16BIT

+    if (val < _UTF8_RANGE(2))

+    #endif

+    {

+      dest[0] = _UTF8_HEAD(2, val);

+      dest[1] = _UTF8_CHAR(1, val);

+      dest[2] = _UTF8_CHAR(0, val);

+      dest += 3;

+      continue;

+    }

+    

+    #ifndef _WCHART_IS_16BIT

+

+    UInt32 b;

+    unsigned numBits;

+         if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); }

+    else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); }

+    else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); }

+    else                           { numBits = 6 * 6; b = _UTF8_START(6); }

+    

+    *dest++ = (Byte)b;

+    

     do

     {

-      numAdds--;

-      if (dest)

-        dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));

-      destPos++;

+      numBits -= 6;

+      *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F));

     }

-    while (numAdds != 0);

+    while (numBits != 0);

+

+    #endif

   }

-  *destLen = destPos;

-  return False;

 }

 

 bool ConvertUTF8ToUnicode(const AString &src, UString &dest)

 {

   dest.Empty();

   size_t destLen = 0;

-  Utf8_To_Utf16(NULL, &destLen, src, src.Len());

-  Bool res = Utf8_To_Utf16(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len());

-  dest.ReleaseBuffer((unsigned)destLen);

-  return res ? true : false;

+  Utf8_To_Utf16(NULL, &destLen, src, src.Ptr(src.Len()));

+  bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src.Ptr(src.Len()));

+  dest.ReleaseBuf_SetEnd((unsigned)destLen);

+  return res;

 }

 

-bool ConvertUnicodeToUTF8(const UString &src, AString &dest)

+void ConvertUnicodeToUTF8(const UString &src, AString &dest)

 {

   dest.Empty();

-  size_t destLen = 0;

-  Utf16_To_Utf8(NULL, &destLen, src, src.Len());

-  Bool res = Utf16_To_Utf8(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len());

-  dest.ReleaseBuffer((unsigned)destLen);

-  return res ? true : false;

+  size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()));

+  Utf16_To_Utf8(dest.GetBuf((unsigned)destLen), src, src.Ptr(src.Len()));

+  dest.ReleaseBuf_SetEnd((unsigned)destLen);

 }

diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
index 601b674..1183170 100644
--- a/CPP/Common/UTFConvert.h
+++ b/CPP/Common/UTFConvert.h
@@ -5,8 +5,8 @@
 

 #include "MyString.h"

 

-bool CheckUTF8(const char *src) throw();

+bool CheckUTF8(const char *src, bool allowReduced = false) throw();

 bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);

-bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);

+void ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);

 

 #endif

diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
index a7f47c3..4967b69 100644
--- a/CPP/Common/Wildcard.cpp
+++ b/CPP/Common/Wildcard.cpp
@@ -15,22 +15,8 @@
 bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)

 {

   if (g_CaseSensitive)

-  {

-    for (;;)

-    {

-      wchar_t c2 = *s2++; if (c2 == 0) return true;

-      wchar_t c1 = *s1++;

-      if (MyCharUpper(c1) !=

-          MyCharUpper(c2))

-        return false;

-    }

-  }

-

-  for (;;)

-  {

-    wchar_t c2 = *s2++; if (c2 == 0) return true;

-    wchar_t c1 = *s1++; if (c1 != c2) return false;

-  }

+    return IsString1PrefixedByString2(s1, s2);

+  return IsString1PrefixedByString2_NoCase(s1, s2);

 }

 

 int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW

@@ -97,7 +83,7 @@
   UString name;

   unsigned prev = 0;

   for (unsigned i = 0; i < len; i++)

-    if (IsCharDirLimiter(path[i]))

+    if (IsPathSepar(path[i]))

     {

       name.SetFrom(path.Ptr(prev), i - prev);

       pathParts.Add(name);

@@ -112,7 +98,7 @@
   const wchar_t *start = path;

   const wchar_t *p = start + path.Len();

   for (; p != start; p--)

-    if (IsCharDirLimiter(*(p - 1)))

+    if (IsPathSepar(*(p - 1)))

       break;

   dirPrefix.SetFrom(path, (unsigned)(p - start));

   name = p;

@@ -124,10 +110,10 @@
   const wchar_t *p = start + path.Len();

   if (p != start)

   {

-    if (IsCharDirLimiter(*(p - 1)))

+    if (IsPathSepar(*(p - 1)))

       p--;

     for (; p != start; p--)

-      if (IsCharDirLimiter(*(p - 1)))

+      if (IsPathSepar(*(p - 1)))

         break;

   }

   dirPrefix.SetFrom(path, (unsigned)(p - start));

@@ -139,7 +125,7 @@
   const wchar_t *start = path;

   const wchar_t *p = start + path.Len();

   for (; p != start; p--)

-    if (IsCharDirLimiter(*(p - 1)))

+    if (IsPathSepar(*(p - 1)))

       break;

   return path.Left((unsigned)(p - start));

 }

@@ -149,7 +135,7 @@
   const wchar_t *start = path;

   const wchar_t *p = start + path.Len();

   for (; p != start; p--)

-    if (IsCharDirLimiter(*(p - 1)))

+    if (IsPathSepar(*(p - 1)))

       break;

   return p;

 }

@@ -177,15 +163,6 @@
 

 namespace NWildcard {

 

-

-#ifdef _WIN32

-bool IsDriveColonName(const wchar_t *s)

-{

-  wchar_t c = s[0];

-  return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');

-}

-#endif

-

 /*

 

 M = MaskParts.Size();

@@ -212,6 +189,19 @@
 {

   if (!isFile && !ForDir)

     return false;

+

+  /*

+  if (PathParts.IsEmpty())

+  {

+    // PathParts.IsEmpty() means all items (universal wildcard)

+    if (!isFile)

+      return true;

+    if (pathParts.Size() <= 1)

+      return ForFile;

+    return (ForDir || Recursive && ForFile);

+  }

+  */

+

   int delta = (int)pathParts.Size() - (int)PathParts.Size();

   if (delta < 0)

     return false;

@@ -286,7 +276,7 @@
     ExcludeItems.Add(item);

 }

 

-void CCensorNode::AddItem(bool include, CItem &item)

+void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)

 {

   if (item.PathParts.Size() <= 1)

   {

@@ -300,9 +290,10 @@
   }

   const UString &front = item.PathParts.Front();

   

-  // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name

-  // if (item.Wildcard)

-  if (DoesNameContainWildcard(front))

+  // WIN32 doesn't support wildcards in file names

+  if (item.WildcardMatching

+      && ignoreWildcardIndex != 0

+      && DoesNameContainWildcard(front))

   {

     AddItemSimple(include, item);

     return;

@@ -311,7 +302,7 @@
   if (index < 0)

     index = SubNodes.Add(CCensorNode(front, this));

   item.PathParts.Delete(0);

-  SubNodes[index].AddItem(include, item);

+  SubNodes[index].AddItem(include, item, ignoreWildcardIndex - 1);

 }

 

 void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching)

@@ -377,6 +368,7 @@
   return finded;

 }

 

+/*

 bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const

 {

   UStringVector pathParts;

@@ -406,6 +398,7 @@
     return include;

   return false;

 }

+*/

 

 bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const

 {

@@ -433,7 +426,7 @@
   bool forFile = true;

   bool forFolder = true;

   UString path2 = path;

-  if (IsCharDirLimiter(path.Back()))

+  if (IsPathSepar(path.Back()))

   {

     path2.DeleteBack();

     forFile = false;

@@ -462,12 +455,90 @@
   return -1;

 }

 

+#ifdef _WIN32

+

+bool IsDriveColonName(const wchar_t *s)

+{

+  wchar_t c = s[0];

+  return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');

+}

+

+unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)

+{

+  if (pathParts.IsEmpty())

+    return 0;

+  

+  unsigned testIndex = 0;

+  if (pathParts[0].IsEmpty())

+  {

+    if (pathParts.Size() < 4

+        || !pathParts[1].IsEmpty()

+        || pathParts[2] != L"?")

+      return 0;

+    testIndex = 3;

+  }

+  if (NWildcard::IsDriveColonName(pathParts[testIndex]))

+    return testIndex + 1;

+  return 0;

+}

+

+#endif

+

+static unsigned GetNumPrefixParts(const UStringVector &pathParts)

+{

+  if (pathParts.IsEmpty())

+    return 0;

+  

+  #ifdef _WIN32

+  

+  if (IsDriveColonName(pathParts[0]))

+    return 1;

+  if (!pathParts[0].IsEmpty())

+    return 0;

+

+  if (pathParts.Size() == 1)

+    return 1;

+  if (!pathParts[1].IsEmpty())

+    return 1;

+  if (pathParts.Size() == 2)

+    return 2;

+  if (pathParts[2] == L".")

+    return 3;

+

+  unsigned networkParts = 2;

+  if (pathParts[2] == L"?")

+  {

+    if (pathParts.Size() == 3)

+      return 3;

+    if (IsDriveColonName(pathParts[3]))

+      return 4;

+    if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))

+      return 3;

+    networkParts = 4;

+  }

+

+  networkParts +=

+      // 2; // server/share

+      1; // server

+  if (pathParts.Size() <= networkParts)

+    return pathParts.Size();

+  return networkParts;

+

+  #else

+  

+  return pathParts[0].IsEmpty() ? 1 : 0;

+ 

+  #endif

+}

+

 void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching)

 {

-  UStringVector pathParts;

   if (path.IsEmpty())

     throw "Empty file path";

+

+  UStringVector pathParts;

   SplitPathToParts(path, pathParts);

+

   bool forFile = true;

   if (pathParts.Back().IsEmpty())

   {

@@ -477,74 +548,55 @@
   

   UString prefix;

   

+  int ignoreWildcardIndex = -1;

+

+  // #ifdef _WIN32

+  // we ignore "?" wildcard in "\\?\" prefix.

+  if (pathParts.Size() >= 3

+      && pathParts[0].IsEmpty()

+      && pathParts[1].IsEmpty()

+      && pathParts[2] == L"?")

+    ignoreWildcardIndex = 2;

+  // #endif

+

   if (pathMode != k_AbsPath)

   {

-    const UString &front = pathParts.Front();

-    bool isAbs = false;

-    

-    if (front.IsEmpty())

-      isAbs = true;

-    else

-    {

-      #ifdef _WIN32

-      

-      if (IsDriveColonName(front))

-        isAbs = true;

-      else

-      

-      #endif

-      

-        FOR_VECTOR (i, pathParts)

-        {

-          const UString &part = pathParts[i];

-          if (part == L".." || part == L".")

-          {

-            isAbs = true;

-            break;

-          }

-        }

-    }

-    

-    unsigned numAbsParts = 0;

-    if (isAbs)

-      if (pathParts.Size() > 1)

-        numAbsParts = pathParts.Size() - 1;

-      else

-        numAbsParts = 1;

-      

-    #ifdef _WIN32

-    

-    // \\?\ case

-    if (numAbsParts >= 3)

-    {

-      if (pathParts[0].IsEmpty() &&

-          pathParts[1].IsEmpty() &&

-          pathParts[2] == L"?")

-      {

-        prefix =

-            WSTRING_PATH_SEPARATOR

-            WSTRING_PATH_SEPARATOR L"?"

-            WSTRING_PATH_SEPARATOR;

-        numAbsParts -= 3;

-        pathParts.DeleteFrontal(3);

-      }

-    }

-    

-    #endif

-    

-    if (numAbsParts > 1 && pathMode == k_FullPath)

-      numAbsParts = 1;

+    ignoreWildcardIndex = -1;

 

-    // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name

-    // if (wildcardMatching)

-    for (unsigned i = 0; i < numAbsParts; i++)

+    const unsigned numPrefixParts = GetNumPrefixParts(pathParts);

+    unsigned numSkipParts = numPrefixParts;

+

+    if (pathMode != k_FullPath)

+    {

+      if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)

+        numSkipParts = pathParts.Size() - 1;

+    }

+    {

+      int dotsIndex = -1;

+      for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)

+      {

+        const UString &part = pathParts[i];

+        if (part == L".." || part == L".")

+          dotsIndex = i;

+      }

+

+      if (dotsIndex >= 0)

+        if (dotsIndex == (int)pathParts.Size() - 1)

+          numSkipParts = pathParts.Size();

+        else

+          numSkipParts = pathParts.Size() - 1;

+    }

+

+    for (unsigned i = 0; i < numSkipParts; i++)

     {

       {

         const UString &front = pathParts.Front();

-        if (DoesNameContainWildcard(front))

-          break;

+        // WIN32 doesn't support wildcards in file names

+        if (wildcardMatching)

+          if (i >= numPrefixParts && DoesNameContainWildcard(front))

+            break;

         prefix += front;

-        prefix += WCHAR_PATH_SEPARATOR;

+        prefix.Add_PathSepar();

       }

       pathParts.Delete(0);

     }

@@ -554,15 +606,29 @@
   if (index < 0)

     index = Pairs.Add(CPair(prefix));

 

+  if (pathMode != k_AbsPath)

+  {

+    if (pathParts.IsEmpty() || pathParts.Size() == 1 && pathParts[0].IsEmpty())

+    {

+      // we create universal item, if we skip all parts as prefix (like \ or L:\ )

+      pathParts.Clear();

+      pathParts.Add(L"*");

+      forFile = true;

+      wildcardMatching = true;

+      recursive = false;

+    }

+  }

+

   CItem item;

   item.PathParts = pathParts;

   item.ForDir = true;

   item.ForFile = forFile;

   item.Recursive = recursive;

   item.WildcardMatching = wildcardMatching;

-  Pairs[index].Head.AddItem(include, item);

+  Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex);

 }

 

+/*

 bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const

 {

   bool finded = false;

@@ -578,6 +644,7 @@
   }

   return finded;

 }

+*/

 

 void CCensor::ExtendExclude()

 {

diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
index 5db765c..2ed7298 100644
--- a/CPP/Common/Wildcard.h
+++ b/CPP/Common/Wildcard.h
@@ -12,15 +12,6 @@
 

 bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);

 

-inline bool IsCharDirLimiter(wchar_t c)

-{

-  return c == WCHAR_PATH_SEPARATOR

-    #ifdef _WIN32

-      || c == L'/'

-    #endif

-    ;

-}

-

 void SplitPathToParts(const UString &path, UStringVector &pathParts);

 void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);

 void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)

@@ -36,9 +27,9 @@
 #ifdef _WIN32

 // returns true, if name is like "a:", "c:", ...

 bool IsDriveColonName(const wchar_t *s);

+unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);

 #endif

 

-

 struct CItem

 {

   UStringVector PathParts;

@@ -66,12 +57,13 @@
   

   bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;

   void AddItemSimple(bool include, CItem &item);

-  bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;

 public:

+  bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;

+

   CCensorNode(): Parent(0) { };

   CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };

 

-  UString Name; // wildcard is not allowed here

+  UString Name; // WIN32 doesn't support wildcards in file names

   CObjectVector<CCensorNode> SubNodes;

   CObjectVector<CItem> IncludeItems;

   CObjectVector<CItem> ExcludeItems;

@@ -80,15 +72,15 @@
 

   int FindSubNode(const UString &path) const;

 

-  void AddItem(bool include, CItem &item);

+  void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);

   void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching);

   void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching);

 

   bool NeedCheckSubDirs() const;

   bool AreThereIncludeItems() const;

 

-  bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;

-  bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;

+  // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;

+  // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;

 

   bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const;

   // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;

@@ -136,7 +128,7 @@
     { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }

   

   void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching);

-  bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;

+  // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;

   void ExtendExclude();

 

   void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);

diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp
index c69d2e3..92fce0a 100644
--- a/CPP/Common/XzCrc64Reg.cpp
+++ b/CPP/Common/XzCrc64Reg.cpp
@@ -7,7 +7,6 @@
 

 #include "../Common/MyCom.h"

 

-#include "../7zip/ICoder.h"

 #include "../7zip/Common/RegisterCodec.h"

 

 class CXzCrc64Hasher:

@@ -15,40 +14,29 @@
   public CMyUnknownImp

 {

   UInt64 _crc;

+  Byte mtDummy[1 << 7];

+

 public:

   CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}

 

-  MY_UNKNOWN_IMP

-

-  STDMETHOD_(void, Init)();

-  STDMETHOD_(void, Update)(const void *data, UInt32 size);

-  STDMETHOD_(void, Final)(Byte *digest);

-  STDMETHOD_(UInt32, GetDigestSize)();

+  MY_UNKNOWN_IMP1(IHasher)

+  INTERFACE_IHasher(;)

 };

 

-STDMETHODIMP_(void) CXzCrc64Hasher::Init()

+STDMETHODIMP_(void) CXzCrc64Hasher::Init() throw()

 {

   _crc = CRC64_INIT_VAL;

 }

 

-STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size)

+STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) throw()

 {

   _crc = Crc64Update(_crc, data, size);

 }

 

-STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest)

+STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) throw()

 {

   UInt64 val = CRC64_GET_DIGEST(_crc);

   SetUi64(digest, val);

 }

 

-STDMETHODIMP_(UInt32) CXzCrc64Hasher::GetDigestSize()

-{

-  return 8;

-}

-

-static IHasher *CreateHasher() { return new CXzCrc64Hasher; }

-

-static CHasherInfo g_HasherInfo = { CreateHasher, 0x4, L"CRC64", 8 };

-

-REGISTER_HASHER(Crc64)

+REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)

diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
index 8aa6d28..e2cb002 100644
--- a/CPP/Windows/COM.h
+++ b/CPP/Windows/COM.h
@@ -22,7 +22,7 @@
     CoInitialize(NULL);

     #endif

   };

-  ~CComInitializer() { CoUninitialize(); };

+  ~CComInitializer() { CoUninitialize(); }

 };

 

 class CStgMedium

@@ -45,6 +45,7 @@
 

 #endif

 

+/*

 //////////////////////////////////

 // GUID <--> String Conversions

 UString GUIDToStringW(REFGUID guid);

@@ -62,6 +63,7 @@
 #else

   #define StringToGUID StringToGUIDA

 #endif

+*/

 

 }}

 

diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp
index 60b5b26..8b3828c 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 ca102f3..6ab4717 100644
--- a/CPP/Windows/Control/ComboBox.cpp
+++ b/CPP/Windows/Control/ComboBox.cpp
@@ -18,11 +18,15 @@
 LRESULT CComboBox::GetLBText(int index, CSysString &s)

 {

   s.Empty();

-  LRESULT len = GetLBTextLen(index);

+  LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character

   if (len == CB_ERR)

     return len;

-  len = GetLBText(index, s.GetBuffer((int)len + 1));

-  s.ReleaseBuffer();

+  LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len));

+  if (len2 == CB_ERR)

+    return len;

+  if (len > len2)

+    len = len2;

+  s.ReleaseBuf_CalcLen((unsigned)len);

   return len;

 }

 

@@ -30,7 +34,7 @@
 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));

 }

 

@@ -39,11 +43,15 @@
   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;

-    len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1));

-    s.ReleaseBuffer();

+    LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));

+    if (len2 == CB_ERR)

+      return len;

+    if (len > len2)

+      len = len2;

+    s.ReleaseBuf_CalcLen((unsigned)len);

     return len;

   }

   AString sa;

diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h
index 25e1730..3439655 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 @@
 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 @@
 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 00c5df7..c435568 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 @@
   

   // 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/Dialog.h b/CPP/Windows/Control/Dialog.h
index 66530e5..b160958 100644
--- a/CPP/Windows/Control/Dialog.h
+++ b/CPP/Windows/Control/Dialog.h
@@ -95,9 +95,9 @@
 

   /*

   #ifdef UNDER_CE

-  virtual void OnHelp(void *) { OnHelp(); };

+  virtual void OnHelp(void *) { OnHelp(); }

   #else

-  virtual void OnHelp(LPHELPINFO) { OnHelp(); };

+  virtual void OnHelp(LPHELPINFO) { OnHelp(); }

   #endif

   */

   virtual void OnHelp() {};

diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h
index 40e3899..4f503aa 100644
--- a/CPP/Windows/Control/Edit.h
+++ b/CPP/Windows/Control/Edit.h
@@ -11,7 +11,7 @@
 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 6897c81..1ed496d 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 {

 

@@ -30,6 +32,18 @@
 

   int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }

   int InsertColumn(int columnIndex, LPCTSTR text, int width);

+  bool SetColumnOrderArray(int count, const int *columns) { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, columns)); }

+

+  /*

+  int GetNumColumns()

+  {

+    HWND header = ListView_GetHeader(_window);

+    if (!header)

+      return -1;

+    return Header_GetItemCount(header);

+  }

+  */

+

   int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); }

   int InsertItem(int index, LPCTSTR text);

   bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); }

@@ -37,11 +51,11 @@
 

   #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 71dc912..f18d89c 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 @@
 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 053de09..551c959 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 cf47bf4..26fa311 100644
--- a/CPP/Windows/Control/ReBar.h
+++ b/CPP/Windows/Control/ReBar.h
@@ -12,21 +12,21 @@
 {

 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 355b9e8..936dd3c 100644
--- a/CPP/Windows/Control/Static.h
+++ b/CPP/Windows/Control/Static.h
@@ -11,15 +11,15 @@
 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 9185c42..7f7d66b 100644
--- a/CPP/Windows/Control/StatusBar.h
+++ b/CPP/Windows/Control/StatusBar.h
@@ -16,7 +16,7 @@
   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 @@
   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 6bc4443..02ed9a1 100644
--- a/CPP/Windows/Control/ToolBar.h
+++ b/CPP/Windows/Control/ToolBar.h
@@ -11,8 +11,8 @@
 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 @@
   }

   #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/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h
index da1936b..afc9bf2 100644
--- a/CPP/Windows/Control/Trackbar.h
+++ b/CPP/Windows/Control/Trackbar.h
@@ -4,23 +4,22 @@
 #define __WINDOWS_CONTROL_TRACKBAR_H

 

 #include "../Window.h"

-#include "../Defs.h"

 

 namespace NWindows {

 namespace NControl {

 

-class CTrackbar1: public CWindow

+class CTrackbar: public CWindow

 {

 public:

   void SetRange(int minimum, int maximum, bool redraw = true)

-    { SendMessage(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); }

+    { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); }

   void SetPos(int pos, bool redraw = true)

-    { SendMessage(TBM_SETPOS, BoolToBOOL(redraw), pos); }

+    { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); }

   void SetTicFreq(int freq)

-    { SendMessage(TBM_SETTICFREQ, freq); }

+    { SendMsg(TBM_SETTICFREQ, freq); }

   

   int GetPos()

-    { return (int)SendMessage(TBM_GETPOS); }

+    { return (int)SendMsg(TBM_GETPOS); }

 };

 

 }}

diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp
index 2588c3a..b6e6d67 100644
--- a/CPP/Windows/Control/Window2.cpp
+++ b/CPP/Windows/Control/Window2.cpp
@@ -178,7 +178,7 @@
 /*

 bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

 {

-  switch(aButtonID)

+  switch (buttonID)

   {

     case IDOK:

       OnOK();

diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h
index f565daa..d632b86 100644
--- a/CPP/Windows/Control/Window2.h
+++ b/CPP/Windows/Control/Window2.h
@@ -35,7 +35,7 @@
   virtual void OnDestroy() { PostQuitMessage(0); }

   virtual void OnClose() { Destroy(); }

   /*

-  virtual LRESULT  OnHelp(LPHELPINFO helpInfo) { OnHelp(); };

+  virtual LRESULT  OnHelp(LPHELPINFO helpInfo) { OnHelp(); }

   virtual LRESULT  OnHelp() {};

   virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

   virtual void OnOK() {};

diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
index 5485ba3..988b66f 100644
--- a/CPP/Windows/DLL.cpp
+++ b/CPP/Windows/DLL.cpp
@@ -95,7 +95,7 @@
   FString s;

   if (MyGetModuleFileName(s))

   {

-    int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR);

+    int pos = s.ReverseFind_PathSepar();

     if (pos >= 0)

     {

       s.DeleteFrom(pos + 1);

diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
index e61cf89..58bcf19 100644
--- a/CPP/Windows/DLL.h
+++ b/CPP/Windows/DLL.h
@@ -13,17 +13,23 @@
 #else

 #define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName)

 #endif

- 

+

+/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another

+    FreeLibrary() code: detaching code in DLL entry-point or in

+    destructors of global objects in DLL module. */

+

 class CLibrary

 {

   HMODULE _module;

+

+  // CLASS_NO_COPY(CLibrary);

 public:

   CLibrary(): _module(NULL) {};

   ~CLibrary() { Free(); }

 

   operator HMODULE() const { return _module; }

   HMODULE* operator&() { return &_module; }

-  bool IsLoaded() const { return (_module != NULL); };

+  bool IsLoaded() const { return (_module != NULL); }

 

   void Attach(HMODULE m)

   {

diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
index e929e75..c252afd 100644
--- a/CPP/Windows/ErrorMsg.cpp
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -42,20 +42,25 @@
 

 UString MyFormatMessage(DWORD errorCode)

 {

-  UString message;

-  if (!MyFormatMessage(errorCode, message))

+  UString m;

+  if (!MyFormatMessage(errorCode, m) || m.IsEmpty())

   {

-    wchar_t s[16];

+    char s[16];

     for (int i = 0; i < 8; i++)

     {

       unsigned t = errorCode & 0xF;

       errorCode >>= 4;

-      s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+      s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

     }

-    s[8] = '\0';

-    message = (UString)L"Error #" + s;

+    s[8] = 0;

+    m.AddAscii("Error #");

+    m.AddAscii(s);

   }

-  return message;

+  else if (m.Len() >= 2

+      && m[m.Len() - 1] == 0x0A

+      && m[m.Len() - 2] == 0x0D)

+    m.DeleteFrom(m.Len() - 2);

+  return m;

 }

 

 }}

diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index c215657..6b70a47 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -86,9 +86,9 @@
   #ifdef WIN_LONG_PATH

   if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)

   {

-    UString longPath;

-    if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-      hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,

+    UString superPath;

+    if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+      hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,

           NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

   }

   #endif

@@ -119,9 +119,9 @@
     #ifdef WIN_LONG_PATH

     if (USE_SUPER_PATH)

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        return BOOLToBool(::SetFileAttributesW(longPath, attrib));

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        return BOOLToBool(::SetFileAttributesW(superPath, attrib));

     }

     #endif

   }

@@ -145,9 +145,9 @@
     #ifdef WIN_LONG_PATH

     if (USE_SUPER_PATH)

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        return BOOLToBool(::RemoveDirectoryW(longPath));

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        return BOOLToBool(::RemoveDirectoryW(superPath));

     }

     #endif

   }

@@ -226,6 +226,29 @@
 

 #endif

 

+/*

+WinXP-64 CreateDir():

+  ""                  - ERROR_PATH_NOT_FOUND

+  \                   - ERROR_ACCESS_DENIED

+  C:\                 - ERROR_ACCESS_DENIED, if there is such drive,

+  

+  D:\folder             - ERROR_PATH_NOT_FOUND, if there is no such drive,

+  C:\nonExistent\folder - ERROR_PATH_NOT_FOUND

+  

+  C:\existFolder      - ERROR_ALREADY_EXISTS

+  C:\existFolder\     - ERROR_ALREADY_EXISTS

+

+  C:\folder   - OK

+  C:\folder\  - OK

+

+  \\Server\nonExistent    - ERROR_BAD_NETPATH

+  \\Server\Share_Readonly - ERROR_ACCESS_DENIED

+  \\Server\Share          - ERROR_ALREADY_EXISTS

+

+  \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED

+  \\Server\Share_FAT_drive  - ERROR_ALREADY_EXISTS

+*/

+

 bool CreateDir(CFSTR path)

 {

   #ifndef _UNICODE

@@ -243,56 +266,127 @@
     #ifdef WIN_LONG_PATH

     if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        return BOOLToBool(::CreateDirectoryW(longPath, NULL));

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        return BOOLToBool(::CreateDirectoryW(superPath, NULL));

     }

     #endif

   }

   return false;

 }

 

-bool CreateComplexDir(CFSTR _aPathName)

+/*

+  CreateDir2 returns true, if directory can contain files after the call (two cases):

+    1) the directory already exists

+    2) the directory was created

+  path must be WITHOUT trailing path separator.

+

+  We need CreateDir2, since fileInfo.Find() for reserved names like "com8"

+   returns FILE instead of DIRECTORY. And we need to use SuperPath */

+ 

+static bool CreateDir2(CFSTR path)

 {

-  FString pathName = _aPathName;

-  int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);

-  if (pos > 0 && (unsigned)pos == pathName.Len() - 1)

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

-    if (pathName.Len() == 3 && pathName[1] == L':')

-      return true; // Disk folder;

-    pathName.Delete(pos);

+    if (::CreateDirectory(fs2fas(path), NULL))

+      return true;

   }

-  const FString pathName2 = pathName;

-  pos = pathName.Len();

+  else

+  #endif

+  {

+    IF_USE_MAIN_PATH

+      if (::CreateDirectoryW(fs2us(path), NULL))

+        return true;

+    #ifdef WIN_LONG_PATH

+    if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)

+    {

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+      {

+        if (::CreateDirectoryW(superPath, NULL))

+          return true;

+        if (::GetLastError() != ERROR_ALREADY_EXISTS)

+          return false;

+        NFind::CFileInfo fi;

+        if (!fi.Find(us2fs(superPath)))

+          return false;

+        return fi.IsDir();

+      }

+    }

+    #endif

+  }

+  if (::GetLastError() != ERROR_ALREADY_EXISTS)

+    return false;

+  NFind::CFileInfo fi;

+  if (!fi.Find(path))

+    return false;

+  return fi.IsDir();

+}

+

+bool CreateComplexDir(CFSTR _path)

+{

+  #ifdef _WIN32

+  

+  {

+    DWORD attrib = NFind::GetFileAttrib(_path);

+    if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)

+      return true;

+  }

+

+  #ifndef UNDER_CE

+  

+  if (IsDriveRootPath_SuperAllowed(_path))

+    return false;

+  

+  unsigned prefixSize = GetRootPrefixSize(_path);

+  

+  #endif

+  

+  #endif

+

+  FString path = _path;

+

+  int pos = path.ReverseFind_PathSepar();

+  if (pos >= 0 && (unsigned)pos == path.Len() - 1)

+  {

+    if (path.Len() == 1)

+      return true;

+    path.DeleteBack();

+  }

+

+  const FString path2 = path;

+  pos = path.Len();

   

   for (;;)

   {

-    if (CreateDir(pathName))

+    if (CreateDir2(path))

       break;

     if (::GetLastError() == ERROR_ALREADY_EXISTS)

-    {

-      NFind::CFileInfo fileInfo;

-      if (!fileInfo.Find(pathName)) // For network folders

-        return true;

-      if (!fileInfo.IsDir())

-        return false;

-      break;

-    }

-    pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);

+      return false;

+    pos = path.ReverseFind_PathSepar();

     if (pos < 0 || pos == 0)

       return false;

-    if (pathName[pos - 1] == L':')

+    

+    #if defined(_WIN32) && !defined(UNDER_CE)

+    if (pos == 1 && IS_PATH_SEPAR(path[0]))

       return false;

-    pathName.DeleteFrom(pos);

+    if (prefixSize >= (unsigned)pos + 1)

+      return false;

+    #endif

+    

+    path.DeleteFrom(pos);

   }

   

-  while (pos < (int)pathName2.Len())

+  while (pos < (int)path2.Len())

   {

-    pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1);

-    if (pos < 0)

-      pos = pathName2.Len();

-    pathName.SetFrom(pathName2, pos);

-    if (!CreateDir(pathName))

+    int pos2 = NName::FindSepar(path2.Ptr(pos + 1));

+    if (pos2 < 0)

+      pos = path2.Len();

+    else

+      pos += 1 + pos2;

+    path.SetFrom(path2, pos);

+    if (!CreateDir(path))

       return false;

   }

   

@@ -301,8 +395,19 @@
 

 bool DeleteFileAlways(CFSTR path)

 {

-  if (!SetFileAttrib(path, 0))

-    return false;

+  /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.

+     SetFileAttrib("name:stream", ) changes attributes of main file. */

+  {

+    DWORD attrib = NFind::GetFileAttrib(path);

+    if (attrib != INVALID_FILE_ATTRIBUTES

+        && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0

+        && (attrib & FILE_ATTRIBUTE_READONLY) != 0)

+    {

+      if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY))

+        return false;

+    }

+  }

+

   #ifndef _UNICODE

   if (!g_IsNT)

   {

@@ -312,15 +417,17 @@
   else

   #endif

   {

+    /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")).

+       Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */

     IF_USE_MAIN_PATH

       if (::DeleteFileW(fs2us(path)))

         return true;

     #ifdef WIN_LONG_PATH

     if (USE_SUPER_PATH)

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        return BOOLToBool(::DeleteFileW(longPath));

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        return BOOLToBool(::DeleteFileW(superPath));

     }

     #endif

   }

@@ -346,7 +453,7 @@
   if (needRemoveSubItems)

   {

     FString s = path;

-    s += FCHAR_PATH_SEPARATOR;

+    s.Add_PathSepar();

     unsigned prefixSize = s.Len();

     s += FCHAR_ANY_MASK;

     NFind::CEnumerator enumerator(s);

@@ -430,7 +537,7 @@
   bool res = MyGetFullPathName(path, resDirPrefix);

   if (!res)

     resDirPrefix = path;

-  int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR);

+  int pos = resDirPrefix.ReverseFind_PathSepar();

   resFileName = resDirPrefix.Ptr(pos + 1);

   resDirPrefix.DeleteFrom(pos + 1);

   return res;

@@ -480,7 +587,7 @@
       {

         unsigned t = value & 0xF;

         value >>= 4;

-        s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+        s[k] = (FChar)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

       }

       s[k] = '\0';

       if (outFile)

diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
index 1c75788..35f6957 100644
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -24,7 +24,14 @@
 

 bool RemoveDir(CFSTR path);

 bool CreateDir(CFSTR path);

+

+/* CreateComplexDir returns true, if directory can contain files after the call (two cases):

+    1) the directory already exists (network shares and drive paths are supported)

+    2) the directory was created

+  path can be WITH or WITHOUT trailing path separator. */

+

 bool CreateComplexDir(CFSTR path);

+

 bool DeleteFileAlways(CFSTR name);

 bool RemoveDirWithSubItems(const FString &path);

 

diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index 35c0bf6..2ab189d 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -2,13 +2,14 @@
 

 #include "StdAfx.h"

 

-#include "FileFind.h"

-#include "FileIO.h"

-#include "FileName.h"

 #ifndef _UNICODE

 #include "../Common/StringConvert.h"

 #endif

 

+#include "FileFind.h"

+#include "FileIO.h"

+#include "FileName.h"

+

 #ifndef _UNICODE

 extern bool g_IsNT;

 #endif

@@ -58,9 +59,9 @@
 {

   if (!IsDir() || Name.IsEmpty())

     return false;

-  if (Name[0] != FTEXT('.'))

+  if (Name[0] != '.')

     return false;

-  return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.'));

+  return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');

 }

 

 #define WIN_FD_TO_MY_FI(fi, fd) \

@@ -114,6 +115,37 @@
   return true;

 }

 

+/*

+WinXP-64 FindFirstFile():

+  ""      -  ERROR_PATH_NOT_FOUND

+  folder\ -  ERROR_FILE_NOT_FOUND

+  \       -  ERROR_FILE_NOT_FOUND

+  c:\     -  ERROR_FILE_NOT_FOUND

+  c:      -  ERROR_FILE_NOT_FOUND, if current dir is ROOT     ( c:\ )

+  c:      -  OK,                   if current dir is NOT ROOT ( c:\folder )

+  folder  -  OK

+

+  \\               - ERROR_INVALID_NAME

+  \\Server         - ERROR_INVALID_NAME

+  \\Server\        - ERROR_INVALID_NAME

+      

+  \\Server\Share            - ERROR_BAD_NETPATH

+  \\Server\Share            - ERROR_BAD_NET_NAME (Win7).

+             !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon),

+                 when we call it for "\\Server\Share"

+                      

+  \\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

+  \\Server\Share_RootDrive\ - ERROR_INVALID_NAME

+  

+  c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder

+*/

+

 bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)

 {

   if (!Close())

@@ -137,9 +169,9 @@
     #ifdef WIN_LONG_PATH

     if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        _handle = ::FindFirstFileW(longPath, &fd);

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        _handle = ::FindFirstFileW(superPath, &fd);

     }

     #endif

     if (_handle == INVALID_HANDLE_VALUE)

@@ -189,24 +221,51 @@
 

 bool CStreamInfo::IsMainStream() const throw()

 {

-  return Name == L"::$DATA";

+  return StringsAreEqualNoCase_Ascii(Name, "::$DATA");

 };

 

 UString CStreamInfo::GetReducedName() const

 {

+  // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"

   UString s = Name;

-  if (s.Len() >= 6)

-    if (wcscmp(s.RightPtr(6), L":$DATA") == 0)

-      s.DeleteFrom(s.Len() - 6);

+  if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))

+    s.DeleteFrom(s.Len() - 6);

   return s;

 }

 

+/*

+UString CStreamInfo::GetReducedName2() const

+{

+  UString s = GetReducedName();

+  if (!s.IsEmpty() && s[0] == ':')

+    s.Delete(0);

+  return s;

+}

+*/

+

 static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)

 {

   si.Size = sd.StreamSize.QuadPart;

   si.Name = sd.cStreamName;

 }

 

+/*

+  WinXP-64 FindFirstStream():

+  ""      -  ERROR_PATH_NOT_FOUND

+  folder\ -  OK

+  folder  -  OK

+  \       -  OK

+  c:\     -  OK

+  c:      -  OK, if current dir is ROOT     ( c:\ )

+  c:      -  OK, if current dir is NOT ROOT ( c:\folder )

+  \\Server\Share   - OK

+  \\Server\Share\  - OK

+

+  \\               - ERROR_INVALID_NAME

+  \\Server         - ERROR_INVALID_NAME

+  \\Server\        - ERROR_INVALID_NAME

+*/

+

 bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)

 {

   if (!Close())

@@ -218,6 +277,7 @@
   }

   {

     MY_WIN32_FIND_STREAM_DATA sd;

+    SetLastError(0);

     IF_USE_MAIN_PATH

       _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);

     if (_handle == INVALID_HANDLE_VALUE)

@@ -228,9 +288,9 @@
       #ifdef WIN_LONG_PATH

       if (USE_SUPER_PATH)

       {

-        UString longPath;

-        if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-          _handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0);

+        UString superPath;

+        if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+          _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);

       }

       #endif

     }

@@ -278,7 +338,7 @@
 

 #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;

 

-void CFileInfoBase::Clear() throw()

+void CFileInfoBase::ClearBase() throw()

 {

   Size = 0;

   MY_CLEAR_FILETIME(CTime);

@@ -289,43 +349,83 @@
   IsDevice = false;

 }

 

-#if defined(_WIN32) && !defined(UNDER_CE)

+/*

+WinXP-64 GetFileAttributes():

+  If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code

 

-static int FindAltStreamColon(CFSTR path)

+  \    - OK

+  C:\  - OK, if there is such drive,

+  D:\  - ERROR_PATH_NOT_FOUND, if there is no such drive,

+

+  C:\folder     - OK

+  C:\folder\    - OK

+  C:\folderBad  - ERROR_FILE_NOT_FOUND

+

+  \\Server\BadShare  - ERROR_BAD_NETPATH

+  \\Server\Share     - WORKS OK, but MSDN says:

+                          GetFileAttributes for a network share, the function fails, and GetLastError

+                          returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.

+*/

+

+DWORD GetFileAttrib(CFSTR path)

 {

-  for (int i = 0;; i++)

+  #ifndef _UNICODE

+  if (!g_IsNT)

+    return ::GetFileAttributes(fs2fas(path));

+  else

+  #endif

   {

-    FChar c = path[i];

-    if (c == 0)

-      return -1;

-    if (c == ':')

+    IF_USE_MAIN_PATH

     {

-      if (path[i + 1] == '\\')

-        if (i == 1 || (i > 1 && path[i - 2] == '\\'))

-        {

-          wchar_t c0 = path[i - 1];

-          if (c0 >= 'a' && c0 <= 'z' ||

-              c0 >= 'A' && c0 <= 'Z')

-            continue;

-        }

-      return i;

+      DWORD dw = ::GetFileAttributesW(fs2us(path));

+      if (dw != INVALID_FILE_ATTRIBUTES)

+        return dw;

     }

+    #ifdef WIN_LONG_PATH

+    if (USE_SUPER_PATH)

+    {

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        return ::GetFileAttributesW(superPath);

+    }

+    #endif

+    return INVALID_FILE_ATTRIBUTES;

   }

 }

 

-#endif

+/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk

+   so instead of absolute path we have relative path in Name. That is not good in some calls */

+

+/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */

+

+/* CFileInfo::Find()

+We alow the following paths (as FindFirstFile):

+  C:\folder

+  c:                      - if current dir is NOT ROOT ( c:\folder )

+

+also we support paths that are not supported by FindFirstFile:

+  \

+  \\.\c:

+  c:\                     - Name will be without tail slash ( c: )

+  \\?\c:\                 - Name will be without tail slash ( c: )

+  \\Server\Share

+  \\?\UNC\Server\Share

+

+  c:\folder:stream  - Name = folder:stream

+  c:\:stream        - Name = :stream

+  c::stream         - Name = c::stream

+*/

 

 bool CFileInfo::Find(CFSTR path)

 {

   #ifdef SUPPORT_DEVICE_FILE

   if (IsDevicePath(path))

   {

-    Clear();

+    ClearBase();

     Name = path + 4;

-

     IsDevice = true;

-    if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */

-        path[5] == ':' && path[6] == 0)

+    

+    if (NName::IsDrivePath2(path + 4) && path[6] == 0)

     {

       FChar drive[4] = { path[4], ':', '\\', 0 };

       UInt64 clusterSize, totalSize, freeSize;

@@ -350,16 +450,37 @@
   #if defined(_WIN32) && !defined(UNDER_CE)

 

   int colonPos = FindAltStreamColon(path);

-  if (colonPos >= 0)

+  if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)

   {

     UString streamName = fs2us(path + (unsigned)colonPos);

     FString filePath = path;

     filePath.DeleteFrom(colonPos);

-    streamName += L":$DATA"; // change it!!!!

-    if (Find(filePath))

+    /* we allow both cases:

+      name:stream

+      name:stream:$DATA

+    */

+    const unsigned kPostfixSize = 6;

+    if (streamName.Len() <= kPostfixSize

+        || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))

+      streamName += L":$DATA";

+

+    bool isOk = true;

+    

+    if (IsDrivePath2(filePath) &&

+        (colonPos == 2 || colonPos == 3 && filePath[2] == '\\'))

     {

-      // if (IsDir())

-        Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;

+      // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)

+      ClearBase();

+      Name.Empty();

+      if (colonPos == 2)

+        Name = filePath;

+    }

+    else

+      isOk = Find(filePath);

+

+    if (isOk)

+    {

+      Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);

       Size = 0;

       CStreamEnumerator enumerator(filePath);

       for (;;)

@@ -373,10 +494,12 @@
           ::SetLastError(ERROR_FILE_NOT_FOUND);

           return false;

         }

-        if (si.Name.IsEqualToNoCase(streamName))

+        if (si.Name.IsEqualTo_NoCase(streamName))

         {

+          // we delete postfix, if alt stream name is not "::$DATA"

+          if (si.Name.Len() > kPostfixSize + 1)

+            si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);

           Name += us2fs(si.Name);

-          Name.DeleteFrom(Name.Len() - 6);

           Size = si.Size;

           IsAltStream = true;

           return true;

@@ -388,53 +511,94 @@
   #endif

 

   CFindFile finder;

-  if (finder.FindFirst(path, *this))

-    return true;

-  #ifdef _WIN32

+

+  #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;

+    if (IsSuperPath(path))

+      rootSize = kSuperPathPrefixSize;

+    

+    if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)

     {

-      unsigned len = MyStringLen(path);

-      if (len > 2 && path[0] == '\\' && path[1] == '\\')

+      DWORD attrib = GetFileAttrib(path);

+      if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)

       {

-        int startPos = 2;

-        if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path))

-          startPos = kSuperUncPathPrefixSize;

-        int pos = FindCharPosInString(path + startPos, FTEXT('\\'));

-        if (pos >= 0)

+        ClearBase();

+        Attrib = attrib;

+        Name = path + rootSize;

+        Name.DeleteFrom(2); // we don't need backslash (C:)

+        return true;

+      }

+    }

+    else if (IS_PATH_SEPAR(path[0]))

+      if (path[1] == 0)

+      {

+        DWORD attrib = GetFileAttrib(path);

+        if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)

         {

-          pos += startPos + 1;

-          len -= pos;

-          int pos2 = FindCharPosInString(path + pos, FTEXT('\\'));

-          if (pos2 < 0 || pos2 == (int)len - 1)

+          ClearBase();

+          Name.Empty();

+          Attrib = attrib;

+          return true;

+        }

+      }

+      else

+      {

+        const unsigned prefixSize = GetNetworkServerPrefixSize(path);

+        if (prefixSize > 0 && path[prefixSize] != 0)

+        {

+          if (NName::FindSepar(path + prefixSize) < 0)

           {

             FString s = path;

-            if (pos2 < 0)

-            {

-              pos2 = len;

-              s += FTEXT('\\');

-            }

+            s.Add_PathSepar();

             s += FCHAR_ANY_MASK;

+            

+            bool isOK = false;

             if (finder.FindFirst(s, *this))

+            {

               if (Name == FTEXT("."))

               {

-                Name.SetFrom(s.Ptr(pos), pos2);

+                Name = path + prefixSize;

                 return true;

               }

-            ::SetLastError(lastError);

+              isOK = true;

+              /* if "\\server\share" maps to root folder "d:\", there is no "." item.

+                 But it's possible that there are another items */

+            }

+            {

+              DWORD attrib = GetFileAttrib(path);

+              if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)

+              {

+                ClearBase();

+                if (attrib != INVALID_FILE_ATTRIBUTES)

+                  Attrib = attrib;

+                else

+                  SetAsDir();

+                Name = path + prefixSize;

+                return true;

+              }

+            }

+            // ::SetLastError(lastError);

           }

         }

       }

-    }

   }

   #endif

-  return false;

+

+  return finder.FindFirst(path, *this);

 }

 

+

 bool DoesFileExist(CFSTR name)

 {

   CFileInfo fi;

@@ -446,12 +610,14 @@
   CFileInfo fi;

   return fi.Find(name) && fi.IsDir();

 }

+

 bool DoesFileOrDirExist(CFSTR name)

 {

   CFileInfo fi;

   return fi.Find(name);

 }

 

+

 bool CEnumerator::NextAny(CFileInfo &fi)

 {

   if (_findFile.IsHandleAllocated())

@@ -509,9 +675,9 @@
     #ifdef WIN_LONG_PATH

     if (!IsHandleAllocated())

     {

-      UString longPath;

-      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

-        _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);

     }

     #endif

   }

@@ -530,23 +696,22 @@
     UINT32 size = GetLogicalDriveStrings(0, NULL);

     if (size == 0)

       return false;

-    AString buf;

-    UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size));

+    CObjArray<char> buf(size);

+    UINT32 newSize = GetLogicalDriveStrings(size, buf);

     if (newSize == 0 || newSize > size)

       return false;

     AString s;

+    UINT32 prev = 0;

     for (UINT32 i = 0; i < newSize; i++)

     {

-      char c = buf[i];

-      if (c == '\0')

+      if (buf[i] == 0)

       {

+        s = buf + prev;

+        prev = i + 1;

         driveStrings.Add(fas2fs(s));

-        s.Empty();

       }

-      else

-        s += c;

     }

-    return s.IsEmpty();

+    return prev == newSize;

   }

   else

   #endif

@@ -554,23 +719,22 @@
     UINT32 size = GetLogicalDriveStringsW(0, NULL);

     if (size == 0)

       return false;

-    UString buf;

-    UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size));

+    CObjArray<wchar_t> buf(size);

+    UINT32 newSize = GetLogicalDriveStringsW(size, buf);

     if (newSize == 0 || newSize > size)

       return false;

     UString s;

+    UINT32 prev = 0;

     for (UINT32 i = 0; i < newSize; i++)

     {

-      WCHAR c = buf[i];

-      if (c == L'\0')

+      if (buf[i] == 0)

       {

+        s = buf + prev;

+        prev = i + 1;

         driveStrings.Add(us2fs(s));

-        s.Empty();

       }

-      else

-        s += c;

     }

-    return s.IsEmpty();

+    return prev == newSize;

   }

 }

 

diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index 1325253..fc1f387 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -41,8 +41,8 @@
   #endif

   */

 

-  CFileInfoBase() { Clear(); }

-  void Clear() throw();

+  CFileInfoBase() { ClearBase(); }

+  void ClearBase() throw();

 

   void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; }

 

@@ -68,7 +68,7 @@
   #endif

 

   bool IsDots() const throw();

-  bool Find(CFSTR wildcard);

+  bool Find(CFSTR path);

 };

 

 class CFindFileBase

@@ -96,7 +96,8 @@
   UString Name;

   UInt64 Size;

 

-  UString GetReducedName() const;

+  UString GetReducedName() const; // returns ":Name"

+  // UString GetReducedName2() const; // returns "Name"

   bool IsMainStream() const throw();

 };

 

@@ -124,6 +125,8 @@
 bool DoesDirExist(CFSTR name);

 bool DoesFileOrDirExist(CFSTR name);

 

+DWORD GetFileAttrib(CFSTR path);

+

 class CEnumerator

 {

   CFindFile _findFile;

diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index 3dcf5c1..a1d52c0 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -130,7 +130,7 @@
   if (low == 0xFFFFFFFF)

     if (::GetLastError() != NO_ERROR)

       return false;

-  newPosition = (((UInt64)high) << 32) + low;

+  newPosition = (((UInt64)(UInt32)high) << 32) + low;

   return true;

 }

 

diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index 96691b9..af4785f 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/FileLink.cpp b/CPP/Windows/FileLink.cpp
index 1bd1d52..f4c7081 100644
--- a/CPP/Windows/FileLink.cpp
+++ b/CPP/Windows/FileLink.cpp
@@ -102,6 +102,8 @@
   }

 }

 

+#if defined(_WIN32) && !defined(UNDER_CE)

+

 bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)

 {

   bool isAbs = IsAbsolutePath(path);

@@ -175,13 +177,21 @@
   return true;

 }

 

+#endif

+

 static void GetString(const Byte *p, unsigned len, UString &res)

 {

-  wchar_t *s = res.GetBuffer(len);

-  for (unsigned i = 0; i < len; i++)

-    s[i] = Get16(p + i * 2);

-  s[len] = 0;

-  res.ReleaseBuffer();

+  wchar_t *s = res.GetBuf(len);

+  unsigned i;

+  for (i = 0; i < len; i++)

+  {

+    wchar_t c = Get16(p + i * 2);

+    if (c == 0)

+      break;

+    s[i] = c;

+  }

+  s[i] = 0;

+  res.ReleaseBuf_SetLen(i);

 }

 

 bool CReparseAttr::Parse(const Byte *p, size_t size)

@@ -367,7 +377,7 @@
 static bool CreatePrefixDirOfFile(CFSTR path)

 {

   FString path2 = path;

-  int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR);

+  int pos = path2.ReverseFind_PathSepar();

   if (pos < 0)

     return true;

   #ifdef _WIN32

diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index 9189ceb..773b834 100644
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -12,13 +12,41 @@
 namespace NFile {

 namespace NName {

 

+#define IS_SEPAR(c) IS_PATH_SEPAR(c)

+

+int FindSepar(const wchar_t *s) throw()

+{

+  for (const wchar_t *p = s;; p++)

+  {

+    const wchar_t c = *p;

+    if (c == 0)

+      return -1;

+    if (IS_SEPAR(c))

+      return (int)(p - s);

+  }

+}

+

+#ifndef USE_UNICODE_FSTRING

+int FindSepar(const FChar *s) throw()

+{

+  for (const FChar *p = s;; p++)

+  {

+    const FChar c = *p;

+    if (c == 0)

+      return -1;

+    if (IS_SEPAR(c))

+      return (int)(p - s);

+  }

+}

+#endif

+

 #ifndef USE_UNICODE_FSTRING

 void NormalizeDirPathPrefix(FString &dirPath)

 {

   if (dirPath.IsEmpty())

     return;

-  if (dirPath.Back() != FCHAR_PATH_SEPARATOR)

-    dirPath += FCHAR_PATH_SEPARATOR;

+  if (!IsPathSepar(dirPath.Back()))

+    dirPath.Add_PathSepar();

 }

 #endif

 

@@ -26,26 +54,51 @@
 {

   if (dirPath.IsEmpty())

     return;

-  if (dirPath.Back() != WCHAR_PATH_SEPARATOR)

-    dirPath += WCHAR_PATH_SEPARATOR;

+  if (!IsPathSepar(dirPath.Back()))

+    dirPath.Add_PathSepar();

 }

 

+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')

 

-#ifdef _WIN32

+bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }

+

+bool IsAltPathPrefix(CFSTR s) throw()

+{

+  unsigned len = MyStringLen(s);

+  if (len == 0)

+    return false;

+  if (s[len - 1] != ':')

+    return false;

+

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  if (IsDevicePath(s))

+    return false;

+  if (IsSuperPath(s))

+  {

+    s += kSuperPathPrefixSize;

+    len -= kSuperPathPrefixSize;

+  }

+  if (len == 2 && IsDrivePath2(s))

+    return false;

+  #endif

+

+  return true;

+}

+

+#if defined(_WIN32) && !defined(UNDER_CE)

 

 const wchar_t *kSuperPathPrefix = L"\\\\?\\";

 static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";

 

-#define IS_DEVICE_PATH(s)  ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\')

-#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\')

-#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\')

-#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')

+#define IS_DEVICE_PATH(s)          (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))

+#define IS_SUPER_PREFIX(s)         (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))

+#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))

 

 #define IS_UNC_WITH_SLASH(s) ( \

-  ((s)[0] == 'U' || (s)[0] == 'u') && \

-  ((s)[1] == 'N' || (s)[1] == 'n') && \

-  ((s)[2] == 'C' || (s)[2] == 'c') && \

-   (s)[3] == '\\')

+     ((s)[0] == 'U' || (s)[0] == 'u') \

+  && ((s)[1] == 'N' || (s)[1] == 'n') \

+  && ((s)[2] == 'C' || (s)[2] == 'c') \

+  && IS_SEPAR((s)[3]))

 

 bool IsDevicePath(CFSTR s) throw()

 {

@@ -81,50 +134,133 @@
 }

 

 bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }

-

-bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }

-bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }

-bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }

-// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }

-

-#ifndef USE_UNICODE_FSTRING

-bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }

-bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }

-bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }

-#endif // USE_UNICODE_FSTRING

-

-bool IsAbsolutePath(const wchar_t *s) throw()

+bool IsNetworkPath(CFSTR s) throw()

 {

-  return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s);

+  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))

+    return false;

+  if (IsSuperUncPath(s))

+    return true;

+  FChar c = s[2];

+  return (c != '.' && c != '?');

+}

+

+unsigned GetNetworkServerPrefixSize(CFSTR s) throw()

+{

+  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))

+    return 0;

+  unsigned prefixSize = 2;

+  if (IsSuperUncPath(s))

+    prefixSize = kSuperUncPathPrefixSize;

+  else

+  {

+    FChar c = s[2];

+    if (c == '.' || c == '?')

+      return 0;

+  }

+  int pos = FindSepar(s + prefixSize);

+  if (pos < 0)

+    return 0;

+  return prefixSize + pos + 1;

+}

+

+bool IsNetworkShareRootPath(CFSTR s) throw()

+{

+  unsigned prefixSize = GetNetworkServerPrefixSize(s);

+  if (prefixSize == 0)

+    return false;

+  s += prefixSize;

+  int pos = FindSepar(s);

+  if (pos < 0)

+    return true;

+  return s[(unsigned)pos + 1] == 0;

 }

 

 static const unsigned kDrivePrefixSize = 3; /* c:\ */

 

+bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }

+// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }

+bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }

+bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }

+// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }

+

+#ifndef USE_UNICODE_FSTRING

+bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }

+// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }

+bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }

+bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }

+bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }

+#endif // USE_UNICODE_FSTRING

+

+/*

+bool IsDrivePath_SuperAllowed(CFSTR s)

+{

+  if (IsSuperPath(s))

+    s += kSuperPathPrefixSize;

+  return IsDrivePath(s);

+}

+*/

+

+bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()

+{

+  if (IsSuperPath(s))

+    s += kSuperPathPrefixSize;

+  return IsDrivePath(s) && s[kDrivePrefixSize] == 0;

+}

+

+bool IsAbsolutePath(const wchar_t *s) throw()

+{

+  return IS_SEPAR(s[0]) || IsDrivePath2(s);

+}

+

+int FindAltStreamColon(CFSTR path)

+{

+  unsigned i = 0;

+  if (IsDrivePath2(path))

+    i = 2;

+  int colonPos = -1;

+  for (;; i++)

+  {

+    FChar c = path[i];

+    if (c == 0)

+      return colonPos;

+    if (c == ':')

+    {

+      if (colonPos < 0)

+        colonPos = i;

+      continue;

+    }

+    if (IS_SEPAR(c))

+      colonPos = -1;

+  }

+}

+

 #ifndef USE_UNICODE_FSTRING

 

-static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw()

+static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)

 {

   // Network path: we look "server\path\" as root prefix

-  int pos = FindCharPosInString(s, '\\');

+  int pos = FindSepar(s);

   if (pos < 0)

     return 0;

-  int pos2 = FindCharPosInString(s + pos + 1, '\\');

+  int pos2 = FindSepar(s + (unsigned)pos + 1);

   if (pos2 < 0)

     return 0;

   return pos + pos2 + 2;

 }

 

-static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw()

+static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)

 {

   if (IsDrivePath(s))

     return kDrivePrefixSize;

-  if (s[0] != '\\' || s[1] != '\\')

+  if (!IS_SEPAR(s[0]))

     return 0;

+  if (s[1] == 0 || !IS_SEPAR(s[1]))

+    return 1;

   unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);

   return (size == 0) ? 0 : 2 + size;

 }

 

-static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()

+static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)

 {

   if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))

   {

@@ -132,13 +268,13 @@
     return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;

   }

   // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"

-  int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR);

+  int pos = FindSepar(s + kSuperPathPrefixSize);

   if (pos < 0)

     return 0;

   return kSuperPathPrefixSize + pos + 1;

 }

 

-unsigned GetRootPrefixSize(CFSTR s) throw()

+unsigned GetRootPrefixSize(CFSTR s)

 {

   if (IS_DEVICE_PATH(s))

     return kDevicePathPrefixSize;

@@ -149,29 +285,31 @@
 

 #endif // USE_UNICODE_FSTRING

 

-static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()

+static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)

 {

   // Network path: we look "server\path\" as root prefix

-  int pos = FindCharPosInString(s, L'\\');

+  int pos = FindSepar(s);

   if (pos < 0)

     return 0;

-  int pos2 = FindCharPosInString(s + pos + 1, L'\\');

+  int pos2 = FindSepar(s + (unsigned)pos + 1);

   if (pos2 < 0)

     return 0;

   return pos + pos2 + 2;

 }

 

-static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()

+static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)

 {

   if (IsDrivePath(s))

     return kDrivePrefixSize;

-  if (s[0] != '\\' || s[1] != '\\')

+  if (!IS_SEPAR(s[0]))

     return 0;

+  if (s[1] == 0 || !IS_SEPAR(s[1]))

+    return 1;

   unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);

   return (size == 0) ? 0 : 2 + size;

 }

 

-static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()

+static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)

 {

   if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))

   {

@@ -179,7 +317,7 @@
     return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;

   }

   // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"

-  int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\');

+  int pos = FindSepar(s + kSuperPathPrefixSize);

   if (pos < 0)

     return 0;

   return kSuperPathPrefixSize + pos + 1;

@@ -196,12 +334,12 @@
 

 #else // _WIN32

 

-bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR }

+bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }

 

 #ifndef USE_UNICODE_FSTRING

-unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }

+unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }

 #endif

-unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }

+unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }

 

 #endif // _WIN32

 

@@ -234,56 +372,68 @@
 static bool ResolveDotsFolders(UString &s)

 {

   #ifdef _WIN32

-  s.Replace(L'/', WCHAR_PATH_SEPARATOR);

+  // s.Replace(L'/', WCHAR_PATH_SEPARATOR);

   #endif

-  for (int i = 0;;)

+  

+  for (unsigned i = 0;;)

   {

-    wchar_t c = s[i];

+    const wchar_t c = s[i];

     if (c == 0)

       return true;

-    if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR))

+    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))

     {

-      wchar_t c1 = s[i + 1];

+      const wchar_t c1 = s[i + 1];

       if (c1 == '.')

       {

-        wchar_t c2 = s[i + 2];

-        if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0)

+        const wchar_t c2 = s[i + 2];

+        if (IS_SEPAR(c2) || c2 == 0)

         {

           if (i == 0)

             return false;

           int k = i - 2;

-          for (; k >= 0; k--)

-            if (s[k] == WCHAR_PATH_SEPARATOR)

+          i += 2;

+          

+          for (;; k--)

+          {

+            if (k < 0)

+              return false;

+            if (!IS_SEPAR(s[(unsigned)k]))

               break;

+          }

+

+          do

+            k--;

+          while (k >= 0 && !IS_SEPAR(s[(unsigned)k]));

+          

           unsigned num;

+          

           if (k >= 0)

           {

-            num = i + 2 - k;

+            num = i - k;

             i = k;

           }

           else

           {

-            num = (c2 == 0 ? (i + 2) : (i + 3));

+            num = (c2 == 0 ? i : (i + 1));

             i = 0;

           }

+          

           s.Delete(i, num);

           continue;

         }

       }

-      else

+      else if (IS_SEPAR(c1) || c1 == 0)

       {

-        if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0)

-        {

-          unsigned num = 2;

-          if (i != 0)

-            i--;

-          else if (c1 == 0)

-            num = 1;

-          s.Delete(i, num);

-          continue;

-        }

+        unsigned num = 2;

+        if (i != 0)

+          i--;

+        else if (c1 == 0)

+          num = 1;

+        s.Delete(i, num);

+        continue;

       }

     }

+

     i++;

   }

 }

@@ -308,11 +458,11 @@
     FChar c = s[i];

     if (c == 0)

       return false;

-    if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR))

+    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))

     {

       FChar c1 = s[i + 1];

-      if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR ||

-          (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR)))

+      if (c1 == 0 || IS_SEPAR(c1) ||

+          (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))

         return true;

     }

   }

@@ -360,16 +510,16 @@
     if (c == '.' || c == ' ')

     {

       FChar c2 = s[i + 1];

-      if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR)

+      if (c2 == 0 || IS_SEPAR(c2))

       {

         // if it's "." or "..", it's not bad name.

         if (c == '.')

         {

-          if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)

+          if (i == 0 || IS_SEPAR(s[i - 1]))

             continue;

           if (s[i - 1] == '.')

           {

-            if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR)

+            if (i - 1 == 0 || IS_SEPAR(s[i - 2]))

               continue;

           }

         }

@@ -431,14 +581,17 @@
     return true;

   }

 

-  if (c == CHAR_PATH_SEPARATOR)

+  if (IS_SEPAR(c))

   {

-    if (s[1] == CHAR_PATH_SEPARATOR)

+    if (IS_SEPAR(s[1]))

     {

       UString temp = fs2us(s + 2);

       unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);

-      if (fixedSize == 0) // maybe we must ignore that error to allow short network paths?

+      // we ignore that error to allow short network paths server\share?

+      /*

+      if (fixedSize == 0)

         return false;

+      */

       UString rem = &temp[fixedSize];

       if (!ResolveDotsFolders(rem))

         return false;

@@ -451,14 +604,17 @@
   }

   else

   {

-    if (IsDrivePath(s))

+    if (IsDrivePath2(s))

     {

       UString temp = fs2us(s);

-      UString rem = &temp[kDrivePrefixSize];

+      unsigned prefixSize = 2;

+      if (IsDrivePath(s))

+        prefixSize = kDrivePrefixSize;

+      UString rem = temp.Ptr(prefixSize);

       if (!ResolveDotsFolders(rem))

         return true;

       res += kSuperPathPrefix;

-      temp.DeleteFrom(kDrivePrefixSize);

+      temp.DeleteFrom(prefixSize);

       res += temp;

       res += rem;

       return true;

@@ -468,8 +624,7 @@
   UString curDir;

   if (!GetCurDir(curDir))

     return false;

-  if (curDir.Back() != WCHAR_PATH_SEPARATOR)

-    curDir += WCHAR_PATH_SEPARATOR;

+  NormalizeDirPathPrefix(curDir);

 

   unsigned fixedSizeStart = 0;

   unsigned fixedSize = 0;

@@ -489,10 +644,10 @@
     }

     else

     {

-      if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR)

+      if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))

         return false;

       fixedSizeStart = 2;

-      fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);

+      fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));

       if (fixedSize == 0)

         return false;

       superMarker = kSuperUncPrefix;

@@ -500,7 +655,7 @@
   }

   

   UString temp;

-  if (c == CHAR_PATH_SEPARATOR)

+  if (IS_SEPAR(c))

   {

     temp = fs2us(s + 1);

   }

@@ -584,7 +739,7 @@
 

   #ifdef UNDER_CE

 

-  if (s[0] != CHAR_PATH_SEPARATOR)

+  if (!IS_SEPAR(s[0]))

   {

     if (!dirPrefix)

       return false;

@@ -614,7 +769,7 @@
     return true;

   if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))

     return true;

-  if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR)

+  if (IS_SEPAR(c) && IS_SEPAR(s[1]))

     return true;

   if (IsDrivePath(s))

     return true;

@@ -628,8 +783,7 @@
     if (!GetCurDir(curDir))

       return false;

   }

-  if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR)

-    curDir += WCHAR_PATH_SEPARATOR;

+  NormalizeDirPathPrefix(curDir);

 

   unsigned fixedSize = 0;

 

@@ -647,9 +801,9 @@
       fixedSize = kDrivePrefixSize;

     else

     {

-      if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR)

+      if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))

         return false;

-      fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);

+      fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));

       if (fixedSize == 0)

         return false;

       fixedSize += 2;

@@ -659,7 +813,7 @@
   #endif // _WIN32

   

   UString temp;

-  if (s[0] == CHAR_PATH_SEPARATOR)

+  if (IS_SEPAR(s[0]))

   {

     temp = fs2us(s + 1);

   }

diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
index 7455654..e2720ff 100644
--- a/CPP/Windows/FileName.h
+++ b/CPP/Windows/FileName.h
@@ -9,29 +9,70 @@
 namespace NFile {

 namespace NName {

 

+int FindSepar(const wchar_t *s) throw();

+#ifndef USE_UNICODE_FSTRING

+int FindSepar(const FChar *s) throw();

+#endif

+

 void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty

 void NormalizeDirPathPrefix(UString &dirPath);

 

-#ifdef _WIN32

+bool IsDrivePath(const wchar_t *s) throw();  // first 3 chars are drive chars like "a:\\"

+

+bool IsAltPathPrefix(CFSTR s) throw(); /* name: */

+

+#if defined(_WIN32) && !defined(UNDER_CE)

 

 extern const wchar_t *kSuperPathPrefix; /* \\?\ */

 const unsigned kDevicePathPrefixSize = 4;

 const unsigned kSuperPathPrefixSize = 4;

 const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;

 

-bool IsDevicePath(CFSTR s) throw(); /* \\.\ */

-bool IsSuperUncPath(CFSTR s) throw();

+bool IsDevicePath(CFSTR s) throw();   /* \\.\ */

+bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */

+bool IsNetworkPath(CFSTR s) throw();  /* \\?\UNC\ or \\SERVER */

 

-bool IsDrivePath(const wchar_t *s) throw();

+/* GetNetworkServerPrefixSize() returns size of server prefix:

+     \\?\UNC\SERVER\

+     \\SERVER\

+  in another cases it returns 0

+*/

+

+unsigned GetNetworkServerPrefixSize(CFSTR s) throw();

+

+bool IsNetworkShareRootPath(CFSTR s) throw();  /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */

+

+// bool IsDrivePath_SuperAllowed(CFSTR s) throw();  // first chars are drive chars like "a:\" or "\\?\a:\"

+bool IsDriveRootPath_SuperAllowed(CFSTR s) throw();  // exact drive root path "a:\" or "\\?\a:\"

+

+bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:"

+// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:"

 bool IsSuperPath(const wchar_t *s) throw();

 bool IsSuperOrDevicePath(const wchar_t *s) throw();

 

 #ifndef USE_UNICODE_FSTRING

+bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:"

+// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:"

 bool IsDrivePath(CFSTR s) throw();

 bool IsSuperPath(CFSTR s) throw();

 bool IsSuperOrDevicePath(CFSTR s) throw();

+

+/* GetRootPrefixSize() returns size of ROOT PREFIX for cases:

+     \

+     \\.\

+     C:\

+     \\?\C:\

+     \\?\UNC\SERVER\Shared\

+     \\SERVER\Shared\

+  in another cases it returns 0

+*/

+

+unsigned GetRootPrefixSize(CFSTR s) throw();

+

 #endif

 

+int FindAltStreamColon(CFSTR path);

+

 #endif // _WIN32

 

 bool IsAbsolutePath(const wchar_t *s) throw();

@@ -44,7 +85,7 @@
 const int kSuperPathType_UseMainAndSuper = 2;

 

 int GetUseSuperPathType(CFSTR s) throw();

-bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew);

+bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew);

 bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);

 

 #define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper)

diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
index 559b6b0..7a2cfd5 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 45c6bcb..1336fe5 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 b8fa99b..401e239 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/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 6ab0e00..6b3f20b 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -9,9 +9,23 @@
 namespace NWindows {

 namespace NCOM {

 

+BSTR AllocBstrFromAscii(const char *s) throw()

+{

+  if (!s)

+    return NULL;

+  UINT len = (UINT)strlen(s);

+  BSTR p = ::SysAllocStringLen(NULL, len);

+  if (p)

+  {

+    for (UINT i = 0; i <= len; i++)

+      p[i] = (Byte)s[i];

+  }

+  return p;

+}

+

 HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()

 {

-  p->bstrVal = ::SysAllocStringLen(0, numChars);

+  p->bstrVal = ::SysAllocStringLen(NULL, numChars);

   if (!p->bstrVal)

   {

     p->vt = VT_ERROR;

@@ -24,19 +38,15 @@
 

 HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()

 {

-  UINT len = (UINT)strlen(s);

-  p->bstrVal = ::SysAllocStringLen(0, len);

-  if (!p->bstrVal)

+  p->bstrVal = AllocBstrFromAscii(s);

+  if (p->bstrVal)

   {

-    p->vt = VT_ERROR;

-    p->scode = E_OUTOFMEMORY;

-    return E_OUTOFMEMORY;

+    p->vt = VT_BSTR;

+    return S_OK;

   }

-  p->vt = VT_BSTR;

-  BSTR dest = p->bstrVal;

-  for (UINT i = 0; i <= len; i++)

-    dest[i] = s[i];

-  return S_OK;

+  p->vt = VT_ERROR;

+  p->scode = E_OUTOFMEMORY;

+  return E_OUTOFMEMORY;

 }

 

 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)

@@ -68,6 +78,7 @@
   InternalCopy(&varSrc);

   return *this;

 }

+

 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)

 {

   InternalCopy(&varSrc);

@@ -97,24 +108,60 @@
   return *this;

 }

 

+CPropVariant& CPropVariant::operator=(const UString &s)

+{

+  InternalClear();

+  vt = VT_BSTR;

+  wReserved1 = 0;

+  bstrVal = ::SysAllocStringLen(s, s.Len());

+  if (!bstrVal)

+    throw kMemException;

+  return *this;

+}

+

+CPropVariant& CPropVariant::operator=(const UString2 &s)

+{

+  /*

+  if (s.IsEmpty())

+    *this = L"";

+  else

+  */

+  {

+    InternalClear();

+    vt = VT_BSTR;

+    wReserved1 = 0;

+    bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());

+    if (!bstrVal)

+      throw kMemException;

+    /* SysAllocStringLen probably appends a null-terminating character for NULL string.

+       But it doesn't specified in MSDN.

+       But we suppose that it works

+

+    if (!s.GetRawPtr())

+    {

+      *bstrVal = 0;

+    }

+    */

+

+    /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)

+                         pointers to this function causes  an unexpected termination of the application.

+       Is it safe? Maybe we must chamnge the code for that case ? */

+  }

+  return *this;

+}

+

 CPropVariant& CPropVariant::operator=(const char *s)

 {

   InternalClear();

   vt = VT_BSTR;

   wReserved1 = 0;

-  UINT len = (UINT)strlen(s);

-  bstrVal = ::SysAllocStringLen(0, len);

+  bstrVal = AllocBstrFromAscii(s);

   if (!bstrVal)

   {

     throw kMemException;

     // vt = VT_ERROR;

     // scode = E_OUTOFMEMORY;

   }

-  else

-  {

-    for (UINT i = 0; i <= len; i++)

-      bstrVal[i] = s[i];

-  }

   return *this;

 }

 

@@ -135,7 +182,7 @@
     InternalClear();

   vt = VT_BSTR;

   wReserved1 = 0;

-  bstrVal = ::SysAllocStringLen(0, numChars);

+  bstrVal = ::SysAllocStringLen(NULL, numChars);

   if (!bstrVal)

   {

     throw kMemException;

@@ -201,7 +248,7 @@
 HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()

 {

   ::VariantClear((tagVARIANT *)this);

-  switch(pSrc->vt)

+  switch (pSrc->vt)

   {

     case VT_UI1:

     case VT_I1:

diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
index 4757705..0304565 100644
--- a/CPP/Windows/PropVariant.h
+++ b/CPP/Windows/PropVariant.h
@@ -5,10 +5,13 @@
 

 #include "../Common/MyTypes.h"

 #include "../Common/MyWindows.h"

+#include "../Common/MyString.h"

 

 namespace NWindows {

 namespace NCOM {

 

+BSTR AllocBstrFromAscii(const char *s) throw();

+

 HRESULT PropVariant_Clear(PROPVARIANT *p) throw();

 

 HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw();

@@ -57,7 +60,7 @@
   CPropVariant(const CPropVariant &varSrc);

   CPropVariant(BSTR bstrSrc);

   CPropVariant(LPCOLESTR lpszSrc);

-  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };

+  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }

   CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }

 

 private:

@@ -74,6 +77,8 @@
   CPropVariant& operator=(const PROPVARIANT &varSrc);

   CPropVariant& operator=(BSTR bstrSrc);

   CPropVariant& operator=(LPCOLESTR lpszSrc);

+  CPropVariant& operator=(const UString &s);

+  CPropVariant& operator=(const UString2 &s);

   CPropVariant& operator=(const char *s);

   

   CPropVariant& operator=(bool bSrc) throw();

diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
index a9a0d97..1501a49 100644
--- a/CPP/Windows/PropVariantConv.cpp
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -37,7 +37,17 @@
     UINT_TO_STR_2(' ', st.wHour);

     UINT_TO_STR_2(':', st.wMinute);

     if (includeSeconds)

+    {

       UINT_TO_STR_2(':', st.wSecond);

+      /*

+      *s++ = '.';

+      unsigned val = st.wMilliseconds;

+      s[2] = (char)('0' + val % 10); val /= 10;

+      s[1] = (char)('0' + val % 10);

+      s[0] = (char)('0' + val / 10);

+      s += 3;

+      */

+    }

   }

   *s = 0;

   return true;

@@ -93,7 +103,7 @@
     case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;

     case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;

     case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;

-    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;

+    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;

     default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);

   }

 }

diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
index 8c3a751..71ca17f 100644
--- a/CPP/Windows/Registry.cpp
+++ b/CPP/Windows/Registry.cpp
@@ -2,6 +2,8 @@
 

 #include "StdAfx.h"

 

+#include <wchar.h>

+

 #ifndef _UNICODE

 #include "../Common/StringConvert.h"

 #endif

@@ -75,15 +77,15 @@
   if (res != ERROR_SUCCESS)

     return res;

   FILETIME fileTime;

-  const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL

-  DWORD size = kBufferSize;

-  TCHAR buffer[kBufferSize];

+  const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL

+  DWORD size = kBufSize;

+  TCHAR buffer[kBufSize];

   while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)

   {

     res = key.RecurseDeleteKey(buffer);

     if (res != ERROR_SUCCESS)

       return res;

-    size = kBufferSize;

+    size = kBufSize;

   }

   key.Close();

   return DeleteSubKey(subKeyName);

@@ -226,7 +228,6 @@
 

 LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()

 {

-  MYASSERT(count != NULL);

   DWORD type = 0;

   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

   MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));

@@ -237,38 +238,47 @@
 {

   value.Empty();

   DWORD type = 0;

-  UInt32 currentSize = 0;

-  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&currentSize);

+  UInt32 curSize = 0;

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize);

   if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

     return res;

-  res = QueryValue(name, value.GetBuffer(currentSize), currentSize);

-  value.ReleaseBuffer();

+  UInt32 curSize2 = curSize;

+  res = QueryValue(name, value.GetBuf(curSize), curSize2);

+  if (curSize > curSize2)

+    curSize = curSize2;

+  value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR));

   return res;

 }

 

+

 #ifndef _UNICODE

+

 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)

 {

-  MYASSERT(count != NULL);

   DWORD type = 0;

   LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

   MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));

   return res;

 }

+

 LONG CKey::QueryValue(LPCWSTR name, UString &value)

 {

   value.Empty();

   DWORD type = 0;

-  UInt32 currentSize = 0;

+  UInt32 curSize = 0;

 

   LONG res;

+

   if (g_IsNT)

   {

-    res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&currentSize);

+    res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize);

     if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

       return res;

-    res = QueryValue(name, value.GetBuffer(currentSize), currentSize);

-    value.ReleaseBuffer();

+    UInt32 curSize2 = curSize;

+    res = QueryValue(name, value.GetBuf(curSize), curSize2);

+    if (curSize > curSize2)

+      curSize = curSize2;

+    value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t));

   }

   else

   {

@@ -276,10 +286,13 @@
     res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);

     value = GetUnicodeString(vTemp);

   }

+  

   return res;

 }

+

 #endif

 

+

 LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()

 {

   DWORD type = 0;

@@ -304,14 +317,14 @@
 {

   keyNames.Clear();

   CSysString keyName;

-  for (UInt32 index = 0; ; index++)

+  for (DWORD index = 0; ; index++)

   {

-    const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL

+    const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL

     FILETIME lastWriteTime;

-    UInt32 nameSize = kBufferSize;

-    LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),

+    UInt32 nameSize = kBufSize;

+    LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize),

         (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);

-    keyName.ReleaseBuffer();

+    keyName.ReleaseBuf_CalcLen(kBufSize);

     if (result == ERROR_NO_MORE_ITEMS)

       break;

     if (result != ERROR_SUCCESS)

@@ -321,47 +334,56 @@
   return ERROR_SUCCESS;

 }

 

-LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw()

+LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)

 {

-  UInt32 numChars = 0;

+  size_t numChars = 0;

+  

   unsigned i;

+  

   for (i = 0; i < strings.Size(); i++)

     numChars += strings[i].Len() + 1;

-  CBuffer<wchar_t> buffer(numChars);

-  unsigned pos = 0;

+  

+  CObjArray<wchar_t> buffer(numChars);

+  size_t pos = 0;

+  

   for (i = 0; i < strings.Size(); i++)

   {

     const UString &s = strings[i];

-    MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);

-    pos += s.Len() + 1;

+    size_t size = s.Len() + 1;

+    wmemcpy(buffer + pos, s, size);

+    pos += size;

   }

-  return SetValue(valueName, buffer, numChars * sizeof(wchar_t));

+  return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));

 }

 

 LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)

 {

   strings.Clear();

   CByteBuffer buffer;

-  UInt32 dataSize;

+  UInt32 dataSize = 0;

   LONG res = QueryValue(valueName, buffer, dataSize);

   if (res != ERROR_SUCCESS)

     return res;

+  if (dataSize > buffer.Size())

+    return E_FAIL;

   if (dataSize % sizeof(wchar_t) != 0)

     return E_FAIL;

+

   const wchar_t *data = (const wchar_t *)(const Byte  *)buffer;

-  unsigned numChars = dataSize / sizeof(wchar_t);

+  size_t numChars = dataSize / sizeof(wchar_t);

+  size_t prev = 0;

   UString s;

-  for (unsigned i = 0; i < numChars; i++)

+  

+  for (size_t i = 0; i < numChars; i++)

   {

-    wchar_t c = data[i];

-    if (c == 0)

+    if (data[i] == 0)

     {

+      s = data + prev;

       strings.Add(s);

-      s.Empty();

+      prev = i + 1;

     }

-    else

-      s += c;

   }

+  

   return res;

 }

 

diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
index 4ac6662..0a31230 100644
--- a/CPP/Windows/Registry.h
+++ b/CPP/Windows/Registry.h
@@ -55,7 +55,7 @@
 

   LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();

 

-  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw();

+  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);

   LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);

 

   LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();

diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp
index d20e713..c28e60e 100644
--- a/CPP/Windows/ResourceString.cpp
+++ b/CPP/Windows/ResourceString.cpp
@@ -25,10 +25,10 @@
   do

   {

     size <<= 1;

-    len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size);

+    len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size);

   }

   while (size - len <= 1);

-  s.ReleaseBuffer();

+  s.ReleaseBuf_CalcLen(len);

   return s;

 }

 

@@ -43,10 +43,10 @@
   do

   {

     size <<= 1;

-    len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size);

+    len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size);

   }

   while (size - len <= 1);

-  s.ReleaseBuffer();

+  s.ReleaseBuf_CalcLen(len);

 }

 

 // NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.

diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp
index 69ef32c..8646cc9 100644
--- a/CPP/Windows/SecurityUtils.cpp
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -2,6 +2,8 @@
 

 #include "StdAfx.h"

 

+#include "../Common/MyString.h"

+

 #include "SecurityUtils.h"

 

 namespace NWindows {

@@ -14,17 +16,18 @@
   DWORD accountNameSize = 0, domainNameSize = 0;

 

   if (!::LookupAccountSid(systemName, sid,

-      accountName.GetBuffer(0), &accountNameSize,

-      domainName.GetBuffer(0), &domainNameSize, sidNameUse))

+      accountName.GetBuf(0), &accountNameSize,

+      domainName.GetBuf(0), &domainNameSize, sidNameUse))

   {

     if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)

       return false;

   }

+  DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize;

   bool result = BOOLToBool(::LookupAccountSid(systemName, sid,

-      accountName.GetBuffer(accountNameSize), &accountNameSize,

-      domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));

-  accountName.ReleaseBuffer();

-  domainName.ReleaseBuffer();

+      accountName.GetBuf(accountNameSize), &accountNameSize2,

+      domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse));

+  accountName.ReleaseBuf_CalcLen(accountNameSize);

+  domainName.ReleaseBuf_CalcLen(domainNameSize);

   return result;

 }

 */

@@ -176,4 +179,3 @@
 }

 

 }}

-

diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
index d5d61a9..b3df199 100644
--- a/CPP/Windows/Shell.cpp
+++ b/CPP/Windows/Shell.cpp
@@ -95,16 +95,18 @@
   {

     AString fileNameA;

     UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);

-    QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);

-    fileNameA.ReleaseBuffer();

+    const unsigned len = bufferSize + 2;

+    QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);

+    fileNameA.ReleaseBuf_CalcLen(len);

     fileName = GetUnicodeString(fileNameA);

   }

   else

   #endif

   {

     UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);

-    QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);

-    fileName.ReleaseBuffer();

+    const unsigned len = bufferSize + 2;

+    QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);

+    fileName.ReleaseBuf_CalcLen(len);

   }

   return fileName;

 }

@@ -120,8 +122,9 @@
 

 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)

 {

-  bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));

-  path.ReleaseBuffer();

+  const unsigned len = MAX_PATH * 2;

+  bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));

+  path.ReleaseBuf_CalcLen(len);

   return result;

 }

 

@@ -174,7 +177,7 @@
 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)

 {

   #ifndef UNDER_CE

-  switch(uMsg)

+  switch (uMsg)

   {

     case BFFM_INITIALIZED:

     {

@@ -208,14 +211,16 @@
   browseInfo.hwndOwner = owner;

   browseInfo.pidlRoot = NULL;

 

-  // there are Unicode/astring problems in WinCE SDK!!!

+  // there are Unicode/Astring problems in some WinCE SDK ?

+  /*

   #ifdef UNDER_CE

-  browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);

+  browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);

   browseInfo.lpszTitle = (LPCSTR)title;

   #else

-  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);

+  */

+  browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);

   browseInfo.lpszTitle = title;

-  #endif

+  // #endif

   browseInfo.ulFlags = ulFlags;

   browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;

   browseInfo.lParam = (LPARAM)initialFolder;

@@ -244,8 +249,9 @@
     ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");

   if (shGetPathFromIDListW == 0)

     return false;

-  bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));

-  path.ReleaseBuffer();

+  const unsigned len = MAX_PATH * 2;

+  bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));

+  path.ReleaseBuf_CalcLen(len);

   return result;

 }

 

@@ -269,7 +275,7 @@
 

 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)

 {

-  switch(uMsg)

+  switch (uMsg)

   {

     case BFFM_INITIALIZED:

     {

@@ -302,7 +308,7 @@
   BROWSEINFOW browseInfo;

   browseInfo.hwndOwner = owner;

   browseInfo.pidlRoot = NULL;

-  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);

+  browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);

   browseInfo.lpszTitle = title;

   browseInfo.ulFlags = ulFlags;

   browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;

diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 545ea0e..5d894d1 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"

@@ -9,6 +11,8 @@
 namespace NWindows {

 namespace NSystem {

 

+#ifdef _WIN32

+

 UInt32 GetNumberOfProcessors()

 {

   SYSTEM_INFO systemInfo;

@@ -16,6 +20,18 @@
   return (UInt32)systemInfo.dwNumberOfProcessors;

 }

 

+#else

+

+UInt32 GetNumberOfProcessors()

+{

+  return 1;

+}

+

+#endif

+

+

+#ifdef _WIN32

+

 #ifndef UNDER_CE

 

 #if !defined(_WIN64) && defined(__GNUC__)

@@ -43,29 +59,53 @@
 

 #endif

 

-UInt64 GetRamSize()

+#endif

+

+

+bool GetRamSize(UInt64 &size)

 {

+  size = (UInt64)(sizeof(size_t)) << 29;

+

+  #ifdef _WIN32

+  

   #ifndef UNDER_CE

-  MY_MEMORYSTATUSEX stat;

-  stat.dwLength = sizeof(stat);

-  #endif

-  #ifdef _WIN64

-  if (!::GlobalMemoryStatusEx(&stat))

-    return 0;

-  return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

-  #else

-  #ifndef UNDER_CE

-  GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)

-      ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");

-  if (globalMemoryStatusEx != 0 && globalMemoryStatusEx(&stat))

-    return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

-  #endif

-  {

-    MEMORYSTATUS stat;

+    MY_MEMORYSTATUSEX stat;

     stat.dwLength = sizeof(stat);

-    ::GlobalMemoryStatus(&stat);

-    return MyMin(stat.dwTotalVirtual, stat.dwTotalPhys);

-  }

+  #endif

+  

+  #ifdef _WIN64

+    

+    if (!::GlobalMemoryStatusEx(&stat))

+      return false;

+    size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

+    return true;

+

+  #else

+    

+    #ifndef UNDER_CE

+      GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)

+          ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");

+      if (globalMemoryStatusEx && globalMemoryStatusEx(&stat))

+      {

+        size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

+        return true;

+      }

+    #endif

+  

+    {

+      MEMORYSTATUS stat2;

+      stat2.dwLength = sizeof(stat2);

+      ::GlobalMemoryStatus(&stat2);

+      size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys);

+      return true;

+    }

+  

+  #endif

+

+  #else

+

+  return false;

+

   #endif

 }

 

diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
index 78a5e1d..845362f 100644
--- a/CPP/Windows/System.h
+++ b/CPP/Windows/System.h
@@ -9,7 +9,8 @@
 namespace NSystem {

 

 UInt32 GetNumberOfProcessors();

-UInt64 GetRamSize();

+

+bool GetRamSize(UInt64 &size); // returns false, if unknown ram size

 

 }}

 

diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
index 0b1f11f..011d2f5 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.cpp b/CPP/Windows/Window.cpp
index 98b0630..0c74222 100644
--- a/CPP/Windows/Window.cpp
+++ b/CPP/Windows/Window.cpp
@@ -114,13 +114,18 @@
 bool CWindow::GetText(CSysString &s)

 {

   s.Empty();

-  int length = GetTextLength();

-  if (length == 0)

+  int len = GetTextLength();

+  if (len == 0)

     return (::GetLastError() == ERROR_SUCCESS);

-  length = GetText(s.GetBuffer(length), length + 1);

-  s.ReleaseBuffer();

-  if (length == 0)

-    return (::GetLastError() != ERROR_SUCCESS);

+  TCHAR *p = s.GetBuf(len);

+  {

+    int len2 = GetText(p, len + 1);

+    if (len > len2)

+      len = len2;

+  }

+  s.ReleaseBuf_CalcLen(len);

+  if (len == 0)

+    return (::GetLastError() == ERROR_SUCCESS);

   return true;

 }

 

@@ -130,18 +135,23 @@
   if (g_IsNT)

   {

     s.Empty();

-    int length = GetWindowTextLengthW(_window);

-    if (length == 0)

+    int len = GetWindowTextLengthW(_window);

+    if (len == 0)

       return (::GetLastError() == ERROR_SUCCESS);

-    length = GetWindowTextW(_window, s.GetBuffer(length), length + 1);

-    s.ReleaseBuffer();

-    if (length == 0)

+    wchar_t *p = s.GetBuf(len);

+    {

+      int len2 = GetWindowTextW(_window, p, len + 1);

+      if (len > len2)

+        len = len2;

+    }

+    s.ReleaseBuf_CalcLen(len);

+    if (len == 0)

       return (::GetLastError() == ERROR_SUCCESS);

     return true;

   }

   CSysString sysString;

   bool result = GetText(sysString);

-  s = GetUnicodeString(sysString);

+  MultiByteToUnicodeString2(s, sysString);

   return result;

 }

 #endif

diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h
index 3db239d..4c80a5b 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 @@
   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 @@
  

   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 @@
   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/Methods.txt b/DOC/Methods.txt
index a300d77..3ca9057 100644
--- a/DOC/Methods.txt
+++ b/DOC/Methods.txt
@@ -1,12 +1,17 @@
-7-Zip method IDs (9.24)

------------------------

+7-Zip method IDs for 7z and xz archives

+---------------------------------------

 

-Each compression or crypto method in 7z has unique binary value (ID).

+Version: 16.03

+Date: 2016-09-27

+

+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).

 

+xz and 7z formats use same ID map.

+

 If you want to add some new ID, you have two ways:

-1) Write request for allocating IDs to 7-zip developers.

-2) Generate 8-bytes ID:

+  1) Write request for allocating IDs to 7-Zip developers.

+  2) Generate 8-bytes ID:

 

     3F ZZ ZZ ZZ ZZ ZZ MM MM 

 

@@ -17,7 +22,7 @@
 

     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

@@ -26,87 +31,106 @@
 00 - Copy

 

 03 - Delta

-04 - x86 (BCJ)

-05 - PPC (Big Endian)

+04 - BCJ (x86)

+05 - PPC (big-endian)

 06 - IA64

-07 - ARM (little endian)

-08 - ARM Thumb (little endian)

+07 - ARM (little-endian)

+08 - ARMT (little-endian)

 09 - SPARC

+

 21 - LZMA2

           

 02.. - Common

-   03 Swap

+   03 [Swap]

       - 2 Swap2

       - 4 Swap4

 

 03.. - 7z

-   01 - LZMA

-      01 - Version

+   01 - 

+      01 - LZMA

   

-   03 - Branch

-      01 - x86

+   03 - [Branch Codecs]

+      01 - [x86 Codecs]

          03  - BCJ

-         1B  - BCJ2

-      02 - PPC

-         05 - PPC (Big Endian)

-      03 - Alpha

+         1B  - BCJ2 (4 packed streams)

+      02 - 

+         05 - PPC (big-endian)

+      03 - 

          01 - Alpha

-      04 - IA64

+      04 - 

          01 - IA64

-      05 - ARM

-         01 - ARM

-      06 - M68

-         05 - M68 (Big Endian)

-      07 - ARM Thumb

-         01 - ARMT

-      08 - SPARC

+      05 - 

+         01 - ARM (little-endian)

+      06 - 

+         05 - M68 (big-endian)

+      07 - 

+         01 - ARMT (little-endian)

+      08 - 

          05 - SPARC

 

-   04 - PPMD

-      01 - Version

+   04 - 

+      01 - PPMD

 

    7F -

-      01 - experimental methods.

+      01 - experimental method.

 

 

-04.. - Misc

+04.. - Misc codecs

+

    00 - Reserved

-   01 - Zip

-      00 - Copy (not used). Use {00} instead

+

+   01 - [Zip]

+      00 - Copy (not used. Use {00} instead)

       01 - Shrink

       06 - Implode

       08 - Deflate

       09 - Deflate64

-      10 - Imploding

-      12 - BZip2 (not used). Use {04 02 02} instead

-      14 - LZMA

+      0A - Imploding

+      0C - BZip2 (not used. Use {040202} instead)

+      0E - LZMA (LZMA-zip)

+      5F - xz

       60 - Jpeg

       61 - WavPack

-      62 - PPMd

+      62 - PPMd (PPMd-zip)

       63 - wzAES

-   02 - BZip

+

+   02 - 

       02 - BZip2

-   03 - Rar

-      01 - Rar15

-      02 - Rar20

-      03 - Rar29

-   04 - Arj

-      01 - Arj (1,2,3)

-      02 - Arj 4

-   05 - Z

-   06 - Lzh

+

+   03 - [Rar]

+      01 - Rar1

+      02 - Rar2

+      03 - Rar3

+      05 - Rar5

+

+   04 - [Arj]

+      01 - Arj(1,2,3)

+      02 - Arj4

+

+   05 - [Z]

+

+   06 - [Lzh]

+

    07 - Reserved for 7z

-   08 - Cab

-   09 - NSIS

+

+   08 - [Cab]

+

+   09 - [NSIS]

       01 - DeflateNSIS

       02 - BZip2NSIS

 

+   F7 - External codecs (that are not included to 7-Zip)

+

+      0x xx - reserved

+      10 xx - reserved (LZHAM)

+      11 xx - reserved (Zstd)

+

 

 06.. - Crypto 

 

    F0 - Ciphers without hashing algo

 

-      01 - AES

+      01 - [AES]

          0x - AES-128

          4x - AES-192

          8x - AES-256

@@ -119,13 +143,16 @@
          x4 - CTR

 

    F1 - Combine Ciphers

-      01 - Zip

-         01 - Main Zip crypto algo

-      03 - RAR

+

+      01 - [Zip]

+         01 - ZipCrypto (Main Zip crypto algo)

+

+      03 - [RAR]

          02 - 

-         03 - Rar29 AES-128 + (modified SHA-1)

-      07 - 7z

-         01 - AES-256 + SHA-256

+         03 - Rar29AES (AES-128 + modified SHA-1)

+

+      07 - [7z]

+         01 - 7zAES (AES-256 + SHA-256)

 

 

 ---

diff --git a/DOC/lzma-history.txt b/DOC/lzma-history.txt
index 6e98358..603a9e8 100644
--- a/DOC/lzma-history.txt
+++ b/DOC/lzma-history.txt
@@ -1,9 +1,66 @@
 HISTORY of the LZMA SDK

 -----------------------

 

+16.04          2016-10-04

+-------------------------

+- The bug was fixed in DllSecur.c.

+

+

+16.03          2016-09-28

+-------------------------

+- SFX modules now use some protection against DLL preloading attack.

+- Some bugs in 7z code were fixed.

+

+

+16.02          2016-05-21

+-------------------------

+- The BUG in 16.00 - 16.01 was fixed:

+  Split Handler (SplitHandler.cpp) returned incorrect 

+  total size value (kpidSize) for split archives.

+

+

+16.01          2016-05-19

+-------------------------	

+- Some internal changes to reduce the number of compiler warnings.

+

+

+16.00          2016-05-10

+-------------------------	

+- Some bugs were fixed.

+

+

+15.12          2015-11-19

+-------------------------	

+- The BUG in C version of 7z decoder was fixed:

+  7zDec.c : SzDecodeLzma2()

+  7z decoder could mistakenly report about decoding error for some 7z archives

+  that use LZMA2 compression method.

+  The probability to get that mistaken decoding error report was about 

+  one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). 

+- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:

+  7zArcIn.c : SzReadHeader2()

+  7z decoder worked incorrectly for 7z archives that contain 

+  empty solid blocks, that can be placed to 7z archive, if some file is 

+  unavailable for reading during archive creation.

+

+

+15.09 beta     2015-10-16

+-------------------------	

+- The BUG in LZMA / LZMA2 encoding code was fixed.

+  The BUG in LzFind.c::MatchFinder_ReadBlock() function.

+  If input data size is larger than (4 GiB - dictionary_size),

+  the following code worked incorrectly:

+  -  LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions 

+     for compressing from memory to memory. 

+     That BUG is not related to LZMA encoder version that works via streams.

+  -  LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if 

+     default value of chunk size (CLzma2EncProps::blockSize) is changed 

+     to value larger than (4 GiB - dictionary_size).

+

+

 9.38 beta      2015-01-03

 -------------------------	

-- The BUG in 9.30-9.37 was fixed:

+- The BUG in 9.31-9.37 was fixed:

   IArchiveGetRawProps interface was disabled for 7z archives.

 - The BUG in 9.26-9.36 was fixed:

   Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows.

diff --git a/DOC/lzma-sdk.txt b/DOC/lzma-sdk.txt
index 86923a4..86fef24 100644
--- a/DOC/lzma-sdk.txt
+++ b/DOC/lzma-sdk.txt
@@ -1,5 +1,5 @@
-LZMA SDK 9.38

--------------

+LZMA SDK 16.04

+--------------

 

 LZMA SDK provides the documentation, samples, header files,

 libraries, and tools you need to develop applications that 

@@ -33,8 +33,9 @@
   1) PPMd var.H (2001): Dmitry Shkarin

   2) SHA-256: Wei Dai (Crypto++ library)

 

-You can copy, modify, distribute and perform LZMA SDK code, even for commercial purposes,

-all without asking permission.

+Anyone is free to copy, modify, publish, use, compile, sell, or distribute the 

+original LZMA SDK code, either in source code form or as a compiled binary, for 

+any purpose, commercial or non-commercial, and by any means.

 

 LZMA SDK code is compatible with open source licenses, for example, you can 

 include it to GNU GPL or GNU LGPL code.

diff --git a/DOC/lzma-specification.txt b/DOC/lzma-specification.txt
index 2e3b874..b6796df 100644
--- a/DOC/lzma-specification.txt
+++ b/DOC/lzma-specification.txt
@@ -2,7 +2,7 @@
 ----------------------------------

 

 Author: Igor Pavlov

-Date: 2013-07-28

+Date: 2015-06-14

 

 This specification defines the format of LZMA compressed data and lzma file format.

 

@@ -352,25 +352,26 @@
 The Range Decoder reads first 5 bytes from input stream to initialize

 the state:

 

-void CRangeDecoder::Init()

+bool CRangeDecoder::Init()

 {

   Corrupted = false;

-  

-  if (InStream->ReadByte() != 0)

-    Corrupted = true;

-  

   Range = 0xFFFFFFFF;

   Code = 0;

+

+  Byte b = InStream->ReadByte();

+  

   for (int i = 0; i < 4; i++)

     Code = (Code << 8) | InStream->ReadByte();

   

-  if (Code == Range)

+  if (b != 0 || Code == Range)

     Corrupted = true;

+  return b == 0;

 }

 

 The LZMA Encoder always writes ZERO in initial byte of compressed stream.

 That scheme allows to simplify the code of the Range Encoder in the 

-LZMA Encoder.

+LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must

+stop decoding and report error.

 

 After the last bit of data was decoded by Range Decoder, the value of the

 "Code" variable must be equal to 0. The LZMA Decoder must check it by