Import org.tukaani
am: ad6cd04413

* commit 'ad6cd044139ae8376be94c0c486f3e3daedd8bd1':
  Import org.tukaani
diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm
old mode 100755
new mode 100644
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
old mode 100755
new mode 100644
index 5a5f271..53a9e3f
--- a/Asm/x86/7zAsm.asm
+++ b/Asm/x86/7zAsm.asm
@@ -1,5 +1,5 @@
 ; 7zAsm.asm -- ASM macros

-; 2009-12-12 : Igor Pavlov : Public domain

+; 2012-12-30 : Igor Pavlov : Public domain

 

 MY_ASM_START macro

   ifdef x64

@@ -13,30 +13,34 @@
 

 MY_PROC macro name:req, numParams:req

   align 16

-  proc_numParams equ numParams

+  proc_numParams = numParams

   ifdef x64

     proc_name equ name

-    name PROC

   else

-    proc_fastcall_name equ @CatStr(@,name,@, %numParams * 4)

-    public proc_fastcall_name

-    proc_fastcall_name:

+    proc_name equ @CatStr(@,name,@, %numParams * 4)

   endif

+  proc_name PROC

 endm

 

 MY_ENDP macro

   ifdef x64

     ret

-    proc_name ENDP

   else

-    ret (proc_numParams - 2) * 4

+    if proc_numParams LT 3

+      ret

+    else

+      ret (proc_numParams - 2) * 4

+    endif

   endif

+  proc_name ENDP

 endm

 

 ifdef x64

   REG_SIZE equ 8

+  REG_LOGAR_SIZE equ 3

 else

   REG_SIZE equ 4

+  REG_LOGAR_SIZE equ 2

 endif

 

   x0 equ EAX

@@ -67,6 +71,14 @@
   r5 equ RBP

   r6 equ RSI

   r7 equ RDI

+  x8 equ r8d

+  x9 equ r9d

+  x10 equ r10d

+  x11 equ r11d

+  x12 equ r12d

+  x13 equ r13d

+  x14 equ r14d

+  x15 equ r15d

 else

   r0 equ x0

   r1 equ x1

diff --git a/Asm/x86/7zCrcOpt.asm b/Asm/x86/7zCrcOpt.asm
old mode 100755
new mode 100644
diff --git a/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm
old mode 100755
new mode 100644
diff --git a/Asm/x86/XzCrc64Opt.asm b/Asm/x86/XzCrc64Opt.asm
new file mode 100644
index 0000000..3e6d490
--- /dev/null
+++ b/Asm/x86/XzCrc64Opt.asm
@@ -0,0 +1,205 @@
+; XzCrc64Opt.asm -- CRC64 calculation : optimized version

+; 2011-06-28 : Igor Pavlov : Public domain

+

+include 7zAsm.asm

+

+MY_ASM_START

+

+ifdef x64

+

+    rD   equ  r9

+    rN   equ  r10

+

+    num_VAR     equ  r8

+    table_VAR   equ  r9

+

+    SRCDAT  equ  rN + rD

+

+CRC_XOR macro dest:req, src:req, t:req

+    xor     dest, QWORD PTR [r5 + src * 8 + 0800h * t]

+endm

+

+CRC1b macro

+    movzx   x6, BYTE PTR [rD]

+    inc     rD

+    movzx   x3, x0_L

+    xor     x6, x3

+    shr     r0, 8

+    CRC_XOR r0, r6, 0

+    dec     rN

+endm

+

+MY_PROLOG macro crc_end:req

+    MY_PUSH_4_REGS

+    

+    mov     r0, r1

+    mov     rN, num_VAR

+    mov     r5, table_VAR

+    mov     rD, r2

+    test    rN, rN

+    jz      crc_end

+  @@:

+    test    rD, 3

+    jz      @F

+    CRC1b

+    jnz     @B

+  @@:

+    cmp     rN, 8

+    jb      crc_end

+    add     rN, rD

+    mov     num_VAR, rN

+    sub     rN, 4

+    and     rN, NOT 3

+    sub     rD, rN

+    mov     x1, [SRCDAT]

+    xor     r0, r1

+    add     rN, 4

+endm

+

+MY_EPILOG macro crc_end:req

+    sub     rN, 4

+    mov     x1, [SRCDAT]

+    xor     r0, r1

+    mov     rD, rN

+    mov     rN, num_VAR

+    sub     rN, rD

+  crc_end:

+    test    rN, rN

+    jz      @F

+    CRC1b

+    jmp     crc_end

+  @@:

+    MY_POP_4_REGS

+endm

+

+MY_PROC XzCrc64UpdateT4, 4

+    MY_PROLOG crc_end_4

+    align 16

+  main_loop_4:

+    mov     x1, [SRCDAT]

+    movzx   x2, x0_L

+    movzx   x3, x0_H

+    shr     r0, 16

+    movzx   x6, x0_L

+    movzx   x7, x0_H

+    shr     r0, 16

+    CRC_XOR r1, r2, 3

+    CRC_XOR r0, r3, 2

+    CRC_XOR r1, r6, 1

+    CRC_XOR r0, r7, 0

+    xor     r0, r1

+

+    add     rD, 4

+    jnz     main_loop_4

+

+    MY_EPILOG crc_end_4

+MY_ENDP

+

+else

+

+    rD   equ  r1

+    rN   equ  r7

+

+    crc_val     equ (REG_SIZE * 5)

+    crc_table   equ (8 + crc_val)

+    table_VAR   equ [r4 + crc_table]

+    num_VAR     equ table_VAR

+

+

+    SRCDAT  equ  rN + rD

+

+CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req

+    op0     dest0, DWORD PTR [r5 + src * 8 + 0800h * t]

+    op1     dest1, DWORD PTR [r5 + src * 8 + 0800h * t + 4]

+endm

+

+CRC_XOR macro dest0:req, dest1:req, src:req, t:req

+    CRC xor, xor, dest0, dest1, src, t

+endm

+

+

+CRC1b macro

+    movzx   x6, BYTE PTR [rD]

+    inc     rD

+    movzx   x3, x0_L

+    xor     x6, x3

+    shrd    r0, r2, 8

+    shr     r2, 8

+    CRC_XOR r0, r2, r6, 0

+    dec     rN

+endm

+

+MY_PROLOG macro crc_end:req

+    MY_PUSH_4_REGS

+    

+    mov     rN, r2

+

+    mov     x0, [r4 + crc_val]

+    mov     x2, [r4 + crc_val + 4]

+    mov     r5, table_VAR

+    test    rN, rN

+    jz      crc_end

+  @@:

+    test    rD, 3

+    jz      @F

+    CRC1b

+    jnz     @B

+  @@:

+    cmp     rN, 8

+    jb      crc_end

+    add     rN, rD

+

+    mov     num_VAR, rN

+

+    sub     rN, 4

+    and     rN, NOT 3

+    sub     rD, rN

+    xor     r0, [SRCDAT]

+    add     rN, 4

+endm

+

+MY_EPILOG macro crc_end:req

+    sub     rN, 4

+    xor     r0, [SRCDAT]

+

+    mov     rD, rN

+    mov     rN, num_VAR

+    sub     rN, rD

+  crc_end:

+    test    rN, rN

+    jz      @F

+    CRC1b

+    jmp     crc_end

+  @@:

+    MY_POP_4_REGS

+endm

+

+MY_PROC XzCrc64UpdateT4, 5

+    MY_PROLOG crc_end_4

+    movzx   x6, x0_L

+    align 16

+  main_loop_4:

+    mov     r3, [SRCDAT]

+    xor     r3, r2

+

+    CRC xor, mov, r3, r2, r6, 3

+    movzx   x6, x0_H

+    shr     r0, 16

+    CRC_XOR r3, r2, r6, 2

+

+    movzx   x6, x0_L

+    movzx   x0, x0_H

+    CRC_XOR r3, r2, r6, 1

+    CRC_XOR r3, r2, r0, 0

+    movzx   x6, x3_L

+    mov     r0, r3

+

+    add     rD, 4

+    jnz     main_loop_4

+

+    MY_EPILOG crc_end_4

+MY_ENDP

+

+endif

+

+end

diff --git a/C/7z.h b/C/7z.h
old mode 100755
new mode 100644
index b7edd3b..dc25f53
--- a/C/7z.h
+++ b/C/7z.h
@@ -1,58 +1,34 @@
 /* 7z.h -- 7z interface

-2010-03-11 : Igor Pavlov : Public domain */

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

 

 #ifndef __7Z_H

 #define __7Z_H

 

-#include "7zBuf.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

 #define k7zStartHeaderSize 0x20

 #define k7zSignatureSize 6

-extern Byte k7zSignature[k7zSignatureSize];

-#define k7zMajorVersion 0

 

-enum EIdEnum

-{

-  k7zIdEnd,

-  k7zIdHeader,

-  k7zIdArchiveProperties,

-  k7zIdAdditionalStreamsInfo,

-  k7zIdMainStreamsInfo,

-  k7zIdFilesInfo,

-  k7zIdPackInfo,

-  k7zIdUnpackInfo,

-  k7zIdSubStreamsInfo,

-  k7zIdSize,

-  k7zIdCRC,

-  k7zIdFolder,

-  k7zIdCodersUnpackSize,

-  k7zIdNumUnpackStream,

-  k7zIdEmptyStream,

-  k7zIdEmptyFile,

-  k7zIdAnti,

-  k7zIdName,

-  k7zIdCTime,

-  k7zIdATime,

-  k7zIdMTime,

-  k7zIdWinAttributes,

-  k7zIdComment,

-  k7zIdEncodedHeader,

-  k7zIdStartPos,

-  k7zIdDummy

-};

+extern Byte k7zSignature[k7zSignatureSize];

 

 typedef struct

 {

-  UInt32 NumInStreams;

-  UInt32 NumOutStreams;

-  UInt64 MethodID;

-  CBuf Props;

-} CSzCoderInfo;

+  const Byte *Data;

+  size_t Size;

+} CSzData;

 

-void SzCoderInfo_Init(CSzCoderInfo *p);

-void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);

+/* CSzCoderInfo & CSzFolder support only default methods */

+

+typedef struct

+{

+  size_t PropsOffset;

+  UInt32 MethodID;

+  Byte NumInStreams;

+  Byte NumOutStreams;

+  Byte PropsSize;

+} CSzCoderInfo;

 

 typedef struct

 {

@@ -60,30 +36,35 @@
   UInt32 OutIndex;

 } CSzBindPair;

 

+#define SZ_NUM_CODERS_IN_FOLDER_MAX 4

+#define SZ_NUM_BINDS_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

 {

-  CSzCoderInfo *Coders;

-  CSzBindPair *BindPairs;

-  UInt32 *PackStreams;

-  UInt64 *UnpackSizes;

   UInt32 NumCoders;

   UInt32 NumBindPairs;

   UInt32 NumPackStreams;

-  int UnpackCRCDefined;

-  UInt32 UnpackCRC;

-

-  UInt32 NumUnpackStreams;

+  UInt32 MainOutStream;

+  UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];

+  CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX];

+  CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];

+  UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];

 } CSzFolder;

 

-void SzFolder_Init(CSzFolder *p);

-UInt64 SzFolder_GetUnpackSize(CSzFolder *p);

-int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);

-UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);

-UInt64 SzFolder_GetUnpackSize(CSzFolder *p);

+/*

+typedef struct

+{

+  size_t CodersDataOffset;

+  size_t UnpackSizeDataOffset;

+  // UInt32 StartCoderUnpackSizesIndex;

+  UInt32 StartPackStreamIndex;

+  // UInt32 IndexOfMainOutStream;

+} CSzFolder2;

+*/

 

-SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,

-    ILookInStream *stream, UInt64 startPos,

-    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);

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

 

 typedef struct

 {

@@ -93,35 +74,46 @@
 

 typedef struct

 {

-  CNtfsFileTime MTime;

-  UInt64 Size;

-  UInt32 Crc;

-  UInt32 Attrib;

-  Byte HasStream;

-  Byte IsDir;

-  Byte IsAnti;

-  Byte CrcDefined;

-  Byte MTimeDefined;

-  Byte AttribDefined;

-} CSzFileItem;

-

-void SzFile_Init(CSzFileItem *p);

+  Byte *Defs; /* MSB 0 bit numbering */

+  UInt32 *Vals;

+} CSzBitUi32s;

 

 typedef struct

 {

-  UInt64 *PackSizes;

-  Byte *PackCRCsDefined;

-  UInt32 *PackCRCs;

-  CSzFolder *Folders;

-  CSzFileItem *Files;

+  Byte *Defs; /* MSB 0 bit numbering */

+  // UInt64 *Vals;

+  CNtfsFileTime *Vals;

+} CSzBitUi64s;

+

+#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)

+

+#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)

+

+typedef struct

+{

   UInt32 NumPackStreams;

   UInt32 NumFolders;

-  UInt32 NumFiles;

+

+  UInt64 *PackPositions; // NumPackStreams + 1

+  CSzBitUi32s FolderCRCs;

+

+  size_t *FoCodersOffsets;

+  size_t *FoSizesOffsets;

+  // UInt32 StartCoderUnpackSizesIndex;

+  UInt32 *FoStartPackStreamIndex;

+

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

+  Byte *CodersData;

+  Byte *UnpackSizesData;

+  size_t UnpackSizesDataSize;

+  // UInt64 *CoderUnpackSizes;

 } CSzAr;

 

-void SzAr_Init(CSzAr *p);

-void SzAr_Free(CSzAr *p, ISzAlloc *alloc);

 

+SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

+    ILookInStream *stream, UInt64 startPos,

+    Byte *outBuffer, size_t outSize,

+    ISzAlloc *allocMain);

 

 /*

   SzExtract extracts file from archive

@@ -146,19 +138,34 @@
 typedef struct

 {

   CSzAr db;

-  

+

   UInt64 startPosAfterHeader;

   UInt64 dataPos;

+  

+  UInt32 NumFiles;

 

-  UInt32 *FolderStartPackStreamIndex;

-  UInt64 *PackStreamStartPositions;

-  UInt32 *FolderStartFileIndex;

+  UInt64 *UnpackPositions;

+  // Byte *IsEmptyFiles;

+  Byte *IsDirs;

+  CSzBitUi32s CRCs;

+

+  CSzBitUi32s Attribs;

+  // CSzBitUi32s Parents;

+  CSzBitUi64s MTime;

+  CSzBitUi64s CTime;

+

+  // UInt32 *FolderStartPackStreamIndex;

+  UInt32 *FolderStartFileIndex; // + 1

   UInt32 *FileIndexToFolderIndexMap;

 

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

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

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

 } CSzArEx;

 

+#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))

+

+#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])

+

 void SzArEx_Init(CSzArEx *p);

 void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);

 UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);

@@ -172,6 +179,11 @@
 

 size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);

 

+/*

+size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);

+UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);

+*/

+

 SRes SzArEx_Extract(

     const CSzArEx *db,

     ILookInStream *inStream,

@@ -196,7 +208,8 @@
 SZ_ERROR_FAIL

 */

 

-SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);

+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,

+    ISzAlloc *allocMain, ISzAlloc *allocTemp);

 

 EXTERN_C_END

 

diff --git a/C/7zAlloc.c b/C/7zAlloc.c
old mode 100755
new mode 100644
index 8874496..698071c
--- a/C/7zAlloc.c
+++ b/C/7zAlloc.c
@@ -1,6 +1,8 @@
 /* 7zAlloc.c -- Allocation functions

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

 

+#include "Precomp.h"

+

 #include "7zAlloc.h"

 

 /* #define _SZ_ALLOC_DEBUG */

diff --git a/C/7zAlloc.h b/C/7zAlloc.h
old mode 100755
new mode 100644
diff --git a/C/7zArcIn.c b/C/7zArcIn.c
new file mode 100644
index 0000000..5fd4f6b
--- /dev/null
+++ b/C/7zArcIn.c
@@ -0,0 +1,1839 @@
+/* 7zArcIn.c -- 7z Input functions

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

+

+#include "Precomp.h"

+

+#include <string.h>

+

+#include "7z.h"

+#include "7zBuf.h"

+#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 k7zMajorVersion 0

+

+enum EIdEnum

+{

+  k7zIdEnd,

+  k7zIdHeader,

+  k7zIdArchiveProperties,

+  k7zIdAdditionalStreamsInfo,

+  k7zIdMainStreamsInfo,

+  k7zIdFilesInfo,

+  k7zIdPackInfo,

+  k7zIdUnpackInfo,

+  k7zIdSubStreamsInfo,

+  k7zIdSize,

+  k7zIdCRC,

+  k7zIdFolder,

+  k7zIdCodersUnpackSize,

+  k7zIdNumUnpackStream,

+  k7zIdEmptyStream,

+  k7zIdEmptyFile,

+  k7zIdAnti,

+  k7zIdName,

+  k7zIdCTime,

+  k7zIdATime,

+  k7zIdMTime,

+  k7zIdWinAttrib,

+  k7zIdComment,

+  k7zIdEncodedHeader,

+  k7zIdStartPos,

+  k7zIdDummy

+  // k7zNtSecure,

+  // k7zParent,

+  // k7zIsReal

+};

+

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

+

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

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

+}

+

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

+

+void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)

+{

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

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

+}

+

+static void SzAr_Init(CSzAr *p)

+{

+  p->NumPackStreams = 0;

+  p->NumFolders = 0;

+  p->PackPositions = 0;

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

+}

+

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

+

+  SzAr_Init(p);

+}

+

+

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

+  SzBitUi32s_Init(&p->CRCs);

+  SzBitUi32s_Init(&p->Attribs);

+  // SzBitUi32s_Init(&p->Parents);

+  SzBitUi64s_Init(&p->MTime);

+  SzBitUi64s_Init(&p->CTime);

+}

+

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

+

+  SzAr_Free(&p->db, alloc);

+  SzArEx_Init(p);

+}

+

+static int TestSignatureCandidate(Byte *testBytes)

+{

+  size_t 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 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)

+#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++;

+

+#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }

+#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }

+

+#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \

+   dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);

+

+static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)

+{

+  Byte firstByte, mask;

+  unsigned i;

+  UInt32 v;

+

+  SZ_READ_BYTE(firstByte);

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

+  {

+    *value = firstByte;

+    return SZ_OK;

+  }

+  SZ_READ_BYTE(v);

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

+  {

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

+    return SZ_OK;

+  }

+  SZ_READ_BYTE(mask);

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

+  mask = 0x20;

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

+  {

+    Byte b;

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

+    {

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

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

+      return SZ_OK;

+    }

+    SZ_READ_BYTE(b);

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

+    mask >>= 1;

+  }

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

+{

+  Byte firstByte;

+  UInt64 value64;

+  if (sd->Size == 0)

+    return SZ_ERROR_ARCHIVE;

+  firstByte = *sd->Data;

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

+  {

+    *value = firstByte;

+    sd->Data++;

+    sd->Size--;

+    return SZ_OK;

+  }

+  RINOK(ReadNumber(sd, &value64));

+  if (value64 >= (UInt32)0x80000000 - 1)

+    return SZ_ERROR_UNSUPPORTED;

+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4)))

+    return SZ_ERROR_UNSUPPORTED;

+  *value = (UInt32)value64;

+  return SZ_OK;

+}

+

+#define ReadID(sd, value) ReadNumber(sd, value)

+

+static SRes SkipData(CSzData *sd)

+{

+  UInt64 size;

+  RINOK(ReadNumber(sd, &size));

+  if (size > sd->Size)

+    return SZ_ERROR_ARCHIVE;

+  SKIP_DATA(sd, size);

+  return SZ_OK;

+}

+

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

+{

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == id)

+      return SZ_OK;

+    if (type == k7zIdEnd)

+      return SZ_ERROR_ARCHIVE;

+    RINOK(SkipData(sd));

+  }

+}

+

+static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)

+{

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

+  if (numBytes > sd->Size)

+    return SZ_ERROR_ARCHIVE;

+  *v = sd->Data;

+  SKIP_DATA(sd, numBytes);

+  return SZ_OK;

+}

+

+static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)

+{

+  Byte b = 0;

+  unsigned m = 0;

+  UInt32 sum = 0;

+  for (; numItems != 0; numItems--)

+  {

+    if (m == 0)

+    {

+      b = *bits++;

+      m = 8;

+    }

+    m--;

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

+  }

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

+  if (allAreDefined == 0)

+  {

+    if (numBytes > sd->Size)

+      return SZ_ERROR_ARCHIVE;

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

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

+    SKIP_DATA(sd, numBytes);

+    return SZ_OK;

+  }

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

+  v2 = *v;

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

+    v2[i] = 0xFF;

+  {

+    unsigned numBits = (unsigned)numItems & 7;

+    if (numBits != 0)

+      v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));

+  }

+  return SZ_OK;

+}

+

+static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)

+{

+  UInt32 i;

+  CSzData sd;

+  UInt32 *vals;

+  const Byte *defs;

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

+  sd = *sd2;

+  defs = crcs->Defs;

+  vals = crcs->Vals;

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

+    if (SzBitArray_Check(defs, i))

+    {

+      SZ_READ_32(vals[i]);

+    }

+    else

+      vals[i] = 0;

+  *sd2 = sd;

+  return SZ_OK;

+}

+

+static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)

+{

+  SzBitUi32s_Free(crcs, alloc);

+  RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));

+  return ReadUi32s(sd, numItems, crcs, alloc);

+}

+

+static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)

+{

+  Byte allAreDefined;

+  UInt32 numDefined = numItems;

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

+  if (!allAreDefined)

+  {

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

+    if (numBytes > sd->Size)

+      return SZ_ERROR_ARCHIVE;

+    numDefined = CountDefinedBits(sd->Data, numItems);

+    SKIP_DATA(sd, numBytes);

+  }

+  if (numDefined > (sd->Size >> 2))

+    return SZ_ERROR_ARCHIVE;

+  SKIP_DATA(sd, (size_t)numDefined * 4);

+  return SZ_OK;

+}

+

+static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc)

+{

+  RINOK(SzReadNumber32(sd, &p->NumPackStreams));

+

+  RINOK(WaitId(sd, k7zIdSize));

+  MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc);

+  {

+    UInt64 sum = 0;

+    UInt32 i;

+    UInt32 numPackStreams = p->NumPackStreams;

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

+    {

+      UInt64 packSize;

+      p->PackPositions[i] = sum;

+      RINOK(ReadNumber(sd, &packSize));

+      sum += packSize;

+      if (sum < packSize)

+        return SZ_ERROR_ARCHIVE;

+    }

+    p->PackPositions[i] = sum;

+  }

+

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+      return SZ_OK;

+    if (type == k7zIdCRC)

+    {

+      /* CRC of packed streams is unused now */

+      RINOK(SkipBitUi32s(sd, p->NumPackStreams));

+      continue;

+    }

+    RINOK(SkipData(sd));

+  }

+}

+

+/*

+static SRes SzReadSwitch(CSzData *sd)

+{

+  Byte external;

+  RINOK(SzReadByte(sd, &external));

+  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;

+}

+*/

+

+#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16

+

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

+{

+  UInt32 numCoders, numBindPairs, numPackStreams, i;

+  UInt32 numInStreams = 0, numOutStreams = 0;

+  const Byte *dataStart = sd->Data;

+  Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX];

+  

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

+  if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)

+    return SZ_ERROR_UNSUPPORTED;

+  f->NumCoders = numCoders;

+  

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

+  {

+    Byte mainByte;

+    CSzCoderInfo *coder = f->Coders + i;

+    unsigned idSize, j;

+    UInt64 id;

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

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

+      return SZ_ERROR_UNSUPPORTED;

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

+    if (idSize > sizeof(id))

+      return SZ_ERROR_UNSUPPORTED;

+    if (idSize > sd->Size)

+      return SZ_ERROR_ARCHIVE;

+    id = 0;

+    for (j = 0; j < idSize; j++)

+    {

+      id = ((id << 8) | *sd->Data);

+      sd->Data++;

+      sd->Size--;

+    }

+    if (id > (UInt32)0xFFFFFFFF)

+      return SZ_ERROR_UNSUPPORTED;

+    coder->MethodID = (UInt32)id;

+    

+    coder->NumInStreams = 1;

+    coder->NumOutStreams = 1;

+    coder->PropsOffset = 0;

+    coder->PropsSize = 0;

+    

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

+    {

+      UInt32 numStreams;

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

+      if (numStreams > NUM_CODER_STREAMS_MAX)

+        return SZ_ERROR_UNSUPPORTED;

+      coder->NumInStreams = (Byte)numStreams;

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

+      if (numStreams > NUM_CODER_STREAMS_MAX)

+        return SZ_ERROR_UNSUPPORTED;

+      coder->NumOutStreams = (Byte)numStreams;

+    }

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

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

+  {

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

+  }

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

+  }

+  

+  return SZ_OK;

+}

+

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

+{

+  CSzData sd;

+  sd = *sd2;

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

+  {

+    Byte firstByte, mask;

+    unsigned i;

+    SZ_READ_BYTE_2(firstByte);

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

+      continue;

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

+    {

+      if (sd.Size == 0)

+        return SZ_ERROR_ARCHIVE;

+      sd.Size--;

+      sd.Data++;

+      continue;

+    }

+    mask = 0x20;

+    for (i = 2; i < 8 && (firstByte & mask) != 0; i++)

+      mask >>= 1;

+    if (i > sd.Size)

+      return SZ_ERROR_ARCHIVE;

+    SKIP_DATA2(sd, i);

+  }

+  *sd2 = sd;

+  return SZ_OK;

+}

+

+#define k_InStreamUsed_MAX 64

+#define k_OutStreamUsed_MAX 64

+

+static SRes ReadUnpackInfo(CSzAr *p,

+    CSzData *sd2,

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

+    return SZ_ERROR_UNSUPPORTED;

+  p->NumFolders = numFolders;

+

+  SZ_READ_BYTE_SD(sd2, external);

+  if (external == 0)

+    sd = *sd2;

+  else

+  {

+    UInt32 index;

+    SzReadNumber32(sd2, &index);

+    if (index >= numTempBufs)

+      return SZ_ERROR_ARCHIVE;

+    sd.Data = tempBufs[index].data;

+    sd.Size = tempBufs[index].size;

+  }

+  

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

+  

+  startBufPtr = sd.Data;

+  

+  packStreamIndex = 0;

+  numCodersOutStreams = 0;

+

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

+  {

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

+    

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

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

+    if (numCoders > NUM_FOLDER_CODERS_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+    

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

+    {

+      Byte mainByte;

+      unsigned idSize;

+      UInt32 coderInStreams, coderOutStreams;

+      

+      SZ_READ_BYTE_2(mainByte);

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

+        return SZ_ERROR_UNSUPPORTED;

+      idSize = (mainByte & 0xF);

+      if (idSize > 8)

+        return SZ_ERROR_UNSUPPORTED;

+      if (idSize > sd.Size)

+        return SZ_ERROR_ARCHIVE;

+      SKIP_DATA2(sd, idSize);

+      

+      coderInStreams = 1;

+      coderOutStreams = 1;

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

+      {

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

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

+        if (coderInStreams > NUM_CODER_STREAMS_MAX ||

+            coderOutStreams > NUM_CODER_STREAMS_MAX)

+          return SZ_ERROR_UNSUPPORTED;

+      }

+      numInStreams += coderInStreams;

+      numOutStreams += coderOutStreams;

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

+      {

+        UInt32 propsSize;

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

+        if (propsSize > sd.Size)

+          return SZ_ERROR_ARCHIVE;

+        SKIP_DATA2(sd, propsSize);

+      }

+    }

+    

+    {

+      UInt32 indexOfMainStream = 0;

+      UInt32 numPackStreams = 1;

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

+      {

+        UInt32 i;

+        UInt32 numBindPairs = numOutStreams - 1;

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

+          return SZ_ERROR_ARCHIVE;

+        

+        if (numInStreams > k_InStreamUsed_MAX ||

+            numOutStreams > k_OutStreamUsed_MAX)

+          return SZ_ERROR_UNSUPPORTED;

+        

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

+          inStreamUsed[i] = False;

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

+          outStreamUsed[i] = False;

+        

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

+        {

+          UInt32 index;

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

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

+            return SZ_ERROR_ARCHIVE;

+          inStreamUsed[index] = True;

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

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

+            return SZ_ERROR_ARCHIVE;

+          outStreamUsed[index] = True;

+        }

+        

+        numPackStreams = numInStreams - numBindPairs;

+        

+        if (numPackStreams != 1)

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

+          {

+            UInt32 temp;

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

+            if (temp >= numInStreams)

+              return SZ_ERROR_ARCHIVE;

+          }

+          

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

+          if (!outStreamUsed[i])

+          {

+            indexOfMainStream = i;

+            break;

+          }

+ 

+        if (i == numOutStreams)

+          return SZ_ERROR_ARCHIVE;

+      }

+      p->FoStartPackStreamIndex[fo] = packStreamIndex;

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

+      numCodersOutStreams += numOutStreams;

+      if (numCodersOutStreams < numOutStreams)

+        return SZ_ERROR_UNSUPPORTED;

+      packStreamIndex += numPackStreams;

+      if (packStreamIndex < numPackStreams)

+        return SZ_ERROR_UNSUPPORTED;

+      if (packStreamIndex > p->NumPackStreams)

+        return SZ_ERROR_ARCHIVE;

+    }

+  }

+  

+  {

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

+  }

+  

+  if (external != 0)

+  {

+    if (sd.Size != 0)

+      return SZ_ERROR_ARCHIVE;

+    sd = *sd2;

+  }

+  

+  RINOK(WaitId(&sd, k7zIdCodersUnpackSize));

+  

+  // MY_ALLOC(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(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 (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+    {

+      *sd2 = sd;

+      return SZ_OK;

+    }

+    if (type == k7zIdCRC)

+    {

+      RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));

+      continue;

+    }

+    RINOK(SkipData(&sd));

+  }

+}

+

+typedef struct

+{

+  UInt32 NumTotalSubStreams;

+  UInt32 NumSubDigests;

+  CSzData sdNumSubStreams;

+  CSzData sdSizes;

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

+  UInt32 numUnpackSizesInData = 0;

+

+  for (;;)

+  {

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

+    if (type == k7zIdNumUnpackStream)

+    {

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

+      numUnpackStreams = 0;

+      numSubDigests = 0;

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

+      {

+        UInt32 numStreams;

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

+        if (numUnpackStreams > numUnpackStreams + numStreams)

+          return SZ_ERROR_UNSUPPORTED;

+        numUnpackStreams += numStreams;

+        if (numStreams != 0)

+          numUnpackSizesInData += (numStreams - 1);

+        if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))

+          numSubDigests += numStreams;

+      }

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

+      continue;

+    }

+    if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)

+      break;

+    RINOK(SkipData(sd));

+  }

+

+  if (!ssi->sdNumSubStreams.Data)

+  {

+    numSubDigests = numFolders;

+    if (p->FolderCRCs.Defs)

+      numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);

+  }

+  

+  ssi->NumTotalSubStreams = numUnpackStreams;

+  ssi->NumSubDigests = numSubDigests;

+

+  if (type == k7zIdSize)

+  {

+    ssi->sdSizes.Data = sd->Data;

+    RINOK(SkipNumbers(sd, numUnpackSizesInData));

+    ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;

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

+  }

+

+  for (;;)

+  {

+    if (type == k7zIdEnd)

+      return SZ_OK;

+    if (type == k7zIdCRC)

+    {

+      ssi->sdCRCs.Data = sd->Data;

+      RINOK(SkipBitUi32s(sd, numSubDigests));

+      ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;

+    }

+    else

+    {

+      RINOK(SkipData(sd));

+    }

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

+  }

+}

+

+static SRes SzReadStreamsInfo(CSzAr *p,

+    CSzData *sd,

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

+    UInt64 *dataOffset,

+    CSubStreamInfo *ssi,

+    ISzAlloc *alloc)

+{

+  UInt64 type;

+

+  SzData_Clear(&ssi->sdSizes);

+  SzData_Clear(&ssi->sdCRCs);

+  SzData_Clear(&ssi->sdNumSubStreams);

+

+  *dataOffset = 0;

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

+  if (type == k7zIdPackInfo)

+  {

+    RINOK(ReadNumber(sd, dataOffset));

+    RINOK(ReadPackInfo(p, sd, alloc));

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

+  }

+  if (type == k7zIdUnpackInfo)

+  {

+    RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));

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

+  }

+  if (type == k7zIdSubStreamsInfo)

+  {

+    RINOK(ReadSubStreamsInfo(p, sd, ssi));

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

+  }

+  else

+  {

+    ssi->NumTotalSubStreams = p->NumFolders;

+    // ssi->NumSubDigests = 0;

+  }

+

+  return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);

+}

+

+static SRes SzReadAndDecodePackedStreams(

+    ILookInStream *inStream,

+    CSzData *sd,

+    CBuf *tempBufs,

+    UInt32 numFoldersMax,

+    UInt64 baseOffset,

+    CSzAr *p,

+    ISzAlloc *allocTemp)

+{

+  UInt64 dataStartPos;

+  UInt32 fo;

+  CSubStreamInfo ssi;

+  CSzData sdCodersUnpSizes;

+

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

+  

+  dataStartPos += baseOffset;

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

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

+}

+

+static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)

+{

+  size_t pos = 0;

+  *offsets++ = 0;

+  if (numFiles == 0)

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

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

+    return SZ_ERROR_ARCHIVE;

+  do

+  {

+    const Byte *p;

+    if (pos == size)

+      return SZ_ERROR_ARCHIVE;

+    for (p = data + pos;

+      #ifdef _WIN32

+      *(const UInt16 *)p != 0

+      #else

+      p[0] != 0 || p[1] != 0

+      #endif

+      ; p += 2);

+    pos = p - data + 2;

+    *offsets++ = (pos >> 1);

+  }

+  while (--numFiles);

+  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;

+}

+

+static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,

+    CSzData *sd2,

+    const CBuf *tempBufs, UInt32 numTempBufs,

+    ISzAlloc *alloc)

+{

+  CSzData sd;

+  UInt32 i;

+  CNtfsFileTime *vals;

+  Byte *defs;

+  Byte external;

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

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

+  if (external == 0)

+    sd = *sd2;

+  else

+  {

+    UInt32 index;

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

+  vals = p->Vals;

+  defs = p->Defs;

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

+    if (SzBitArray_Check(defs, i))

+    {

+      if (sd.Size < 8)

+        return SZ_ERROR_ARCHIVE;

+      vals[i].Low = GetUi32(sd.Data);

+      vals[i].High = GetUi32(sd.Data + 4);

+      SKIP_DATA2(sd, 8);

+    }

+    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,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp

+    )

+{

+  UInt64 type;

+  UInt32 numFiles = 0;

+  UInt32 numEmptyStreams = 0;

+  UInt32 i;

+  CSubStreamInfo ssi;

+  const Byte *emptyStreams = 0;

+  const Byte *emptyFiles = 0;

+

+  SzData_Clear(&ssi.sdSizes);

+  SzData_Clear(&ssi.sdCRCs);

+  SzData_Clear(&ssi.sdNumSubStreams);

+

+  ssi.NumSubDigests = 0;

+  ssi.NumTotalSubStreams = 0;

+

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

+

+  if (type == k7zIdArchiveProperties)

+  {

+    for (;;)

+    {

+      UInt64 type;

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

+      if (type == 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;

+    SzAr_Free(&tempAr, allocTemp);

+    if (res != SZ_OK)

+      return res;

+    *numTempBufs = numTempFolders;

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

+  }

+

+  if (type == k7zIdMainStreamsInfo)

+  {

+    RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,

+        &p->dataPos, &ssi, allocMain));

+    p->dataPos += p->startPosAfterHeader;

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

+  }

+

+  if (type == k7zIdEnd)

+  {

+    // *sd2 = sd;

+    return SZ_OK;

+  }

+  if (type != k7zIdFilesInfo)

+    return SZ_ERROR_ARCHIVE;

+  

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

+  p->NumFiles = numFiles;

+

+  for (;;)

+  {

+    UInt64 type;

+    UInt64 size;

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

+    if (type == k7zIdEnd)

+      break;

+    RINOK(ReadNumber(sd, &size));

+    if (size > sd->Size)

+      return SZ_ERROR_ARCHIVE;

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

+    {

+      SKIP_DATA(sd, size);

+    }

+    else switch((int)type)

+    {

+      case k7zIdName:

+      {

+        size_t namesSize;

+        const Byte *namesData;

+        Byte external;

+

+        SZ_READ_BYTE(external);

+        if (external == 0)

+        {

+          namesSize = (size_t)size - 1;

+          namesData = sd->Data;

+        }

+        else

+        {

+          UInt32 index;

+          SzReadNumber32(sd, &index);

+          if (index >= *numTempBufs)

+            return SZ_ERROR_ARCHIVE;

+          namesData = (tempBufs)[index].data;

+          namesSize = (tempBufs)[index].size;

+        }

+

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

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

+        if (external == 0)

+        {

+          SKIP_DATA(sd, namesSize);

+        }

+        break;

+      }

+      case k7zIdEmptyStream:

+      {

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

+        numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);

+        break;

+      }

+      case k7zIdEmptyFile:

+      {

+        RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));

+        break;

+      }

+      case k7zIdWinAttrib:

+      {

+        Byte external;

+        CSzData sdSwitch;

+        CSzData *sdPtr;

+        SzBitUi32s_Free(&p->Attribs, allocMain);

+        RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));

+

+        SZ_READ_BYTE(external);

+        if (external == 0)

+          sdPtr = sd;

+        else

+        {

+          UInt32 index;

+          SzReadNumber32(sd, &index);

+          if (index >= *numTempBufs)

+            return SZ_ERROR_ARCHIVE;

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

+          sdSwitch.Size = (tempBufs)[index].size;

+          sdPtr = &sdSwitch;

+        }

+        RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));

+        break;

+      }

+      /*

+      case k7zParent:

+      {

+        SzBitUi32s_Free(&p->Parents, allocMain);

+        RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));

+        RINOK(SzReadSwitch(sd));

+        RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));

+        break;

+      }

+      */

+      case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;

+      case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;

+      default:

+      {

+        SKIP_DATA(sd, size);

+      }

+    }

+  }

+

+  if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)

+    return SZ_ERROR_ARCHIVE;

+

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+      break;

+    RINOK(SkipData(sd));

+  }

+

+  {

+    UInt32 emptyFileIndex = 0;

+

+    UInt32 folderIndex = 0;

+    UInt32 indexInFolder = 0;

+    UInt64 unpackPos = 0;

+    const Byte *digestsDefs = 0;

+    const Byte *digestsVals = 0;

+    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(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);

+    MY_ALLOC(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));

+      if (allDigestsDefined)

+        digestsVals = ssi.sdCRCs.Data;

+      else

+      {

+        size_t numBytes = (ssi.NumSubDigests + 7) >> 3;

+        digestsDefs = ssi.sdCRCs.Data;

+        digestsVals = digestsDefs + numBytes;

+      }

+    }

+

+    digestIndex = 0;

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

+    {

+      if (mask == 0)

+      {

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

+        p->IsDirs[byteIndex] = isDirMask;

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

+        isDirMask = 0;

+        crcMask = 0;

+        mask = 0x80;

+      }

+

+      p->UnpackPositions[i] = unpackPos;

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

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

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

+      {

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

+          isDirMask |= mask;

+        emptyFileIndex++;

+        if (indexInFolder == 0)

+        {

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

+          continue;

+        }

+      }

+      if (indexInFolder == 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);

+          {

+            curNumSubStreams = 1;

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

+            {

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

+            }

+          }

+          if (curNumSubStreams != 0)

+            break;

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

+          folderIndex++; // check it

+        }

+      }

+      p->FileIndexToFolderIndexMap[i] = folderIndex;

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

+        continue;

+      

+      indexInFolder++;

+      if (indexInFolder >= curNumSubStreams)

+      {

+        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]];

+        if (folderUnpackSize < unpackPos - startFolderUnpackPos)

+          return SZ_ERROR_ARCHIVE;

+        unpackPos = startFolderUnpackPos + folderUnpackSize;

+

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

+        {

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

+          crcMask |= mask;

+        }

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

+        {

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

+          digestsValsIndex++;

+          crcMask |= mask;

+        }

+        folderIndex++;

+        indexInFolder = 0;

+      }

+      else

+      {

+        UInt64 v;

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

+        unpackPos += v;

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

+        {

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

+          digestsValsIndex++;

+          crcMask |= mask;

+        }

+      }

+    }

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

+  }

+  return SZ_OK;

+}

+

+static SRes SzReadHeader(

+    CSzArEx *p,

+    CSzData *sd,

+    ILookInStream *inStream,

+    ISzAlloc *allocMain

+    ,ISzAlloc *allocTemp

+    )

+{

+  // Byte *emptyStreamVector = 0;

+  // Byte *emptyFileVector = 0;

+  // Byte *lwtVector = 0;

+  UInt32 i;

+  UInt32 numTempBufs = 0;

+  SRes res;

+  CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];

+

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

+    Buf_Init(tempBufs + i);

+  // SzBitUi32s_Init(&digests);

+  

+  res = SzReadHeader2(p, sd,

+      // &emptyStreamVector,

+      // &emptyFileVector,

+      // &lwtVector,

+      inStream,

+      tempBufs, &numTempBufs,

+      allocMain, allocTemp

+      );

+  

+  for (i = 0; i < numTempBufs; 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;

+  }

+

+  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,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

+  Byte header[k7zStartHeaderSize];

+  Int64 startArcPos;

+  UInt64 nextHeaderOffset, nextHeaderSize;

+  size_t nextHeaderSizeT;

+  UInt32 nextHeaderCRC;

+  CBuf buf;

+  SRes res;

+

+  startArcPos = 0;

+  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));

+

+  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));

+

+  if (!TestSignatureCandidate(header))

+    return SZ_ERROR_NO_ARCHIVE;

+  if (header[6] != k7zMajorVersion)

+    return SZ_ERROR_UNSUPPORTED;

+

+  nextHeaderOffset = GetUi64(header + 12);

+  nextHeaderSize = GetUi64(header + 20);

+  nextHeaderCRC = GetUi32(header + 28);

+

+  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;

+  

+  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))

+    return SZ_ERROR_CRC;

+

+  nextHeaderSizeT = (size_t)nextHeaderSize;

+  if (nextHeaderSizeT != nextHeaderSize)

+    return SZ_ERROR_MEM;

+  if (nextHeaderSizeT == 0)

+    return SZ_OK;

+  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||

+      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)

+    return SZ_ERROR_NO_ARCHIVE;

+

+  {

+    Int64 pos = 0;

+    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));

+    if ((UInt64)pos < startArcPos + nextHeaderOffset ||

+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||

+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)

+      return SZ_ERROR_INPUT_EOF;

+  }

+

+  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));

+

+  if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))

+    return SZ_ERROR_MEM;

+

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

+  if (res == SZ_OK)

+  {

+    res = SZ_ERROR_ARCHIVE;

+    if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)

+    {

+      CSzData sd;

+      UInt64 type;

+      sd.Data = buf.data;

+      sd.Size = buf.size;

+      res = ReadID(&sd, &type);

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

+      {

+        CSzAr tempAr;

+        CBuf tempBuf;

+        Buf_Init(&tempBuf);

+        

+        SzAr_Init(&tempAr);

+        res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);

+        SzAr_Free(&tempAr, allocTemp);

+       

+        if (res != SZ_OK)

+        {

+          Buf_Free(&tempBuf, allocTemp);

+        }

+        else

+        {

+          Buf_Free(&buf, allocTemp);

+          buf.data = tempBuf.data;

+          buf.size = tempBuf.size;

+          sd.Data = buf.data;

+          sd.Size = buf.size;

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

+          {

+            SzArEx_Free(p, allocMain);

+            sd2 = sd;

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

+              );

+            if (res != SZ_OK)

+              break;

+          }

+

+          // res = SzReadHeader(p, &sd, 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)

+{

+  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,

+    UInt32 fileIndex,

+    UInt32 *blockIndex,

+    Byte **tempBuf,

+    size_t *outBufferSize,

+    size_t *offset,

+    size_t *outSizeProcessed,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

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

+  SRes res = SZ_OK;

+  *offset = 0;

+  *outSizeProcessed = 0;

+  if (folderIndex == (UInt32)-1)

+  {

+    IAlloc_Free(allocMain, *tempBuf);

+    *blockIndex = folderIndex;

+    *tempBuf = 0;

+    *outBufferSize = 0;

+    return SZ_OK;

+  }

+

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

+  {

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

+    UInt64 unpackSizeSpec =

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

+        p->UnpackPositions[p->FolderStartFileIndex[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));

+    

+    if (res == SZ_OK)

+    {

+      *outBufferSize = unpackSize;

+      if (unpackSize != 0)

+      {

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

+        if (*tempBuf == 0)

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

+          }

+        }

+      }

+    }

+  }

+  if (res == SZ_OK)

+  {

+    UInt64 unpackPos = p->UnpackPositions[fileIndex];

+    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[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;

+  }

+  return res;

+}

+

+

+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)

+{

+  size_t offs = p->FileNameOffsets[fileIndex];

+  size_t len = p->FileNameOffsets[fileIndex + 1] - offs;

+  if (dest != 0)

+  {

+    size_t i;

+    const Byte *src = p->FileNames + offs * 2;

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

+      dest[i] = GetUi16(src + i * 2);

+  }

+  return len;

+}

+

+/*

+size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)

+{

+  size_t len;

+  if (!p->FileNameOffsets)

+    return 1;

+  len = 0;

+  for (;;)

+  {

+    UInt32 parent = (UInt32)(Int32)-1;

+    len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];

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

+      parent = p->Parents.Vals[fileIndex];

+    if (parent == (UInt32)(Int32)-1)

+      return len;

+    fileIndex = parent;

+  }

+}

+

+UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)

+{

+  Bool needSlash;

+  if (!p->FileNameOffsets)

+  {

+    *(--dest) = 0;

+    return dest;

+  }

+  needSlash = False;

+  for (;;)

+  {

+    UInt32 parent = (UInt32)(Int32)-1;

+    size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];

+    SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);

+    if (needSlash)

+      *(dest - 1) = '/';

+    needSlash = True;

+    dest -= curLen;

+

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

+      parent = p->Parents.Vals[fileIndex];

+    if (parent == (UInt32)(Int32)-1)

+      return dest;

+    fileIndex = parent;

+  }

+}

+*/

diff --git a/C/7zBuf.c b/C/7zBuf.c
old mode 100755
new mode 100644
index a35fa2f..b0ac110
--- a/C/7zBuf.c
+++ b/C/7zBuf.c
@@ -1,7 +1,7 @@
 /* 7zBuf.c -- Byte Buffer

-2008-03-28

-Igor Pavlov

-Public domain */

+2013-01-21 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include "7zBuf.h"

 

diff --git a/C/7zBuf.h b/C/7zBuf.h
old mode 100755
new mode 100644
index 88ff0c2..e5f9218
--- a/C/7zBuf.h
+++ b/C/7zBuf.h
@@ -1,14 +1,12 @@
 /* 7zBuf.h -- Byte Buffer

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

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

 

 #ifndef __7Z_BUF_H

 #define __7Z_BUF_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 typedef struct

 {

@@ -32,8 +30,6 @@
 int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);

 void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/7zBuf2.c b/C/7zBuf2.c
old mode 100755
new mode 100644
index 1c8b931..9633796
--- a/C/7zBuf2.c
+++ b/C/7zBuf2.c
@@ -1,7 +1,10 @@
 /* 7zBuf2.c -- Byte Buffer

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

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

+

+#include "Precomp.h"

 

 #include <string.h>

+

 #include "7zBuf.h"

 

 void DynBuf_Construct(CDynBuf *p)

diff --git a/C/7zCrc.c b/C/7zCrc.c
old mode 100755
new mode 100644
index 5801dab..161d4d1
--- a/C/7zCrc.c
+++ b/C/7zCrc.c
@@ -1,41 +1,33 @@
-/* 7zCrc.c -- CRC32 calculation

-2009-11-23 : Igor Pavlov : Public domain */

+/* 7zCrc.c -- CRC32 init

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

+

+#include "Precomp.h"

 

 #include "7zCrc.h"

 #include "CpuArch.h"

 

 #define kCrcPoly 0xEDB88320

 

-#ifdef MY_CPU_LE

-#define CRC_NUM_TABLES 8

+#ifdef MY_CPU_X86_OR_AMD64

+  #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 1

+  #define CRC_NUM_TABLES 5

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

+#endif

+

+#ifndef MY_CPU_BE

+  UInt32 MY_FAST_CALL CrcUpdateT4(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);

 

-static CRC_FUNC g_CrcUpdate;

+CRC_FUNC g_CrcUpdate;

 UInt32 g_CrcTable[256 * CRC_NUM_TABLES];

 

-#if CRC_NUM_TABLES == 1

-

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

-

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

-{

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

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

-    v = CRC_UPDATE_BYTE_2(v, *p);

-  return v;

-}

-

-#else

-

-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

-

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

 {

   return g_CrcUpdate(v, data, size, g_CrcTable);

@@ -57,18 +49,37 @@
       r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));

     g_CrcTable[i] = r;

   }

-  #if CRC_NUM_TABLES == 1

-  g_CrcUpdate = CrcUpdateT1;

-  #else

   for (; i < 256 * CRC_NUM_TABLES; i++)

   {

     UInt32 r = g_CrcTable[i - 256];

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

   }

+  

+  #ifdef MY_CPU_LE

+

   g_CrcUpdate = CrcUpdateT4;

-  #ifdef MY_CPU_X86_OR_AMD64

+  

+  #if CRC_NUM_TABLES == 8

   if (!CPU_Is_InOrder())

     g_CrcUpdate = CrcUpdateT8;

   #endif

+

+  #else

+  {

+    #ifndef MY_CPU_BE

+    UInt32 k = 1;

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

+      g_CrcUpdate = CrcUpdateT4;

+    else

+    #endif

+    {

+      for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)

+      {

+        UInt32 x = g_CrcTable[i - 256];

+        g_CrcTable[i] = CRC_UINT32_SWAP(x);

+      }

+      g_CrcUpdate = CrcUpdateT1_BeT4;

+    }

+  }

   #endif

 }

diff --git a/C/7zCrc.h b/C/7zCrc.h
old mode 100755
new mode 100644
index 4a1ec38..3b04594
--- a/C/7zCrc.h
+++ b/C/7zCrc.h
@@ -1,10 +1,10 @@
 /* 7zCrc.h -- CRC32 calculation

-2009-11-21 : Igor Pavlov : Public domain */

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

 

 #ifndef __7Z_CRC_H

 #define __7Z_CRC_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
old mode 100755
new mode 100644
index 6205d71..48b0136
--- a/C/7zCrcOpt.c
+++ b/C/7zCrcOpt.c
@@ -1,12 +1,14 @@
-/* 7zCrcOpt.c -- CRC32 calculation : optimized version

-2009-11-23 : Igor Pavlov : Public domain */

+/* 7zCrcOpt.c -- CRC32 calculation

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

+

+#include "Precomp.h"

 

 #include "CpuArch.h"

 

-#ifdef MY_CPU_LE

-

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

 

+#ifndef MY_CPU_BE

+

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

 {

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

@@ -32,3 +34,33 @@
 }

 

 #endif

+

+

+#ifndef MY_CPU_LE

+

+#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)

+{

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

+  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 -= 0x100;

+  v = CRC_UINT32_SWAP(v);

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

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+#endif

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

-2010-11-02 : Igor Pavlov : Public domain */

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

+

+#include "Precomp.h"

 

 #include <string.h>

 

@@ -63,7 +65,7 @@
   return 0;

 }

 

-static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

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

     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

 {

   CPpmd7 ppmd;

@@ -77,12 +79,12 @@
   s.res = SZ_OK;

   s.processed = 0;

 

-  if (coder->Props.size != 5)

+  if (propsSize != 5)

     return SZ_ERROR_UNSUPPORTED;

 

   {

-    unsigned order = coder->Props.data[0];

-    UInt32 memSize = GetUi32(coder->Props.data + 1);

+    unsigned order = props[0];

+    UInt32 memSize = GetUi32(props + 1);

     if (order < PPMD7_MIN_ORDER ||

         order > PPMD7_MAX_ORDER ||

         memSize < PPMD7_MIN_MEM_SIZE ||

@@ -124,14 +126,14 @@
 #endif

 

 

-static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

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

     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

 {

   CLzmaDec state;

   SRes res = SZ_OK;

 

   LzmaDec_Construct(&state);

-  RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));

+  RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));

   state.dic = outBuffer;

   state.dicBufSize = outSize;

   LzmaDec_Init(&state);

@@ -172,16 +174,16 @@
   return res;

 }

 

-static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

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

     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

 {

   CLzma2Dec state;

   SRes res = SZ_OK;

 

   Lzma2Dec_Construct(&state);

-  if (coder->Props.size != 1)

+  if (propsSize != 1)

     return SZ_ERROR_DATA;

-  RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));

+  RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));

   state.decoder.dic = outBuffer;

   state.decoder.dicBufSize = outSize;

   Lzma2Dec_Init(&state);

@@ -242,7 +244,7 @@
 

 static Bool IS_MAIN_METHOD(UInt32 m)

 {

-  switch(m)

+  switch (m)

   {

     case k_Copy:

     case k_LZMA:

@@ -260,7 +262,7 @@
   return

       c->NumInStreams == 1 &&

       c->NumOutStreams == 1 &&

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

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

       IS_MAIN_METHOD((UInt32)c->MethodID);

 }

 

@@ -280,8 +282,9 @@
   }

   if (f->NumCoders == 2)

   {

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

-    if (c->MethodID > (UInt32)0xFFFFFFFF ||

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

+    if (

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

         c->NumInStreams != 1 ||

         c->NumOutStreams != 1 ||

         f->NumPackStreams != 1 ||

@@ -321,18 +324,12 @@
   return SZ_ERROR_UNSUPPORTED;

 }

 

-static UInt64 GetSum(const UInt64 *values, UInt32 index)

-{

-  UInt64 sum = 0;

-  UInt32 i;

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

-    sum += values[i];

-  return sum;

-}

-

 #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;

 

-static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,

+static SRes SzFolder_Decode2(const CSzFolder *folder,

+    const Byte *propsData,

+    const UInt64 *unpackSizes,

+    const UInt64 *packPositions,

     ILookInStream *inStream, UInt64 startPos,

     Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,

     Byte *tempBuf[])

@@ -346,7 +343,7 @@
 

   for (ci = 0; ci < folder->NumCoders; ci++)

   {

-    CSzCoderInfo *coder = &folder->Coders[ci];

+    const CSzCoderInfo *coder = &folder->Coders[ci];

 

     if (IS_MAIN_METHOD((UInt32)coder->MethodID))

     {

@@ -358,7 +355,7 @@
       if (folder->NumCoders == 4)

       {

         UInt32 indices[] = { 3, 2, 0 };

-        UInt64 unpackSize = folder->UnpackSizes[ci];

+        UInt64 unpackSize = unpackSizes[ci];

         si = indices[ci];

         if (ci < 2)

         {

@@ -382,8 +379,8 @@
         else

           return SZ_ERROR_UNSUPPORTED;

       }

-      offset = GetSum(packSizes, si);

-      inSize = packSizes[si];

+      offset = packPositions[si];

+      inSize = packPositions[si + 1] - offset;

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

 

       if (coder->MethodID == k_Copy)

@@ -394,16 +391,16 @@
       }

       else if (coder->MethodID == k_LZMA)

       {

-        RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

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

       }

       else if (coder->MethodID == k_LZMA2)

       {

-        RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

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

       }

       else

       {

         #ifdef _7ZIP_PPMD_SUPPPORT

-        RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

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

         #else

         return SZ_ERROR_UNSUPPORTED;

         #endif

@@ -411,8 +408,8 @@
     }

     else if (coder->MethodID == k_BCJ2)

     {

-      UInt64 offset = GetSum(packSizes, 1);

-      UInt64 s3Size = packSizes[1];

+      UInt64 offset = packPositions[1];

+      UInt64 s3Size = packPositions[2] - offset;

       SRes res;

       if (ci != 3)

         return SZ_ERROR_UNSUPPORTED;

@@ -438,7 +435,7 @@
     {

       if (ci != 1)

         return SZ_ERROR_UNSUPPORTED;

-      switch(coder->MethodID)

+      switch (coder->MethodID)

       {

         case k_BCJ:

         {

@@ -456,15 +453,41 @@
   return SZ_OK;

 }

 

-SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,

+SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

     ILookInStream *inStream, UInt64 startPos,

-    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)

+    Byte *outBuffer, size_t outSize,

+    ISzAlloc *allocMain)

 {

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

-  int i;

-  SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,

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

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

-    IAlloc_Free(allocMain, tempBuf[i]);

-  return res;

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

+  

+  if (res != SZ_OK)

+    return res;

+

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

+    return SZ_ERROR_FAIL;

+  {

+    int i;

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

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

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

+        inStream, startPos,

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

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

+      IAlloc_Free(allocMain, tempBuf[i]);

+    return res;

+  }

 }

diff --git a/C/7zFile.c b/C/7zFile.c
old mode 100755
new mode 100644
index 6d82c79..98fe716
--- a/C/7zFile.c
+++ b/C/7zFile.c
@@ -1,6 +1,8 @@
 /* 7zFile.c -- File IO

 2009-11-24 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include "7zFile.h"

 

 #ifndef USE_WINDOWS_FILE

diff --git a/C/7zFile.h b/C/7zFile.h
old mode 100755
new mode 100644
index 5d85787..d62a192
--- a/C/7zFile.h
+++ b/C/7zFile.h
@@ -1,5 +1,5 @@
 /* 7zFile.h -- File IO

-2009-11-24 : Igor Pavlov : Public domain */

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

 

 #ifndef __7Z_FILE_H

 #define __7Z_FILE_H

@@ -14,7 +14,7 @@
 #include <stdio.h>

 #endif

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

diff --git a/C/7zIn.c b/C/7zIn.c
deleted file mode 100755
index f1a4492..0000000
--- a/C/7zIn.c
+++ /dev/null
@@ -1,1402 +0,0 @@
-/* 7zIn.c -- 7z Input functions

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

-

-#include <string.h>

-

-#include "7z.h"

-#include "7zCrc.h"

-#include "CpuArch.h"

-

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

-

-#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }

-

-#define NUM_FOLDER_CODERS_MAX 32

-#define NUM_CODER_STREAMS_MAX 32

-

-void SzCoderInfo_Init(CSzCoderInfo *p)

-{

-  Buf_Init(&p->Props);

-}

-

-void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)

-{

-  Buf_Free(&p->Props, alloc);

-  SzCoderInfo_Init(p);

-}

-

-void SzFolder_Init(CSzFolder *p)

-{

-  p->Coders = 0;

-  p->BindPairs = 0;

-  p->PackStreams = 0;

-  p->UnpackSizes = 0;

-  p->NumCoders = 0;

-  p->NumBindPairs = 0;

-  p->NumPackStreams = 0;

-  p->UnpackCRCDefined = 0;

-  p->UnpackCRC = 0;

-  p->NumUnpackStreams = 0;

-}

-

-void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)

-{

-  UInt32 i;

-  if (p->Coders)

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

-      SzCoderInfo_Free(&p->Coders[i], alloc);

-  IAlloc_Free(alloc, p->Coders);

-  IAlloc_Free(alloc, p->BindPairs);

-  IAlloc_Free(alloc, p->PackStreams);

-  IAlloc_Free(alloc, p->UnpackSizes);

-  SzFolder_Init(p);

-}

-

-UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)

-{

-  UInt32 result = 0;

-  UInt32 i;

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

-    result += p->Coders[i].NumOutStreams;

-  return result;

-}

-

-int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)

-{

-  UInt32 i;

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

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

-      return i;

-  return -1;

-}

-

-

-int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)

-{

-  UInt32 i;

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

-    if (p->BindPairs[i].OutIndex == outStreamIndex)

-      return i;

-  return -1;

-}

-

-UInt64 SzFolder_GetUnpackSize(CSzFolder *p)

-{

-  int i = (int)SzFolder_GetNumOutStreams(p);

-  if (i == 0)

-    return 0;

-  for (i--; i >= 0; i--)

-    if (SzFolder_FindBindPairForOutStream(p, i) < 0)

-      return p->UnpackSizes[i];

-  /* throw 1; */

-  return 0;

-}

-

-void SzFile_Init(CSzFileItem *p)

-{

-  p->HasStream = 1;

-  p->IsDir = 0;

-  p->IsAnti = 0;

-  p->CrcDefined = 0;

-  p->MTimeDefined = 0;

-}

-

-void SzAr_Init(CSzAr *p)

-{

-  p->PackSizes = 0;

-  p->PackCRCsDefined = 0;

-  p->PackCRCs = 0;

-  p->Folders = 0;

-  p->Files = 0;

-  p->NumPackStreams = 0;

-  p->NumFolders = 0;

-  p->NumFiles = 0;

-}

-

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

-{

-  UInt32 i;

-  if (p->Folders)

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

-      SzFolder_Free(&p->Folders[i], alloc);

-

-  IAlloc_Free(alloc, p->PackSizes);

-  IAlloc_Free(alloc, p->PackCRCsDefined);

-  IAlloc_Free(alloc, p->PackCRCs);

-  IAlloc_Free(alloc, p->Folders);

-  IAlloc_Free(alloc, p->Files);

-  SzAr_Init(p);

-}

-

-

-void SzArEx_Init(CSzArEx *p)

-{

-  SzAr_Init(&p->db);

-  p->FolderStartPackStreamIndex = 0;

-  p->PackStreamStartPositions = 0;

-  p->FolderStartFileIndex = 0;

-  p->FileIndexToFolderIndexMap = 0;

-  p->FileNameOffsets = 0;

-  Buf_Init(&p->FileNames);

-}

-

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

-  Buf_Free(&p->FileNames, alloc);

-

-  SzAr_Free(&p->db, alloc);

-  SzArEx_Init(p);

-}

-

-/*

-UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const

-{

-  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];

-}

-

-UInt64 GetFilePackSize(int fileIndex) const

-{

-  int folderIndex = FileIndexToFolderIndexMap[fileIndex];

-  if (folderIndex >= 0)

-  {

-    const CSzFolder &folderInfo = Folders[folderIndex];

-    if (FolderStartFileIndex[folderIndex] == fileIndex)

-    return GetFolderFullPackSize(folderIndex);

-  }

-  return 0;

-}

-*/

-

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

-

-static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)

-{

-  UInt32 startPos = 0;

-  UInt64 startPosSize = 0;

-  UInt32 i;

-  UInt32 folderIndex = 0;

-  UInt32 indexInFolder = 0;

-  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);

-  for (i = 0; i < p->db.NumFolders; i++)

-  {

-    p->FolderStartPackStreamIndex[i] = startPos;

-    startPos += p->db.Folders[i].NumPackStreams;

-  }

-

-  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);

-

-  for (i = 0; i < p->db.NumPackStreams; i++)

-  {

-    p->PackStreamStartPositions[i] = startPosSize;

-    startPosSize += p->db.PackSizes[i];

-  }

-

-  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);

-  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);

-

-  for (i = 0; i < p->db.NumFiles; i++)

-  {

-    CSzFileItem *file = p->db.Files + i;

-    int emptyStream = !file->HasStream;

-    if (emptyStream && indexInFolder == 0)

-    {

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

-      continue;

-    }

-    if (indexInFolder == 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 (p->db.Folders[folderIndex].NumUnpackStreams != 0)

-          break;

-        folderIndex++;

-      }

-    }

-    p->FileIndexToFolderIndexMap[i] = folderIndex;

-    if (emptyStream)

-      continue;

-    indexInFolder++;

-    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)

-    {

-      folderIndex++;

-      indexInFolder = 0;

-    }

-  }

-  return SZ_OK;

-}

-

-

-UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)

-{

-  return p->dataPos +

-    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];

-}

-

-int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)

-{

-  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];

-  CSzFolder *folder = p->db.Folders + folderIndex;

-  UInt64 size = 0;

-  UInt32 i;

-  for (i = 0; i < folder->NumPackStreams; i++)

-  {

-    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];

-    if (t < size) /* check it */

-      return SZ_ERROR_FAIL;

-    size = t;

-  }

-  *resSize = size;

-  return SZ_OK;

-}

-

-

-/*

-SRes SzReadTime(const CObjectVector<CBuf> &dataVector,

-    CObjectVector<CSzFileItem> &files, UInt64 type)

-{

-  CBoolVector boolVector;

-  RINOK(ReadBoolVector2(files.Size(), boolVector))

-

-  CStreamSwitch streamSwitch;

-  RINOK(streamSwitch.Set(this, &dataVector));

-

-  for (int i = 0; i < files.Size(); i++)

-  {

-    CSzFileItem &file = files[i];

-    CArchiveFileTime fileTime;

-    bool defined = boolVector[i];

-    if (defined)

-    {

-      UInt32 low, high;

-      RINOK(SzReadUInt32(low));

-      RINOK(SzReadUInt32(high));

-      fileTime.dwLowDateTime = low;

-      fileTime.dwHighDateTime = high;

-    }

-    switch(type)

-    {

-      case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;

-      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;

-      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;

-    }

-  }

-  return SZ_OK;

-}

-*/

-

-static int TestSignatureCandidate(Byte *testBytes)

-{

-  size_t i;

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

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

-      return 0;

-  return 1;

-}

-

-typedef struct _CSzState

-{

-  Byte *Data;

-  size_t Size;

-}CSzData;

-

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

-{

-  if (sd->Size == 0)

-    return SZ_ERROR_ARCHIVE;

-  sd->Size--;

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

-  return SZ_OK;

-}

-

-static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size)

-{

-  size_t i;

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

-  {

-    RINOK(SzReadByte(sd, data + i));

-  }

-  return SZ_OK;

-}

-

-static SRes SzReadUInt32(CSzData *sd, UInt32 *value)

-{

-  int i;

-  *value = 0;

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

-  {

-    Byte b;

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

-    *value |= ((UInt32)(b) << (8 * i));

-  }

-  return SZ_OK;

-}

-

-static SRes SzReadNumber(CSzData *sd, UInt64 *value)

-{

-  Byte firstByte;

-  Byte mask = 0x80;

-  int i;

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

-  *value = 0;

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

-  {

-    Byte b;

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

-    {

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

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

-      return SZ_OK;

-    }

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

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

-    mask >>= 1;

-  }

-  return SZ_OK;

-}

-

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

-{

-  UInt64 value64;

-  RINOK(SzReadNumber(sd, &value64));

-  if (value64 >= 0x80000000)

-    return SZ_ERROR_UNSUPPORTED;

-  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))

-    return SZ_ERROR_UNSUPPORTED;

-  *value = (UInt32)value64;

-  return SZ_OK;

-}

-

-static SRes SzReadID(CSzData *sd, UInt64 *value)

-{

-  return SzReadNumber(sd, value);

-}

-

-static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)

-{

-  if (size > sd->Size)

-    return SZ_ERROR_ARCHIVE;

-  sd->Size -= (size_t)size;

-  sd->Data += (size_t)size;

-  return SZ_OK;

-}

-

-static SRes SzSkeepData(CSzData *sd)

-{

-  UInt64 size;

-  RINOK(SzReadNumber(sd, &size));

-  return SzSkeepDataSize(sd, size);

-}

-

-static SRes SzReadArchiveProperties(CSzData *sd)

-{

-  for (;;)

-  {

-    UInt64 type;

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

-    if (type == k7zIdEnd)

-      break;

-    SzSkeepData(sd);

-  }

-  return SZ_OK;

-}

-

-static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)

-{

-  for (;;)

-  {

-    UInt64 type;

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

-    if (type == attribute)

-      return SZ_OK;

-    if (type == k7zIdEnd)

-      return SZ_ERROR_ARCHIVE;

-    RINOK(SzSkeepData(sd));

-  }

-}

-

-static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)

-{

-  Byte b = 0;

-  Byte mask = 0;

-  size_t i;

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

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

-  {

-    if (mask == 0)

-    {

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

-      mask = 0x80;

-    }

-    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);

-    mask >>= 1;

-  }

-  return SZ_OK;

-}

-

-static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)

-{

-  Byte allAreDefined;

-  size_t i;

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

-  if (allAreDefined == 0)

-    return SzReadBoolVector(sd, numItems, v, alloc);

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

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

-    (*v)[i] = 1;

-  return SZ_OK;

-}

-

-static SRes SzReadHashDigests(

-    CSzData *sd,

-    size_t numItems,

-    Byte **digestsDefined,

-    UInt32 **digests,

-    ISzAlloc *alloc)

-{

-  size_t i;

-  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));

-  MY_ALLOC(UInt32, *digests, numItems, alloc);

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

-    if ((*digestsDefined)[i])

-    {

-      RINOK(SzReadUInt32(sd, (*digests) + i));

-    }

-  return SZ_OK;

-}

-

-static SRes SzReadPackInfo(

-    CSzData *sd,

-    UInt64 *dataOffset,

-    UInt32 *numPackStreams,

-    UInt64 **packSizes,

-    Byte **packCRCsDefined,

-    UInt32 **packCRCs,

-    ISzAlloc *alloc)

-{

-  UInt32 i;

-  RINOK(SzReadNumber(sd, dataOffset));

-  RINOK(SzReadNumber32(sd, numPackStreams));

-

-  RINOK(SzWaitAttribute(sd, k7zIdSize));

-

-  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);

-

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

-  {

-    RINOK(SzReadNumber(sd, (*packSizes) + i));

-  }

-

-  for (;;)

-  {

-    UInt64 type;

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

-    if (type == k7zIdEnd)

-      break;

-    if (type == k7zIdCRC)

-    {

-      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc));

-      continue;

-    }

-    RINOK(SzSkeepData(sd));

-  }

-  if (*packCRCsDefined == 0)

-  {

-    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);

-    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);

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

-    {

-      (*packCRCsDefined)[i] = 0;

-      (*packCRCs)[i] = 0;

-    }

-  }

-  return SZ_OK;

-}

-

-static SRes SzReadSwitch(CSzData *sd)

-{

-  Byte external;

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

-  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;

-}

-

-static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)

-{

-  UInt32 numCoders, numBindPairs, numPackStreams, i;

-  UInt32 numInStreams = 0, numOutStreams = 0;

-  

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

-  if (numCoders > NUM_FOLDER_CODERS_MAX)

-    return SZ_ERROR_UNSUPPORTED;

-  folder->NumCoders = numCoders;

-  

-  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);

-

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

-    SzCoderInfo_Init(folder->Coders + i);

-

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

-  {

-    Byte mainByte;

-    CSzCoderInfo *coder = folder->Coders + i;

-    {

-      unsigned idSize, j;

-      Byte longID[15];

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

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

-      RINOK(SzReadBytes(sd, longID, idSize));

-      if (idSize > sizeof(coder->MethodID))

-        return SZ_ERROR_UNSUPPORTED;

-      coder->MethodID = 0;

-      for (j = 0; j < idSize; j++)

-        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);

-

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

-      {

-        RINOK(SzReadNumber32(sd, &coder->NumInStreams));

-        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));

-        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||

-            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)

-          return SZ_ERROR_UNSUPPORTED;

-      }

-      else

-      {

-        coder->NumInStreams = 1;

-        coder->NumOutStreams = 1;

-      }

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

-      {

-        UInt64 propertiesSize = 0;

-        RINOK(SzReadNumber(sd, &propertiesSize));

-        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))

-          return SZ_ERROR_MEM;

-        RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));

-      }

-    }

-    while ((mainByte & 0x80) != 0)

-    {

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

-      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));

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

-      {

-        UInt32 n;

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

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

-      }

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

-      {

-        UInt64 propertiesSize = 0;

-        RINOK(SzReadNumber(sd, &propertiesSize));

-        RINOK(SzSkeepDataSize(sd, propertiesSize));

-      }

-    }

-    numInStreams += coder->NumInStreams;

-    numOutStreams += coder->NumOutStreams;

-  }

-

-  if (numOutStreams == 0)

-    return SZ_ERROR_UNSUPPORTED;

-

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

-  MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);

-

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

-  {

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

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

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

-  }

-

-  if (numInStreams < numBindPairs)

-    return SZ_ERROR_UNSUPPORTED;

-

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

-  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);

-

-  if (numPackStreams == 1)

-  {

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

-      if (SzFolder_FindBindPairForInStream(folder, i) < 0)

-        break;

-    if (i == numInStreams)

-      return SZ_ERROR_UNSUPPORTED;

-    folder->PackStreams[0] = i;

-  }

-  else

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

-    {

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

-    }

-  return SZ_OK;

-}

-

-static SRes SzReadUnpackInfo(

-    CSzData *sd,

-    UInt32 *numFolders,

-    CSzFolder **folders,  /* for alloc */

-    ISzAlloc *alloc,

-    ISzAlloc *allocTemp)

-{

-  UInt32 i;

-  RINOK(SzWaitAttribute(sd, k7zIdFolder));

-  RINOK(SzReadNumber32(sd, numFolders));

-  {

-    RINOK(SzReadSwitch(sd));

-

-    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);

-

-    for (i = 0; i < *numFolders; i++)

-      SzFolder_Init((*folders) + i);

-

-    for (i = 0; i < *numFolders; i++)

-    {

-      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));

-    }

-  }

-

-  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));

-

-  for (i = 0; i < *numFolders; i++)

-  {

-    UInt32 j;

-    CSzFolder *folder = (*folders) + i;

-    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);

-

-    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);

-

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

-    {

-      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));

-    }

-  }

-

-  for (;;)

-  {

-    UInt64 type;

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

-    if (type == k7zIdEnd)

-      return SZ_OK;

-    if (type == k7zIdCRC)

-    {

-      SRes res;

-      Byte *crcsDefined = 0;

-      UInt32 *crcs = 0;

-      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);

-      if (res == SZ_OK)

-      {

-        for (i = 0; i < *numFolders; i++)

-        {

-          CSzFolder *folder = (*folders) + i;

-          folder->UnpackCRCDefined = crcsDefined[i];

-          folder->UnpackCRC = crcs[i];

-        }

-      }

-      IAlloc_Free(allocTemp, crcs);

-      IAlloc_Free(allocTemp, crcsDefined);

-      RINOK(res);

-      continue;

-    }

-    RINOK(SzSkeepData(sd));

-  }

-}

-

-static SRes SzReadSubStreamsInfo(

-    CSzData *sd,

-    UInt32 numFolders,

-    CSzFolder *folders,

-    UInt32 *numUnpackStreams,

-    UInt64 **unpackSizes,

-    Byte **digestsDefined,

-    UInt32 **digests,

-    ISzAlloc *allocTemp)

-{

-  UInt64 type = 0;

-  UInt32 i;

-  UInt32 si = 0;

-  UInt32 numDigests = 0;

-

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

-    folders[i].NumUnpackStreams = 1;

-  *numUnpackStreams = numFolders;

-

-  for (;;)

-  {

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

-    if (type == k7zIdNumUnpackStream)

-    {

-      *numUnpackStreams = 0;

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

-      {

-        UInt32 numStreams;

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

-        folders[i].NumUnpackStreams = numStreams;

-        *numUnpackStreams += numStreams;

-      }

-      continue;

-    }

-    if (type == k7zIdCRC || type == k7zIdSize)

-      break;

-    if (type == k7zIdEnd)

-      break;

-    RINOK(SzSkeepData(sd));

-  }

-

-  if (*numUnpackStreams == 0)

-  {

-    *unpackSizes = 0;

-    *digestsDefined = 0;

-    *digests = 0;

-  }

-  else

-  {

-    *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));

-    RINOM(*unpackSizes);

-    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));

-    RINOM(*digestsDefined);

-    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));

-    RINOM(*digests);

-  }

-

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

-  {

-    /*

-    v3.13 incorrectly worked with empty folders

-    v4.07: we check that folder is empty

-    */

-    UInt64 sum = 0;

-    UInt32 j;

-    UInt32 numSubstreams = folders[i].NumUnpackStreams;

-    if (numSubstreams == 0)

-      continue;

-    if (type == k7zIdSize)

-    for (j = 1; j < numSubstreams; j++)

-    {

-      UInt64 size;

-      RINOK(SzReadNumber(sd, &size));

-      (*unpackSizes)[si++] = size;

-      sum += size;

-    }

-    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;

-  }

-  if (type == k7zIdSize)

-  {

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

-  }

-

-  for (i = 0; i < *numUnpackStreams; i++)

-  {

-    (*digestsDefined)[i] = 0;

-    (*digests)[i] = 0;

-  }

-

-

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

-  {

-    UInt32 numSubstreams = folders[i].NumUnpackStreams;

-    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)

-      numDigests += numSubstreams;

-  }

-

- 

-  si = 0;

-  for (;;)

-  {

-    if (type == k7zIdCRC)

-    {

-      int digestIndex = 0;

-      Byte *digestsDefined2 = 0;

-      UInt32 *digests2 = 0;

-      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);

-      if (res == SZ_OK)

-      {

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

-        {

-          CSzFolder *folder = folders + i;

-          UInt32 numSubstreams = folder->NumUnpackStreams;

-          if (numSubstreams == 1 && folder->UnpackCRCDefined)

-          {

-            (*digestsDefined)[si] = 1;

-            (*digests)[si] = folder->UnpackCRC;

-            si++;

-          }

-          else

-          {

-            UInt32 j;

-            for (j = 0; j < numSubstreams; j++, digestIndex++)

-            {

-              (*digestsDefined)[si] = digestsDefined2[digestIndex];

-              (*digests)[si] = digests2[digestIndex];

-              si++;

-            }

-          }

-        }

-      }

-      IAlloc_Free(allocTemp, digestsDefined2);

-      IAlloc_Free(allocTemp, digests2);

-      RINOK(res);

-    }

-    else if (type == k7zIdEnd)

-      return SZ_OK;

-    else

-    {

-      RINOK(SzSkeepData(sd));

-    }

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

-  }

-}

-

-

-static SRes SzReadStreamsInfo(

-    CSzData *sd,

-    UInt64 *dataOffset,

-    CSzAr *p,

-    UInt32 *numUnpackStreams,

-    UInt64 **unpackSizes, /* allocTemp */

-    Byte **digestsDefined,   /* allocTemp */

-    UInt32 **digests,        /* allocTemp */

-    ISzAlloc *alloc,

-    ISzAlloc *allocTemp)

-{

-  for (;;)

-  {

-    UInt64 type;

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

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

-      return SZ_ERROR_UNSUPPORTED;

-    switch((int)type)

-    {

-      case k7zIdEnd:

-        return SZ_OK;

-      case k7zIdPackInfo:

-      {

-        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,

-            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));

-        break;

-      }

-      case k7zIdUnpackInfo:

-      {

-        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));

-        break;

-      }

-      case k7zIdSubStreamsInfo:

-      {

-        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,

-            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));

-        break;

-      }

-      default:

-        return SZ_ERROR_UNSUPPORTED;

-    }

-  }

-}

-

-size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)

-{

-  size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];

-  if (dest != 0)

-  {

-    size_t i;

-    const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);

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

-      dest[i] = GetUi16(src + i * 2);

-  }

-  return len;

-}

-

-static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)

-{

-  UInt32 i;

-  size_t pos = 0;

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

-  {

-    sizes[i] = pos;

-    for (;;)

-    {

-      if (pos >= size)

-        return SZ_ERROR_ARCHIVE;

-      if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)

-        break;

-      pos++;

-    }

-    pos++;

-  }

-  sizes[i] = pos;

-  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;

-}

-

-static SRes SzReadHeader2(

-    CSzArEx *p,   /* allocMain */

-    CSzData *sd,

-    UInt64 **unpackSizes,  /* allocTemp */

-    Byte **digestsDefined,    /* allocTemp */

-    UInt32 **digests,         /* allocTemp */

-    Byte **emptyStreamVector, /* allocTemp */

-    Byte **emptyFileVector,   /* allocTemp */

-    Byte **lwtVector,         /* allocTemp */

-    ISzAlloc *allocMain,

-    ISzAlloc *allocTemp)

-{

-  UInt64 type;

-  UInt32 numUnpackStreams = 0;

-  UInt32 numFiles = 0;

-  CSzFileItem *files = 0;

-  UInt32 numEmptyStreams = 0;

-  UInt32 i;

-

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

-

-  if (type == k7zIdArchiveProperties)

-  {

-    RINOK(SzReadArchiveProperties(sd));

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

-  }

- 

- 

-  if (type == k7zIdMainStreamsInfo)

-  {

-    RINOK(SzReadStreamsInfo(sd,

-        &p->dataPos,

-        &p->db,

-        &numUnpackStreams,

-        unpackSizes,

-        digestsDefined,

-        digests, allocMain, allocTemp));

-    p->dataPos += p->startPosAfterHeader;

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

-  }

-

-  if (type == k7zIdEnd)

-    return SZ_OK;

-  if (type != k7zIdFilesInfo)

-    return SZ_ERROR_ARCHIVE;

-  

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

-  p->db.NumFiles = numFiles;

-

-  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);

-

-  p->db.Files = files;

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

-    SzFile_Init(files + i);

-

-  for (;;)

-  {

-    UInt64 type;

-    UInt64 size;

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

-    if (type == k7zIdEnd)

-      break;

-    RINOK(SzReadNumber(sd, &size));

-    if (size > sd->Size)

-      return SZ_ERROR_ARCHIVE;

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

-    {

-      RINOK(SzSkeepDataSize(sd, size));

-    }

-    else

-    switch((int)type)

-    {

-      case k7zIdName:

-      {

-        size_t namesSize;

-        RINOK(SzReadSwitch(sd));

-        namesSize = (size_t)size - 1;

-        if ((namesSize & 1) != 0)

-          return SZ_ERROR_ARCHIVE;

-        if (!Buf_Create(&p->FileNames, namesSize, allocMain))

-          return SZ_ERROR_MEM;

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

-        memcpy(p->FileNames.data, sd->Data, namesSize);

-        RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))

-        RINOK(SzSkeepDataSize(sd, namesSize));

-        break;

-      }

-      case k7zIdEmptyStream:

-      {

-        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));

-        numEmptyStreams = 0;

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

-          if ((*emptyStreamVector)[i])

-            numEmptyStreams++;

-        break;

-      }

-      case k7zIdEmptyFile:

-      {

-        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));

-        break;

-      }

-      case k7zIdWinAttributes:

-      {

-        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));

-        RINOK(SzReadSwitch(sd));

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

-        {

-          CSzFileItem *f = &files[i];

-          Byte defined = (*lwtVector)[i];

-          f->AttribDefined = defined;

-          f->Attrib = 0;

-          if (defined)

-          {

-            RINOK(SzReadUInt32(sd, &f->Attrib));

-          }

-        }

-        IAlloc_Free(allocTemp, *lwtVector);

-        *lwtVector = NULL;

-        break;

-      }

-      case k7zIdMTime:

-      {

-        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));

-        RINOK(SzReadSwitch(sd));

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

-        {

-          CSzFileItem *f = &files[i];

-          Byte defined = (*lwtVector)[i];

-          f->MTimeDefined = defined;

-          f->MTime.Low = f->MTime.High = 0;

-          if (defined)

-          {

-            RINOK(SzReadUInt32(sd, &f->MTime.Low));

-            RINOK(SzReadUInt32(sd, &f->MTime.High));

-          }

-        }

-        IAlloc_Free(allocTemp, *lwtVector);

-        *lwtVector = NULL;

-        break;

-      }

-      default:

-      {

-        RINOK(SzSkeepDataSize(sd, size));

-      }

-    }

-  }

-

-  {

-    UInt32 emptyFileIndex = 0;

-    UInt32 sizeIndex = 0;

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

-    {

-      CSzFileItem *file = files + i;

-      file->IsAnti = 0;

-      if (*emptyStreamVector == 0)

-        file->HasStream = 1;

-      else

-        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);

-      if (file->HasStream)

-      {

-        file->IsDir = 0;

-        file->Size = (*unpackSizes)[sizeIndex];

-        file->Crc = (*digests)[sizeIndex];

-        file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];

-        sizeIndex++;

-      }

-      else

-      {

-        if (*emptyFileVector == 0)

-          file->IsDir = 1;

-        else

-          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);

-        emptyFileIndex++;

-        file->Size = 0;

-        file->Crc = 0;

-        file->CrcDefined = 0;

-      }

-    }

-  }

-  return SzArEx_Fill(p, allocMain);

-}

-

-static SRes SzReadHeader(

-    CSzArEx *p,

-    CSzData *sd,

-    ISzAlloc *allocMain,

-    ISzAlloc *allocTemp)

-{

-  UInt64 *unpackSizes = 0;

-  Byte *digestsDefined = 0;

-  UInt32 *digests = 0;

-  Byte *emptyStreamVector = 0;

-  Byte *emptyFileVector = 0;

-  Byte *lwtVector = 0;

-  SRes res = SzReadHeader2(p, sd,

-      &unpackSizes, &digestsDefined, &digests,

-      &emptyStreamVector, &emptyFileVector, &lwtVector,

-      allocMain, allocTemp);

-  IAlloc_Free(allocTemp, unpackSizes);

-  IAlloc_Free(allocTemp, digestsDefined);

-  IAlloc_Free(allocTemp, digests);

-  IAlloc_Free(allocTemp, emptyStreamVector);

-  IAlloc_Free(allocTemp, emptyFileVector);

-  IAlloc_Free(allocTemp, lwtVector);

-  return res;

-}

-

-static SRes SzReadAndDecodePackedStreams2(

-    ILookInStream *inStream,

-    CSzData *sd,

-    CBuf *outBuffer,

-    UInt64 baseOffset,

-    CSzAr *p,

-    UInt64 **unpackSizes,

-    Byte **digestsDefined,

-    UInt32 **digests,

-    ISzAlloc *allocTemp)

-{

-

-  UInt32 numUnpackStreams = 0;

-  UInt64 dataStartPos;

-  CSzFolder *folder;

-  UInt64 unpackSize;

-  SRes res;

-

-  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,

-      &numUnpackStreams,  unpackSizes, digestsDefined, digests,

-      allocTemp, allocTemp));

-  

-  dataStartPos += baseOffset;

-  if (p->NumFolders != 1)

-    return SZ_ERROR_ARCHIVE;

-

-  folder = p->Folders;

-  unpackSize = SzFolder_GetUnpackSize(folder);

-  

-  RINOK(LookInStream_SeekTo(inStream, dataStartPos));

-

-  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))

-    return SZ_ERROR_MEM;

-  

-  res = SzFolder_Decode(folder, p->PackSizes,

-          inStream, dataStartPos,

-          outBuffer->data, (size_t)unpackSize, allocTemp);

-  RINOK(res);

-  if (folder->UnpackCRCDefined)

-    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)

-      return SZ_ERROR_CRC;

-  return SZ_OK;

-}

-

-static SRes SzReadAndDecodePackedStreams(

-    ILookInStream *inStream,

-    CSzData *sd,

-    CBuf *outBuffer,

-    UInt64 baseOffset,

-    ISzAlloc *allocTemp)

-{

-  CSzAr p;

-  UInt64 *unpackSizes = 0;

-  Byte *digestsDefined = 0;

-  UInt32 *digests = 0;

-  SRes res;

-  SzAr_Init(&p);

-  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,

-    &p, &unpackSizes, &digestsDefined, &digests,

-    allocTemp);

-  SzAr_Free(&p, allocTemp);

-  IAlloc_Free(allocTemp, unpackSizes);

-  IAlloc_Free(allocTemp, digestsDefined);

-  IAlloc_Free(allocTemp, digests);

-  return res;

-}

-

-static SRes SzArEx_Open2(

-    CSzArEx *p,

-    ILookInStream *inStream,

-    ISzAlloc *allocMain,

-    ISzAlloc *allocTemp)

-{

-  Byte header[k7zStartHeaderSize];

-  Int64 startArcPos;

-  UInt64 nextHeaderOffset, nextHeaderSize;

-  size_t nextHeaderSizeT;

-  UInt32 nextHeaderCRC;

-  CBuf buffer;

-  SRes res;

-

-  startArcPos = 0;

-  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));

-

-  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));

-

-  if (!TestSignatureCandidate(header))

-    return SZ_ERROR_NO_ARCHIVE;

-  if (header[6] != k7zMajorVersion)

-    return SZ_ERROR_UNSUPPORTED;

-

-  nextHeaderOffset = GetUi64(header + 12);

-  nextHeaderSize = GetUi64(header + 20);

-  nextHeaderCRC = GetUi32(header + 28);

-

-  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;

-  

-  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))

-    return SZ_ERROR_CRC;

-

-  nextHeaderSizeT = (size_t)nextHeaderSize;

-  if (nextHeaderSizeT != nextHeaderSize)

-    return SZ_ERROR_MEM;

-  if (nextHeaderSizeT == 0)

-    return SZ_OK;

-  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||

-      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)

-    return SZ_ERROR_NO_ARCHIVE;

-

-  {

-    Int64 pos = 0;

-    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));

-    if ((UInt64)pos < startArcPos + nextHeaderOffset ||

-        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||

-        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)

-      return SZ_ERROR_INPUT_EOF;

-  }

-

-  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));

-

-  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))

-    return SZ_ERROR_MEM;

-

-  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);

-  if (res == SZ_OK)

-  {

-    res = SZ_ERROR_ARCHIVE;

-    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)

-    {

-      CSzData sd;

-      UInt64 type;

-      sd.Data = buffer.data;

-      sd.Size = buffer.size;

-      res = SzReadID(&sd, &type);

-      if (res == SZ_OK)

-      {

-        if (type == k7zIdEncodedHeader)

-        {

-          CBuf outBuffer;

-          Buf_Init(&outBuffer);

-          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);

-          if (res != SZ_OK)

-            Buf_Free(&outBuffer, allocTemp);

-          else

-          {

-            Buf_Free(&buffer, allocTemp);

-            buffer.data = outBuffer.data;

-            buffer.size = outBuffer.size;

-            sd.Data = buffer.data;

-            sd.Size = buffer.size;

-            res = SzReadID(&sd, &type);

-          }

-        }

-      }

-      if (res == SZ_OK)

-      {

-        if (type == k7zIdHeader)

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

-        else

-          res = SZ_ERROR_UNSUPPORTED;

-      }

-    }

-  }

-  Buf_Free(&buffer, allocTemp);

-  return res;

-}

-

-SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)

-{

-  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);

-  if (res != SZ_OK)

-    SzArEx_Free(p, allocMain);

-  return res;

-}

-

-SRes SzArEx_Extract(

-    const CSzArEx *p,

-    ILookInStream *inStream,

-    UInt32 fileIndex,

-    UInt32 *blockIndex,

-    Byte **outBuffer,

-    size_t *outBufferSize,

-    size_t *offset,

-    size_t *outSizeProcessed,

-    ISzAlloc *allocMain,

-    ISzAlloc *allocTemp)

-{

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

-  SRes res = SZ_OK;

-  *offset = 0;

-  *outSizeProcessed = 0;

-  if (folderIndex == (UInt32)-1)

-  {

-    IAlloc_Free(allocMain, *outBuffer);

-    *blockIndex = folderIndex;

-    *outBuffer = 0;

-    *outBufferSize = 0;

-    return SZ_OK;

-  }

-

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

-  {

-    CSzFolder *folder = p->db.Folders + folderIndex;

-    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);

-    size_t unpackSize = (size_t)unpackSizeSpec;

-    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

-

-    if (unpackSize != unpackSizeSpec)

-      return SZ_ERROR_MEM;

-    *blockIndex = folderIndex;

-    IAlloc_Free(allocMain, *outBuffer);

-    *outBuffer = 0;

-    

-    RINOK(LookInStream_SeekTo(inStream, startOffset));

-    

-    if (res == SZ_OK)

-    {

-      *outBufferSize = unpackSize;

-      if (unpackSize != 0)

-      {

-        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);

-        if (*outBuffer == 0)

-          res = SZ_ERROR_MEM;

-      }

-      if (res == SZ_OK)

-      {

-        res = SzFolder_Decode(folder,

-          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],

-          inStream, startOffset,

-          *outBuffer, unpackSize, allocTemp);

-        if (res == SZ_OK)

-        {

-          if (folder->UnpackCRCDefined)

-          {

-            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)

-              res = SZ_ERROR_CRC;

-          }

-        }

-      }

-    }

-  }

-  if (res == SZ_OK)

-  {

-    UInt32 i;

-    CSzFileItem *fileItem = p->db.Files + fileIndex;

-    *offset = 0;

-    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)

-      *offset += (UInt32)p->db.Files[i].Size;

-    *outSizeProcessed = (size_t)fileItem->Size;

-    if (*offset + *outSizeProcessed > *outBufferSize)

-      return SZ_ERROR_FAIL;

-    if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)

-      res = SZ_ERROR_CRC;

-  }

-  return res;

-}

diff --git a/C/7zStream.c b/C/7zStream.c
old mode 100755
new mode 100644
index f0959fb..5a92d53
--- a/C/7zStream.c
+++ b/C/7zStream.c
@@ -1,9 +1,11 @@
 /* 7zStream.c -- 7z Stream functions

-2010-03-11 : Igor Pavlov : Public domain */

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

+

+#include "Precomp.h"

 

 #include <string.h>

 

-#include "Types.h"

+#include "7zTypes.h"

 

 SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)

 {

diff --git a/C/Types.h b/C/7zTypes.h
old mode 100755
new mode 100644
similarity index 96%
rename from C/Types.h
rename to C/7zTypes.h
index f193ce2..903047b
--- a/C/Types.h
+++ b/C/7zTypes.h
@@ -1,15 +1,15 @@
-/* Types.h -- Basic types

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

+/* 7zTypes.h -- Basic types

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

 

 #ifndef __7Z_TYPES_H

 #define __7Z_TYPES_H

 

-#include <stddef.h>

-

 #ifdef _WIN32

-#include <windows.h>

+/* #include <windows.h> */

 #endif

 

+#include <stddef.h>

+

 #ifndef EXTERN_C_BEGIN

 #ifdef __cplusplus

 #define EXTERN_C_BEGIN extern "C" {

@@ -43,7 +43,8 @@
 typedef int SRes;

 

 #ifdef _WIN32

-typedef DWORD WRes;

+/* typedef DWORD WRes; */

+typedef unsigned WRes;

 #else

 typedef int WRes;

 #endif

@@ -116,6 +117,7 @@
 

 #else

 

+#define MY_NO_INLINE

 #define MY_CDECL

 #define MY_FAST_CALL

 

diff --git a/C/7zVersion.h b/C/7zVersion.h
old mode 100755
new mode 100644
index d4ac470..feedd30
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,7 +1,10 @@
 #define MY_VER_MAJOR 9

-#define MY_VER_MINOR 20

-#define MY_VER_BUILD 0

-#define MY_VERSION "9.20"

-#define MY_DATE "2010-11-18"

+#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"

+#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

diff --git a/C/7zVersion.rc b/C/7zVersion.rc
new file mode 100644
index 0000000..6ed26de
--- /dev/null
+++ b/C/7zVersion.rc
@@ -0,0 +1,55 @@
+#define MY_VS_FFI_FILEFLAGSMASK  0x0000003FL

+#define MY_VOS_NT_WINDOWS32  0x00040004L

+#define MY_VOS_CE_WINDOWS32  0x00050004L

+

+#define MY_VFT_APP  0x00000001L

+#define MY_VFT_DLL  0x00000002L

+

+// #include <WinVer.h>

+

+#ifndef MY_VERSION

+#include "7zVersion.h"

+#endif

+

+#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0

+

+#ifdef DEBUG

+#define DBG_FL VS_FF_DEBUG

+#else

+#define DBG_FL 0

+#endif

+

+#define MY_VERSION_INFO(fileType, descr, intName, origName)  \

+LANGUAGE 9, 1 \

+1 VERSIONINFO \

+  FILEVERSION MY_VER \

+  PRODUCTVERSION MY_VER \

+  FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \

+  FILEFLAGS DBG_FL \

+  FILEOS MY_VOS_NT_WINDOWS32 \

+  FILETYPE fileType \

+  FILESUBTYPE 0x0L \

+BEGIN \

+    BLOCK "StringFileInfo" \

+    BEGIN  \

+        BLOCK "040904b0" \

+        BEGIN \

+            VALUE "CompanyName", "Igor Pavlov" \

+            VALUE "FileDescription", descr \

+            VALUE "FileVersion", MY_VERSION  \

+            VALUE "InternalName", intName \

+            VALUE "LegalCopyright", MY_COPYRIGHT \

+            VALUE "OriginalFilename", origName \

+            VALUE "ProductName", "7-Zip" \

+            VALUE "ProductVersion", MY_VERSION \

+        END \

+    END \

+    BLOCK "VarFileInfo" \

+    BEGIN \

+        VALUE "Translation", 0x409, 1200 \

+    END \

+END

+

+#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe")

+

+#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll")

diff --git a/C/Aes.c b/C/Aes.c
new file mode 100644
index 0000000..06bf9d3
--- /dev/null
+++ b/C/Aes.c
@@ -0,0 +1,284 @@
+/* Aes.c -- AES encryption / decryption

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

+

+#include "Precomp.h"

+

+#include "Aes.h"

+#include "CpuArch.h"

+

+static UInt32 T[256 * 4];

+static 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,

+  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,

+  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,

+  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,

+  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,

+  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,

+  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,

+  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,

+  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,

+  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,

+  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,

+  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,

+  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,

+  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+AES_CODE_FUNC g_AesCbc_Encode;

+AES_CODE_FUNC g_AesCbc_Decode;

+AES_CODE_FUNC g_AesCtr_Code;

+

+static UInt32 D[256 * 4];

+static Byte InvS[256];

+

+static 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)

+

+#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))

+

+#define gb0(x) ( (x)          & 0xFF)

+#define gb1(x) (((x) >> ( 8)) & 0xFF)

+#define gb2(x) (((x) >> (16)) & 0xFF)

+#define gb3(x) (((x) >> (24)) & 0xFF)

+

+void AesGenTables(void)

+{

+  unsigned i;

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

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

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

+  {

+    {

+      UInt32 a1 = Sbox[i];

+      UInt32 a2 = xtime(a1);

+      UInt32 a3 = a2 ^ a1;

+      T[        i] = Ui32(a2, a1, a1, a3);

+      T[0x100 + i] = Ui32(a3, a2, a1, a1);

+      T[0x200 + i] = Ui32(a1, a3, a2, a1);

+      T[0x300 + i] = Ui32(a1, a1, a3, a2);

+    }

+    {

+      UInt32 a1 = InvS[i];

+      UInt32 a2 = xtime(a1);

+      UInt32 a4 = xtime(a2);

+      UInt32 a8 = xtime(a4);

+      UInt32 a9 = a8 ^ a1;

+      UInt32 aB = a8 ^ a2 ^ a1;

+      UInt32 aD = a8 ^ a4 ^ a1;

+      UInt32 aE = a8 ^ a4 ^ a2;

+      D[        i] = Ui32(aE, a9, aD, aB);

+      D[0x100 + i] = Ui32(aB, aE, a9, aD);

+      D[0x200 + i] = Ui32(aD, aB, aE, a9);

+      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())

+  {

+    g_AesCbc_Encode = AesCbc_Encode_Intel;

+    g_AesCbc_Decode = AesCbc_Decode_Intel;

+    g_AesCtr_Code = AesCtr_Code_Intel;

+  }

+  #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); \

+

+#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, 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];

+

+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)

+{

+  unsigned i, wSize;

+  wSize = keySize + 28;

+  keySize /= 4;

+  w[0] = ((UInt32)keySize / 2) + 3;

+  w += 4;

+

+  for (i = 0; i < keySize; i++, key += 4)

+    w[i] = GetUi32(key);

+

+  for (; i < wSize; i++)

+  {

+    UInt32 t = w[i - 1];

+    unsigned rem = i % keySize;

+    if (rem == 0)

+      t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);

+    else if (keySize > 6 && rem == 4)

+      t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);

+    w[i] = w[i - keySize] ^ t;

+  }

+}

+

+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)

+{

+  unsigned i, num;

+  Aes_SetKey_Enc(w, key, keySize);

+  num = keySize + 20;

+  w += 8;

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

+  {

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

+  }

+}

+

+/* 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 */

+

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

+{

+  UInt32 s[4];

+  UInt32 m[4];

+  UInt32 numRounds2 = w[0];

+  w += 4;

+  s[0] = src[0] ^ w[0];

+  s[1] = src[1] ^ w[1];

+  s[2] = src[2] ^ w[2];

+  s[3] = src[3] ^ w[3];

+  w += 4;

+  for (;;)

+  {

+    HT16(m, s, 0);

+    if (--numRounds2 == 0)

+      break;

+    HT16(s, m, 4);

+    w += 8;

+  }

+  w += 4;

+  FT4(0); FT4(1); FT4(2); FT4(3);

+}

+

+static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)

+{

+  UInt32 s[4];

+  UInt32 m[4];

+  UInt32 numRounds2 = w[0];

+  w += 4 + numRounds2 * 8;

+  s[0] = src[0] ^ w[0];

+  s[1] = src[1] ^ w[1];

+  s[2] = src[2] ^ w[2];

+  s[3] = src[3] ^ w[3];

+  for (;;)

+  {

+    w -= 8;

+    HD16(m, s, 4);

+    if (--numRounds2 == 0)

+      break;

+    HD16(s, m, 0);

+  }

+  FD4(0); FD4(1); FD4(2); FD4(3);

+}

+

+void AesCbc_Init(UInt32 *p, const Byte *iv)

+{

+  unsigned i;

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

+    p[i] = GetUi32(iv + i * 4);

+}

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)

+  {

+    p[0] ^= GetUi32(data);

+    p[1] ^= GetUi32(data + 4);

+    p[2] ^= GetUi32(data + 8);

+    p[3] ^= GetUi32(data + 12);

+    

+    Aes_Encode(p + 4, p, p);

+    

+    SetUi32(data,      p[0]);

+    SetUi32(data + 4,  p[1]);

+    SetUi32(data + 8,  p[2]);

+    SetUi32(data + 12, p[3]);

+  }

+}

+

+void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  UInt32 in[4], out[4];

+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)

+  {

+    in[0] = GetUi32(data);

+    in[1] = GetUi32(data + 4);

+    in[2] = GetUi32(data + 8);

+    in[3] = GetUi32(data + 12);

+

+    Aes_Decode(p + 4, out, in);

+

+    SetUi32(data,      p[0] ^ out[0]);

+    SetUi32(data + 4,  p[1] ^ out[1]);

+    SetUi32(data + 8,  p[2] ^ out[2]);

+    SetUi32(data + 12, p[3] ^ out[3]);

+    

+    p[0] = in[0];

+    p[1] = in[1];

+    p[2] = in[2];

+    p[3] = in[3];

+  }

+}

+

+void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  for (; numBlocks != 0; numBlocks--)

+  {

+    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/Aes.h b/C/Aes.h
new file mode 100644
index 0000000..381e979
--- /dev/null
+++ b/C/Aes.h
@@ -0,0 +1,38 @@
+/* Aes.h -- AES encryption / decryption

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

+

+#ifndef __AES_H

+#define __AES_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#define AES_BLOCK_SIZE 16

+

+/* Call AesGenTables one time before other AES functions */

+void AesGenTables(void);

+

+/* UInt32 pointers must be 16-byte aligned */

+

+/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */

+#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)

+

+/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */

+/* keySize = 16 or 24 or 32 (bytes) */

+typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);

+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);

+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);

+

+/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */

+void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */

+/* data - 16-byte aligned pointer to data */

+/* numBlocks - the number of 16-byte blocks in data array */

+typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);

+extern AES_CODE_FUNC g_AesCbc_Encode;

+extern AES_CODE_FUNC g_AesCbc_Decode;

+extern AES_CODE_FUNC g_AesCtr_Code;

+

+EXTERN_C_END

+

+#endif

diff --git a/C/AesOpt.c b/C/AesOpt.c
new file mode 100644
index 0000000..e5d4d26
--- /dev/null
+++ b/C/AesOpt.c
@@ -0,0 +1,184 @@
+/* AesOpt.c -- Intel's AES

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

+

+#include "Precomp.h"

+

+#include "CpuArch.h"

+

+#ifdef MY_CPU_X86_OR_AMD64

+#if _MSC_VER >= 1500

+#define USE_INTEL_AES

+#endif

+#endif

+

+#ifdef USE_INTEL_AES

+

+#include <wmmintrin.h>

+

+void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i m = *p;

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p + 3;

+    m = _mm_xor_si128(m, *data);

+    m = _mm_xor_si128(m, p[2]);

+    do

+    {

+      m = _mm_aesenc_si128(m, w[0]);

+      m = _mm_aesenc_si128(m, w[1]);

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesenc_si128(m, w[0]);

+    m = _mm_aesenclast_si128(m, w[1]);

+    *data = m;

+  }

+  *p = m;

+}

+

+#define NUM_WAYS 3

+

+#define AES_OP_W(op, n) { \

+    const __m128i t = w[n]; \

+    m0 = op(m0, t); \

+    m1 = op(m1, t); \

+    m2 = op(m2, t); \

+    }

+

+#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)

+#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)

+#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)

+#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)

+

+void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i iv = *p;

+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)

+  {

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

+    const __m128i *w = p + numRounds2 * 2;

+    __m128i m0, m1, m2;

+    {

+      const __m128i t = w[2];

+      m0 = _mm_xor_si128(t, data[0]);

+      m1 = _mm_xor_si128(t, data[1]);

+      m2 = _mm_xor_si128(t, data[2]);

+    }

+    numRounds2--;

+    do

+    {

+      AES_DEC(1)

+      AES_DEC(0)

+      w -= 2;

+    }

+    while (--numRounds2 != 0);

+    AES_DEC(1)

+    AES_DEC_LAST(0)

+

+    {

+      __m128i t;

+      t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;

+      t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;

+      t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;

+    }

+  }

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

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

+    const __m128i *w = p + numRounds2 * 2;

+    __m128i m = _mm_xor_si128(w[2], *data);

+    numRounds2--;

+    do

+    {

+      m = _mm_aesdec_si128(m, w[1]);

+      m = _mm_aesdec_si128(m, w[0]);

+      w -= 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesdec_si128(m, w[1]);

+    m = _mm_aesdeclast_si128(m, w[0]);

+

+    m = _mm_xor_si128(m, iv);

+    iv = *data;

+    *data = m;

+  }

+  *p = iv;

+}

+

+void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i ctr = *p;

+  __m128i one;

+  one.m128i_u64[0] = 1;

+  one.m128i_u64[1] = 0;

+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p;

+    __m128i m0, m1, m2;

+    {

+      const __m128i t = w[2];

+      ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);

+      ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);

+      ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);

+    }

+    w += 3;

+    do

+    {

+      AES_ENC(0)

+      AES_ENC(1)

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    AES_ENC(0)

+    AES_ENC_LAST(1)

+    data[0] = _mm_xor_si128(data[0], m0);

+    data[1] = _mm_xor_si128(data[1], m1);

+    data[2] = _mm_xor_si128(data[2], m2);

+  }

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p;

+    __m128i m;

+    ctr = _mm_add_epi64(ctr, one);

+    m = _mm_xor_si128(ctr, p[2]);

+    w += 3;

+    do

+    {

+      m = _mm_aesenc_si128(m, w[0]);

+      m = _mm_aesenc_si128(m, w[1]);

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesenc_si128(m, w[0]);

+    m = _mm_aesenclast_si128(m, w[1]);

+    *data = _mm_xor_si128(*data, m);

+  }

+  *p = ctr;

+}

+

+#else

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCbc_Encode(p, data, numBlocks);

+}

+

+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCbc_Decode(p, data, numBlocks);

+}

+

+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCtr_Code(p, data, numBlocks);

+}

+

+#endif

diff --git a/C/Alloc.c b/C/Alloc.c
old mode 100755
new mode 100644
index bb24a77..8e2839a
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,7 +1,7 @@
 /* Alloc.c -- Memory allocation functions

-2008-09-24

-Igor Pavlov

-Public domain */

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

+

+#include "Precomp.h"

 

 #ifdef _WIN32

 #include <windows.h>

diff --git a/C/Alloc.h b/C/Alloc.h
old mode 100755
new mode 100644
diff --git a/C/Android.mk b/C/Android.mk
new file mode 100644
index 0000000..539bbbc
--- /dev/null
+++ b/C/Android.mk
@@ -0,0 +1,57 @@
+# Copyright 2015 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+lzma_files := \
+  7zAlloc.c \
+  7zArcIn.c \
+  7zBuf2.c \
+  7zBuf.c \
+  7zCrc.c \
+  7zCrcOpt.c \
+  7zDec.c \
+  7zFile.c \
+  7zStream.c \
+  Aes.c \
+  AesOpt.c \
+  Alloc.c \
+  Bcj2.c \
+  Bra86.c \
+  Bra.c \
+  BraIA64.c \
+  CpuArch.c \
+  Delta.c \
+  LzFind.c \
+  Lzma2Dec.c \
+  Lzma2Enc.c \
+  Lzma86Dec.c \
+  Lzma86Enc.c \
+  LzmaDec.c \
+  LzmaEnc.c \
+  LzmaLib.c \
+  Ppmd7.c \
+  Ppmd7Dec.c \
+  Ppmd7Enc.c \
+  Sha256.c \
+  Sort.c \
+  Xz.c \
+  XzCrc64.c \
+  XzCrc64Opt.c \
+  XzDec.c \
+  XzEnc.c \
+  XzIn.c
+
+LOCAL_MODULE := liblzma
+LOCAL_CFLAGS := -D_7ZIP_ST
+LOCAL_SRC_FILES := $(lzma_files)
+LOCAL_MULTILIB := both
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblzma
+LOCAL_CFLAGS := -D_7ZIP_ST
+LOCAL_SRC_FILES := $(lzma_files)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/C/Bcj2.c b/C/Bcj2.c
old mode 100755
new mode 100644
index 474bdd4..ac4ca0c
--- a/C/Bcj2.c
+++ b/C/Bcj2.c
@@ -1,6 +1,8 @@
 /* Bcj2.c -- Converter for x86 code (BCJ2)

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

 

+#include "Precomp.h"

+

 #include "Bcj2.h"

 

 #ifdef _LZMA_PROB32

diff --git a/C/Bcj2.h b/C/Bcj2.h
old mode 100755
new mode 100644
index d9d857b..e8304c5
--- a/C/Bcj2.h
+++ b/C/Bcj2.h
@@ -1,14 +1,12 @@
 /* Bcj2.h -- Converter for x86 code (BCJ2)

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

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

 

 #ifndef __BCJ2_H

 #define __BCJ2_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 /*

 Conditions:

@@ -31,8 +29,6 @@
     const Byte *buf3, SizeT size3,

     Byte *outBuf, SizeT outSize);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/Bra.c b/C/Bra.c
old mode 100755
new mode 100644
index 2a0f147..976810c
--- a/C/Bra.c
+++ b/C/Bra.c
@@ -1,6 +1,8 @@
 /* Bra.c -- Converters for RISC code

 2010-04-16 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include "Bra.h"

 

 SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

diff --git a/C/Bra.h b/C/Bra.h
old mode 100755
new mode 100644
index 9c91e33..aba8dce
--- a/C/Bra.h
+++ b/C/Bra.h
@@ -1,14 +1,12 @@
 /* Bra.h -- Branch converters for executables

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

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

 

 #ifndef __BRA_H

 #define __BRA_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 /*

 These functions convert relative addresses to absolute addresses

@@ -61,8 +59,6 @@
 SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

 SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/Bra86.c b/C/Bra86.c
old mode 100755
new mode 100644
index 93566cb..8dd3ed4
--- a/C/Bra86.c
+++ b/C/Bra86.c
@@ -1,85 +1,82 @@
 /* Bra86.c -- Converter for x86 code (BCJ)

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

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

+

+#include "Precomp.h"

 

 #include "Bra.h"

 

-#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)

-

-const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};

-const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};

+#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)

 

 SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)

 {

-  SizeT bufferPos = 0, prevPosT;

-  UInt32 prevMask = *state & 0x7;

+  SizeT pos = 0;

+  UInt32 mask = *state & 7;

   if (size < 5)

     return 0;

+  size -= 4;

   ip += 5;

-  prevPosT = (SizeT)0 - 1;

 

   for (;;)

   {

-    Byte *p = data + bufferPos;

-    Byte *limit = data + size - 4;

+    Byte *p = data + pos;

+    const Byte *limit = data + size;

     for (; p < limit; p++)

       if ((*p & 0xFE) == 0xE8)

         break;

-    bufferPos = (SizeT)(p - data);

-    if (p >= limit)

-      break;

-    prevPosT = bufferPos - prevPosT;

-    if (prevPosT > 3)

-      prevMask = 0;

-    else

+

     {

-      prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;

-      if (prevMask != 0)

+      SizeT d = (SizeT)(p - data - pos);

+      pos = (SizeT)(p - data);

+      if (p >= limit)

       {

-        Byte b = p[4 - kMaskToBitNumber[prevMask]];

-        if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))

+        *state = (d > 2 ? 0 : mask >> (unsigned)d);

+        return pos;

+      }

+      if (d > 2)

+        mask = 0;

+      else

+      {

+        mask >>= (unsigned)d;

+        if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))

         {

-          prevPosT = bufferPos;

-          prevMask = ((prevMask << 1) & 0x7) | 1;

-          bufferPos++;

+          mask = (mask >> 1) | 4;

+          pos++;

           continue;

         }

       }

     }

-    prevPosT = bufferPos;

 

     if (Test86MSByte(p[4]))

     {

-      UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);

-      UInt32 dest;

-      for (;;)

+      UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);

+      UInt32 cur = ip + (UInt32)pos;

+      pos += 5;

+      if (encoding)

+        v += cur;

+      else

+        v -= cur;

+      if (mask != 0)

       {

-        Byte b;

-        int index;

-        if (encoding)

-          dest = (ip + (UInt32)bufferPos) + src;

-        else

-          dest = src - (ip + (UInt32)bufferPos);

-        if (prevMask == 0)

-          break;

-        index = kMaskToBitNumber[prevMask] * 8;

-        b = (Byte)(dest >> (24 - index));

-        if (!Test86MSByte(b))

-          break;

-        src = dest ^ ((1 << (32 - index)) - 1);

+        unsigned sh = (mask & 6) << 2;

+        if (Test86MSByte((Byte)(v >> sh)))

+        {

+          v ^= (((UInt32)0x100 << sh) - 1);

+          if (encoding)

+            v += cur;

+          else

+            v -= cur;

+        }

+        mask = 0;

       }

-      p[4] = (Byte)(~(((dest >> 24) & 1) - 1));

-      p[3] = (Byte)(dest >> 16);

-      p[2] = (Byte)(dest >> 8);

-      p[1] = (Byte)dest;

-      bufferPos += 5;

+      p[1] = (Byte)v;

+      p[2] = (Byte)(v >> 8);

+      p[3] = (Byte)(v >> 16);

+      p[4] = (Byte)(0 - ((v >> 24) & 1));

     }

     else

     {

-      prevMask = ((prevMask << 1) & 0x7) | 1;

-      bufferPos++;

+      mask = (mask >> 1) | 4;

+      pos++;

     }

   }

-  prevPosT = bufferPos - prevPosT;

-  *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));

-  return bufferPos;

 }

diff --git a/C/BraIA64.c b/C/BraIA64.c
old mode 100755
new mode 100644
index f359f16..813830c
--- a/C/BraIA64.c
+++ b/C/BraIA64.c
@@ -1,5 +1,7 @@
 /* BraIA64.c -- Converter for IA-64 code

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

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

+

+#include "Precomp.h"

 

 #include "Bra.h"

 

diff --git a/C/Compiler.h b/C/Compiler.h
new file mode 100644
index 0000000..0f76670
--- /dev/null
+++ b/C/Compiler.h
@@ -0,0 +1,28 @@
+/* Compiler.h -- Compiler ypes

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

+

+#ifndef __7Z_COMPILER_H

+#define __7Z_COMPILER_H

+

+#ifdef _MSC_VER

+

+  #ifdef UNDER_CE

+    #define RPC_NO_WINDOWS_H

+    /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */

+    #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union

+    #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int

+  #endif

+

+  #if _MSC_VER >= 1300

+    #pragma warning(disable : 4996) // This function or variable may be unsafe

+  #else

+    #pragma warning(disable : 4511) // copy constructor could not be generated

+    #pragma warning(disable : 4512) // assignment operator could not be generated

+    #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

+  #endif

+

+#endif

+

+#endif

diff --git a/C/CpuArch.c b/C/CpuArch.c
old mode 100755
new mode 100644
index 36e7680..f8ac0c2
--- a/C/CpuArch.c
+++ b/C/CpuArch.c
@@ -1,5 +1,7 @@
 /* CpuArch.c -- CPU specific code

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

+2012-05-29: Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include "CpuArch.h"

 

@@ -9,6 +11,10 @@
 #define USE_ASM

 #endif

 

+#if !defined(USE_ASM) && _MSC_VER >= 1500

+#include <intrin.h>

+#endif

+

 #if defined(USE_ASM) && !defined(MY_CPU_AMD64)

 static UInt32 CheckFlag(UInt32 flag)

 {

@@ -73,9 +79,17 @@
   #else

 

   __asm__ __volatile__ (

+  #if defined(MY_CPU_X86) && defined(__PIC__)

+    "mov %%ebx, %%edi;"

+    "cpuid;"

+    "xchgl %%ebx, %%edi;"

+    : "=a" (*a) ,

+      "=D" (*b) ,

+  #else

     "cpuid"

     : "=a" (*a) ,

       "=b" (*b) ,

+  #endif

       "=c" (*c) ,

       "=d" (*d)

     : "0" (function)) ;

@@ -135,7 +149,14 @@
   firm = x86cpuid_GetFirm(&p);

   switch (firm)

   {

-    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));

+    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 */

+        )));

     case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));

     case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));

   }

@@ -143,6 +164,7 @@
 }

 

 #if !defined(MY_CPU_AMD64) && defined(_WIN32)

+#include <windows.h>

 static Bool CPU_Sys_Is_SSE_Supported()

 {

   OSVERSIONINFO vi;

diff --git a/C/CpuArch.h b/C/CpuArch.h
old mode 100755
new mode 100644
index 0a709bb..2316205
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -1,10 +1,10 @@
 /* CpuArch.h -- CPU specific code

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

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

 

 #ifndef __CPU_ARCH_H

 #define __CPU_ARCH_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

@@ -52,7 +52,7 @@
 #define MY_CPU_LE

 #endif

 

-#if defined(__BIG_ENDIAN__)

+#if defined(__BIG_ENDIAN__) || defined(__m68k__) ||  defined(__ARMEB__) || defined(__MIPSEB__)

 #define MY_CPU_BE

 #endif

 

@@ -62,9 +62,9 @@
 

 #ifdef MY_CPU_LE_UNALIGN

 

-#define GetUi16(p) (*(const UInt16 *)(p))

-#define GetUi32(p) (*(const UInt32 *)(p))

-#define GetUi64(p) (*(const UInt64 *)(p))

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

@@ -99,6 +99,8 @@
 

 #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)

 

+#include <stdlib.h>

+

 #pragma intrinsic(_byteswap_ulong)

 #pragma intrinsic(_byteswap_uint64)

 #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))

@@ -116,7 +118,7 @@
 

 #endif

 

-#define GetBe16(p) (((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

diff --git a/C/Delta.c b/C/Delta.c
old mode 100755
new mode 100644
index 93c93a1..6cbbe46
--- a/C/Delta.c
+++ b/C/Delta.c
@@ -1,6 +1,8 @@
 /* Delta.c -- Delta converter

 2009-05-26 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include "Delta.h"

 

 void Delta_Init(Byte *state)

diff --git a/C/Delta.h b/C/Delta.h
old mode 100755
new mode 100644
index 776cd45..e59d5a2
--- a/C/Delta.h
+++ b/C/Delta.h
@@ -1,14 +1,12 @@
 /* Delta.h -- Delta converter

-2009-04-15 : Igor Pavlov : Public domain */

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

 

 #ifndef __DELTA_H

 #define __DELTA_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 #define DELTA_STATE_SIZE 256

 

@@ -16,8 +14,6 @@
 void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);

 void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/LzFind.c b/C/LzFind.c
old mode 100755
new mode 100644
index f6c9e66..df79867
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,6 +1,8 @@
 /* LzFind.c -- Match finder for LZ algorithms

 2009-04-22 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include <string.h>

 

 #include "LzFind.h"

diff --git a/C/LzFind.h b/C/LzFind.h
old mode 100755
new mode 100644
index 7ebdfa4..bad5000
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,14 +1,12 @@
 /* LzFind.h -- Match finder for LZ algorithms

-2009-04-22 : Igor Pavlov : Public domain */

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

 

 #ifndef __LZ_FIND_H

 #define __LZ_FIND_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 typedef UInt32 CLzRef;

 

@@ -108,8 +106,6 @@
 void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

 void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/LzFindMt.c b/C/LzFindMt.c
old mode 100755
new mode 100644
index db95590..5356d4a
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,7 @@
 /* LzFindMt.c -- multithreaded Match finder for LZ algorithms

-2009-09-20 : Igor Pavlov : Public domain */

+2014-12-29 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include "LzHash.h"

 

@@ -97,7 +99,7 @@
 

 #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }

 

-static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)

+static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)

 {

   if (p->wasCreated)

     return SZ_OK;

@@ -119,7 +121,7 @@
   return SZ_OK;

 }

 

-static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)

+static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)

 {

   SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);

   if (res != SZ_OK)

@@ -451,13 +453,12 @@
 #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)

 #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)

 

-static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }

-static unsigned MY_STD_CALL BtThreadFunc2(void *p)

+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }

+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)

 {

   Byte allocaDummy[0x180];

-  int i = 0;

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

-    allocaDummy[i] = (Byte)i;

+  allocaDummy[0] = 0;

+  allocaDummy[1] = allocaDummy[0];

   BtThreadFunc((CMatchFinderMt *)p);

   return 0;

 }

diff --git a/C/LzFindMt.h b/C/LzFindMt.h
old mode 100755
new mode 100644
index 17ed237..320d87c
--- a/C/LzFindMt.h
+++ b/C/LzFindMt.h
@@ -1,5 +1,5 @@
 /* LzFindMt.h -- multithreaded Match finder for LZ algorithms

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

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

 

 #ifndef __LZ_FIND_MT_H

 #define __LZ_FIND_MT_H

@@ -7,9 +7,7 @@
 #include "LzFind.h"

 #include "Threads.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 #define kMtHashBlockSize (1 << 13)

 #define kMtHashNumBlocks (1 << 3)

@@ -98,8 +96,6 @@
 void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);

 void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/LzHash.h b/C/LzHash.h
old mode 100755
new mode 100644
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
old mode 100755
new mode 100644
index 8f24067..ed91619
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -1,8 +1,10 @@
 /* Lzma2Dec.c -- LZMA2 Decoder

-2009-05-03 : Igor Pavlov : Public domain */

+2010-12-15 : Igor Pavlov : Public domain */

 

 /* #define SHOW_DEBUG_INFO */

 

+#include "Precomp.h"

+

 #ifdef SHOW_DEBUG_INFO

 #include <stdio.h>

 #endif

@@ -330,27 +332,21 @@
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)

 {

-  CLzma2Dec decoder;

+  CLzma2Dec p;

   SRes res;

   SizeT outSize = *destLen, inSize = *srcLen;

-  Byte props[LZMA_PROPS_SIZE];

-

-  Lzma2Dec_Construct(&decoder);

-

   *destLen = *srcLen = 0;

   *status = LZMA_STATUS_NOT_SPECIFIED;

-  decoder.decoder.dic = dest;

-  decoder.decoder.dicBufSize = outSize;

-

-  RINOK(Lzma2Dec_GetOldProps(prop, props));

-  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));

-  

+  Lzma2Dec_Construct(&p);

+  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));

+  p.decoder.dic = dest;

+  p.decoder.dicBufSize = outSize;

+  Lzma2Dec_Init(&p);

   *srcLen = inSize;

-  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);

-  *destLen = decoder.decoder.dicPos;

+  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);

+  *destLen = p.decoder.dicPos;

   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

     res = SZ_ERROR_INPUT_EOF;

-

-  LzmaDec_FreeProbs(&decoder.decoder, alloc);

+  Lzma2Dec_FreeProbs(&p, alloc);

   return res;

 }

diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
old mode 100755
new mode 100644
index 827698d..9254523
--- a/C/Lzma2Dec.h
+++ b/C/Lzma2Dec.h
@@ -1,14 +1,12 @@
 /* Lzma2Dec.h -- LZMA2 Decoder

-2009-05-03 : Igor Pavlov : Public domain */

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

 

 #ifndef __LZMA2_DEC_H

 #define __LZMA2_DEC_H

 

 #include "LzmaDec.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 /* ---------- State Interface ---------- */

 

@@ -77,8 +75,6 @@
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
old mode 100755
new mode 100644
index 35f6ed7..34a97f3
--- a/C/Lzma2Enc.c
+++ b/C/Lzma2Enc.c
@@ -1,5 +1,7 @@
 /* Lzma2Enc.c -- LZMA2 Encoder

-2010-09-24 : Igor Pavlov : Public domain */

+2012-06-19 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 /* #include <stdio.h> */

 #include <string.h>

@@ -216,8 +218,7 @@
     t3 = t1n * t2;

 

   p->lzmaProps.numThreads = t1;

-  p->numBlockThreads = t2;

-  p->numTotalThreads = t3;

+

   LzmaEncProps_Normalize(&p->lzmaProps);

 

   if (p->blockSize == 0)

@@ -231,6 +232,21 @@
     if (blockSize < dictSize) blockSize = dictSize;

     p->blockSize = (size_t)blockSize;

   }

+  if (t2 > 1)

+  {

+    UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;

+    if (temp > p->lzmaProps.reduceSize)

+    {

+      UInt64 numBlocks = temp / p->blockSize;

+      if (numBlocks < t2)

+      {

+        t2 = (UInt32)numBlocks;

+        t3 = t1 * t2;

+      }

+    }

+  }

+  p->numBlockThreads = t2;

+  p->numTotalThreads = t3;

 }

 

 static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)

diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h
old mode 100755
new mode 100644
index 38830e5..061178a
--- a/C/Lzma2Enc.h
+++ b/C/Lzma2Enc.h
@@ -1,14 +1,12 @@
 /* Lzma2Enc.h -- LZMA2 Encoder

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

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

 

 #ifndef __LZMA2_ENC_H

 #define __LZMA2_ENC_H

 

 #include "LzmaEnc.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 typedef struct

 {

@@ -59,8 +57,6 @@
     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

 */

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/Lzma86.h b/C/Lzma86.h
old mode 100755
new mode 100644
index 6425bb8..83057e5
--- a/C/Lzma86.h
+++ b/C/Lzma86.h
@@ -1,10 +1,10 @@
 /* Lzma86.h -- LZMA + x86 (BCJ) Filter

-2009-08-14 : Igor Pavlov : Public domain */

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

 

 #ifndef __LZMA86_H

 #define __LZMA86_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

diff --git a/C/Lzma86Dec.c b/C/Lzma86Dec.c
old mode 100755
new mode 100644
diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c
old mode 100755
new mode 100644
index a29c605..41b488c
--- a/C/Lzma86Enc.c
+++ b/C/Lzma86Enc.c
@@ -99,7 +99,7 @@
         }

       }

     }

-    dest[0] = (bestIsFiltered ? 1 : 0);

+    dest[0] = (Byte)(bestIsFiltered ? 1 : 0);

     *destLen = LZMA86_HEADER_SIZE + minSize;

   }

   if (useFilter)

diff --git a/C/LzmaDec.c b/C/LzmaDec.c
old mode 100755
new mode 100644
index 4fdc11d..38cd9d6
--- a/C/LzmaDec.c
+++ b/C/LzmaDec.c
@@ -1,5 +1,7 @@
 /* LzmaDec.c -- LZMA Decoder

-2009-09-20 : Igor Pavlov : Public domain */

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

+

+#include "Precomp.h"

 

 #include "LzmaDec.h"

 

@@ -44,6 +46,13 @@
   i -= 0x40; }

 #endif

 

+#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)

+#define MATCHED_LITER_DEC \

+  matchByte <<= 1; \

+  bit = (matchByte & offs); \

+  probLit = prob + offs + bit + symbol; \

+  GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)

+

 #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }

 

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

@@ -171,24 +180,47 @@
       {

         state -= (state < 4) ? state : 3;

         symbol = 1;

-        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);

+        #ifdef _LZMA_SIZE_OPT

+        do { NORMAL_LITER_DEC } while (symbol < 0x100);

+        #else

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        #endif

       }

       else

       {

-        unsigned matchByte = p->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;

+        #ifdef _LZMA_SIZE_OPT

         do

         {

           unsigned bit;

           CLzmaProb *probLit;

-          matchByte <<= 1;

-          bit = (matchByte & offs);

-          probLit = prob + offs + bit + symbol;

-          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)

+          MATCHED_LITER_DEC

         }

         while (symbol < 0x100);

+        #else

+        {

+          unsigned bit;

+          CLzmaProb *probLit;

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+        }

+        #endif

       }

       dic[dicPos++] = (Byte)symbol;

       processedPos++;

@@ -442,8 +474,9 @@
 

     p->processedPos += len;

     p->remainLen -= len;

-    while (len-- != 0)

+    while (len != 0)

     {

+      len--;

       dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

       dicPos++;

     }

@@ -972,28 +1005,21 @@
 {

   CLzmaDec p;

   SRes res;

-  SizeT inSize = *srcLen;

-  SizeT outSize = *destLen;

-  *srcLen = *destLen = 0;

+  SizeT outSize = *destLen, inSize = *srcLen;

+  *destLen = *srcLen = 0;

+  *status = LZMA_STATUS_NOT_SPECIFIED;

   if (inSize < RC_INIT_SIZE)

     return SZ_ERROR_INPUT_EOF;

-

   LzmaDec_Construct(&p);

-  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);

-  if (res != 0)

-    return res;

+  RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));

   p.dic = dest;

   p.dicBufSize = outSize;

-

   LzmaDec_Init(&p);

-  

   *srcLen = inSize;

   res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);

-

+  *destLen = p.dicPos;

   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

     res = SZ_ERROR_INPUT_EOF;

-

-  (*destLen) = p.dicPos;

   LzmaDec_FreeProbs(&p, alloc);

   return res;

 }

diff --git a/C/LzmaDec.h b/C/LzmaDec.h
old mode 100755
new mode 100644
index 6741a64..2633abe
--- a/C/LzmaDec.h
+++ b/C/LzmaDec.h
@@ -1,14 +1,12 @@
 /* LzmaDec.h -- LZMA Decoder

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

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

 

 #ifndef __LZMA_DEC_H

 #define __LZMA_DEC_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 /* #define _LZMA_PROB32 */

 /* _LZMA_PROB32 can increase the speed on some CPUs,

@@ -224,8 +222,6 @@
     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,

     ELzmaStatus *status, ISzAlloc *alloc);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
old mode 100755
new mode 100644
index 9e6dbdb..40ee6a4
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,7 @@
 /* LzmaEnc.c -- LZMA Encoder

-2010-04-16 : Igor Pavlov : Public domain */

+2014-12-29 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include <string.h>

 

@@ -18,7 +20,7 @@
 #endif

 

 #ifdef SHOW_STAT

-static int ttt = 0;

+static unsigned g_STAT_OFFSET = 0;

 #endif

 

 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)

@@ -46,6 +48,7 @@
 {

   p->level = 5;

   p->dictSize = p->mc = 0;

+  p->reduceSize = (UInt64)(Int64)-1;

   p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;

   p->writeEndMark = 0;

 }

@@ -56,6 +59,15 @@
   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)

+  {

+    unsigned i;

+    for (i = 11; i <= 30; i++)

+    {

+      if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }

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

@@ -329,7 +341,6 @@
 

   SRes result;

   UInt32 dictSize;

-  UInt32 matchFinderCycles;

 

   int needInit;

 

@@ -398,7 +409,6 @@
       props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))

     return SZ_ERROR_PARAM;

   p->dictSize = props.dictSize;

-  p->matchFinderCycles = props.mc;

   {

     unsigned fb = props.fb;

     if (fb < 5)

@@ -508,7 +518,7 @@
 

 static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)

 {

-  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)

+  if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)

   {

     Byte temp = p->cache;

     do

@@ -534,7 +544,7 @@
     RangeEnc_ShiftLow(p);

 }

 

-static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)

+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)

 {

   do

   {

@@ -803,9 +813,10 @@
 static void MovePos(CLzmaEnc *p, UInt32 num)

 {

   #ifdef SHOW_STAT

-  ttt += num;

+  g_STAT_OFFSET += num;

   printf("\n MovePos %d", num);

   #endif

+  

   if (num != 0)

   {

     p->additionalOffset += num;

@@ -818,15 +829,17 @@
   UInt32 lenRes = 0, numPairs;

   p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);

   numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);

+  

   #ifdef SHOW_STAT

-  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);

-  ttt++;

+  printf("\n i = %d numPairs = %d    ", 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]);

   }

   #endif

+  

   if (numPairs > 0)

   {

     lenRes = p->matches[numPairs - 2];

@@ -1897,12 +1910,10 @@
 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)

 {

   UInt32 beforeSize = kNumOpts;

-  Bool btMode;

   if (!RangeEnc_Alloc(&p->rc, alloc))

     return SZ_ERROR_MEM;

-  btMode = (p->matchFinderBase.btMode != 0);

   #ifndef _7ZIP_ST

-  p->mtMode = (p->multiThread && !p->fastMode && btMode);

+  p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));

   #endif

 

   {

@@ -2157,9 +2168,8 @@
 

   #ifndef _7ZIP_ST

   Byte allocaDummy[0x300];

-  int i = 0;

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

-    allocaDummy[i] = (Byte)i;

+  allocaDummy[0] = 0;

+  allocaDummy[1] = allocaDummy[0];

   #endif

 

   for (;;)

diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h
old mode 100755
new mode 100644
index 999f5af..c2806b4
--- a/C/LzmaEnc.h
+++ b/C/LzmaEnc.h
@@ -1,14 +1,12 @@
 /*  LzmaEnc.h -- LZMA Encoder

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

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

 

 #ifndef __LZMA_ENC_H

 #define __LZMA_ENC_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 #define LZMA_PROPS_SIZE 5

 

@@ -18,6 +16,8 @@
   UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version

                       (1 << 12) <= dictSize <= (1 << 30) for 64-bit version

                        default = (1 << 24) */

+  UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.

+                        Encoder uses this value to reduce dictionary size */

   int lc;          /* 0 <= lc <= 8, default = 3 */

   int lp;          /* 0 <= lp <= 4, default = 0 */

   int pb;          /* 0 <= pb <= 4, default = 2 */

@@ -73,8 +73,6 @@
     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,

     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/LzmaLib.c b/C/LzmaLib.c
old mode 100755
new mode 100644
diff --git a/C/LzmaLib.h b/C/LzmaLib.h
old mode 100755
new mode 100644
index 55e1e11..5c35e53
--- a/C/LzmaLib.h
+++ b/C/LzmaLib.h
@@ -1,14 +1,12 @@
 /* LzmaLib.h -- LZMA library interface

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

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

 

 #ifndef __LZMA_LIB_H

 #define __LZMA_LIB_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

 

 #define MY_STDAPI int MY_STD_CALL

 

@@ -128,8 +126,6 @@
 MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,

   const unsigned char *props, size_t propsSize);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/MtCoder.c b/C/MtCoder.c
old mode 100755
new mode 100644
index 9f0d268..303b435
--- a/C/MtCoder.c
+++ b/C/MtCoder.c
@@ -1,6 +1,8 @@
 /* MtCoder.c -- Multi-thread Coder

 2010-09-24 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include <stdio.h>

 

 #include "MtCoder.h"

diff --git a/C/MtCoder.h b/C/MtCoder.h
old mode 100755
new mode 100644
diff --git a/C/Ppmd.h b/C/Ppmd.h
old mode 100755
new mode 100644
index 14344a7..25ce2d2
--- a/C/Ppmd.h
+++ b/C/Ppmd.h
@@ -1,11 +1,10 @@
 /* Ppmd.h -- PPMD codec common code

-2010-03-12 : Igor Pavlov : Public domain

+2013-01-18 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

 #ifndef __PPMD_H

 #define __PPMD_H

 

-#include "Types.h"

 #include "CpuArch.h"

 

 EXTERN_C_BEGIN

@@ -29,6 +28,9 @@
 #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)

 #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)

 

+#pragma pack(push, 1)

+/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */

+

 /* SEE-contexts for PPM-contexts with masked symbols */

 typedef struct

 {

@@ -48,6 +50,8 @@
   UInt16 SuccessorHigh;

 } CPpmd_State;

 

+#pragma pack(pop)

+

 typedef

   #ifdef PPMD_32BIT

     CPpmd_State *

diff --git a/C/Ppmd7.c b/C/Ppmd7.c
old mode 100755
new mode 100644
index 4b160cf..798c118
--- a/C/Ppmd7.c
+++ b/C/Ppmd7.c
@@ -2,6 +2,8 @@
 2010-03-12 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

+#include "Precomp.h"

+

 #include <memory.h>

 

 #include "Ppmd7.h"

diff --git a/C/Ppmd7.h b/C/Ppmd7.h
old mode 100755
new mode 100644
diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
old mode 100755
new mode 100644
index d6608e8..3d01d76
--- a/C/Ppmd7Dec.c
+++ b/C/Ppmd7Dec.c
@@ -2,6 +2,8 @@
 2010-03-12 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

+#include "Precomp.h"

+

 #include "Ppmd7.h"

 

 #define kTopValue (1 << 24)

diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
old mode 100755
new mode 100644
index b1fecae..d82ea90
--- a/C/Ppmd7Enc.c
+++ b/C/Ppmd7Enc.c
@@ -2,6 +2,8 @@
 2010-03-12 : Igor Pavlov : Public domain

 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

 

+#include "Precomp.h"

+

 #include "Ppmd7.h"

 

 #define kTopValue (1 << 24)

diff --git a/C/Precomp.h b/C/Precomp.h
new file mode 100644
index 0000000..edb5814
--- /dev/null
+++ b/C/Precomp.h
@@ -0,0 +1,10 @@
+/* Precomp.h -- StdAfx

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

+

+#ifndef __7Z_PRECOMP_H

+#define __7Z_PRECOMP_H

+

+#include "Compiler.h"

+/* #include "7zTypes.h" */

+

+#endif

diff --git a/C/RotateDefs.h b/C/RotateDefs.h
old mode 100755
new mode 100644
index ff9b722..ad7d164
--- a/C/RotateDefs.h
+++ b/C/RotateDefs.h
@@ -1,5 +1,5 @@
 /* RotateDefs.h -- Rotate functions

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

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

 

 #ifndef __ROTATE_DEFS_H

 #define __ROTATE_DEFS_H

@@ -7,6 +7,12 @@
 #ifdef _MSC_VER

 

 #include <stdlib.h>

+

+// #if (_MSC_VER >= 1200)

+#pragma intrinsic(_rotl)

+#pragma intrinsic(_rotr)

+// #endif

+

 #define rotlFixed(x, n) _rotl((x), (n))

 #define rotrFixed(x, n) _rotr((x), (n))

 

diff --git a/C/Sha256.c b/C/Sha256.c
old mode 100755
new mode 100644
index cfb9eac..91208d3
--- a/C/Sha256.c
+++ b/C/Sha256.c
@@ -2,6 +2,8 @@
 2010-06-11 : Igor Pavlov : Public domain

 This code is based on public domain code from Wei Dai's Crypto++ library. */

 

+#include "Precomp.h"

+

 #include "RotateDefs.h"

 #include "Sha256.h"

 

diff --git a/C/Sha256.h b/C/Sha256.h
old mode 100755
new mode 100644
index 26d1e3a..7f17ccf
--- a/C/Sha256.h
+++ b/C/Sha256.h
@@ -1,10 +1,10 @@
 /* Sha256.h -- SHA-256 Hash

-2010-06-11 : Igor Pavlov : Public domain */

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

 

 #ifndef __CRYPTO_SHA256_H

 #define __CRYPTO_SHA256_H

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

diff --git a/C/Sort.c b/C/Sort.c
new file mode 100644
index 0000000..73dcbf0
--- /dev/null
+++ b/C/Sort.c
@@ -0,0 +1,141 @@
+/* Sort.c -- Sort functions

+2014-04-05 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "Sort.h"

+

+#define HeapSortDown(p, k, size, temp) \

+  { for (;;) { \

+    size_t s = (k << 1); \

+    if (s > size) break; \

+    if (s < size && p[s + 1] > p[s]) s++; \

+    if (temp >= p[s]) break; \

+    p[k] = p[s]; k = s; \

+  } p[k] = temp; }

+

+void HeapSort(UInt32 *p, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt32 temp = p[i];

+      size_t k = i;

+      HeapSortDown(p, k, size, temp)

+    }

+    while (--i != 0);

+  }

+  /*

+  do

+  {

+    size_t k = 1;

+    UInt32 temp = p[size];

+    p[size--] = p[1];

+    HeapSortDown(p, k, size, temp)

+  }

+  while (size > 1);

+  */

+  while (size > 3)

+  {

+    UInt32 temp = p[size];

+    size_t k = (p[3] > p[2]) ? 3 : 2;

+    p[size--] = p[1];

+    p[1] = p[k];

+    HeapSortDown(p, k, size, temp)

+  }

+  {

+    UInt32 temp = p[size];

+    p[size] = p[1];

+    if (size > 2 && p[2] < temp)

+    {

+      p[1] = p[2];

+      p[2] = temp;

+    }

+    else

+      p[1] = temp;

+  }

+}

+

+void HeapSort64(UInt64 *p, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt64 temp = p[i];

+      size_t k = i;

+      HeapSortDown(p, k, size, temp)

+    }

+    while (--i != 0);

+  }

+  /*

+  do

+  {

+    size_t k = 1;

+    UInt64 temp = p[size];

+    p[size--] = p[1];

+    HeapSortDown(p, k, size, temp)

+  }

+  while (size > 1);

+  */

+  while (size > 3)

+  {

+    UInt64 temp = p[size];

+    size_t k = (p[3] > p[2]) ? 3 : 2;

+    p[size--] = p[1];

+    p[1] = p[k];

+    HeapSortDown(p, k, size, temp)

+  }

+  {

+    UInt64 temp = p[size];

+    p[size] = p[1];

+    if (size > 2 && p[2] < temp)

+    {

+      p[1] = p[2];

+      p[2] = temp;

+    }

+    else

+      p[1] = temp;

+  }

+}

+

+/*

+#define HeapSortRefDown(p, vals, n, size, temp) \

+  { size_t k = n; UInt32 val = vals[temp]; for (;;) { \

+    size_t s = (k << 1); \

+    if (s > size) break; \

+    if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \

+    if (val >= vals[p[s]]) break; \

+    p[k] = p[s]; k = s; \

+  } p[k] = temp; }

+

+void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt32 temp = p[i];

+      HeapSortRefDown(p, vals, i, size, temp);

+    }

+    while (--i != 0);

+  }

+  do

+  {

+    UInt32 temp = p[size];

+    p[size--] = p[1];

+    HeapSortRefDown(p, vals, 1, size, temp);

+  }

+  while (size > 1);

+}

+*/

diff --git a/C/Sort.h b/C/Sort.h
new file mode 100644
index 0000000..7209d78
--- /dev/null
+++ b/C/Sort.h
@@ -0,0 +1,18 @@
+/* Sort.h -- Sort functions

+2014-04-05 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_SORT_H

+#define __7Z_SORT_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+void HeapSort(UInt32 *p, size_t size);

+void HeapSort64(UInt64 *p, size_t size);

+

+/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Threads.c b/C/Threads.c
old mode 100755
new mode 100644
index 4be44fb..18ba1e8
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,5 +1,7 @@
 /* Threads.c -- multithreading library

-2009-09-20 : Igor Pavlov : Public domain */

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

+

+#include "Precomp.h"

 

 #ifndef _WIN32_WCE

 #include <process.h>

@@ -29,14 +31,21 @@
 

 WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)

 {

-  unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */

-  *p =

-    #ifdef UNDER_CE

-    CreateThread(0, 0, func, param, 0, &threadId);

-    #else

-    (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);

-    #endif

-    /* maybe we must use errno here, but probably GetLastError() is also OK. */

+  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */

+  

+  #ifdef UNDER_CE

+  

+  DWORD threadId;

+  *p = CreateThread(0, 0, func, param, 0, &threadId);

+

+  #else

+

+  unsigned threadId;

+  *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);

+   

+  #endif

+

+  /* maybe we must use errno here, but probably GetLastError() is also OK. */

   return HandleToWRes(*p);

 }

 

diff --git a/C/Threads.h b/C/Threads.h
old mode 100755
new mode 100644
index 6a7afa8..e927208
--- a/C/Threads.h
+++ b/C/Threads.h
@@ -1,15 +1,17 @@
 /* Threads.h -- multithreading library

-2009-03-27 : Igor Pavlov : Public domain */

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

 

 #ifndef __7Z_THREADS_H

 #define __7Z_THREADS_H

 

-#include "Types.h"

-

-#ifdef __cplusplus

-extern "C" {

+#ifdef _WIN32

+#include <windows.h>

 #endif

 

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

 WRes HandlePtr_Close(HANDLE *h);

 WRes Handle_WaitObject(HANDLE h);

 

@@ -18,7 +20,15 @@
 #define Thread_WasCreated(p) (*(p) != NULL)

 #define Thread_Close(p) HandlePtr_Close(p)

 #define Thread_Wait(p) Handle_WaitObject(*(p))

-typedef unsigned THREAD_FUNC_RET_TYPE;

+

+typedef

+#ifdef UNDER_CE

+  DWORD

+#else

+  unsigned

+#endif

+  THREAD_FUNC_RET_TYPE;

+

 #define THREAD_FUNC_CALL_TYPE MY_STD_CALL

 #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE

 typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);

@@ -52,8 +62,6 @@
 #define CriticalSection_Enter(p) EnterCriticalSection(p)

 #define CriticalSection_Leave(p) LeaveCriticalSection(p)

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
old mode 100755
new mode 100644
index 9f5806b..73122f7
--- 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 /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /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 BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -50,7 +50,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98

 # SUBTRACT LINK32 /pdb:none

 

 !ELSEIF  "$(CFG)" == "7z - Win32 Debug"

@@ -67,7 +67,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 /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c

+# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -75,7 +75,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept

 

 !ENDIF 

 

@@ -100,6 +100,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\7zArcIn.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\7zBuf.c

 # End Source File

 # Begin Source File

@@ -133,11 +137,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\7zIn.c

+SOURCE=..\..\7zStream.c

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\7zStream.c

+SOURCE=..\..\7zTypes.h

 # End Source File

 # Begin Source File

 

@@ -190,7 +194,6 @@
 # Begin Source File

 

 SOURCE=..\..\Ppmd7.c

-# SUBTRACT CPP /YX

 # End Source File

 # Begin Source File

 

@@ -199,11 +202,23 @@
 # Begin Source File

 

 SOURCE=..\..\Ppmd7Dec.c

-# SUBTRACT CPP /YX

+# End Source File

+# End Group

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compiler.h

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\Types.h

+SOURCE=.\Precomp.c

+# ADD CPP /Yc"Precomp.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\Precomp.h

 # End Source File

 # End Group

 # Begin Source File

diff --git a/C/Util/7z/7z.dsw b/C/Util/7z/7z.dsw
old mode 100755
new mode 100644
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
old mode 100755
new mode 100644
index f217340..736a7fe
--- a/C/Util/7z/7zMain.c
+++ b/C/Util/7z/7zMain.c
@@ -1,11 +1,14 @@
 /* 7zMain.c - Test application for 7z Decoder

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

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

+

+#include "Precomp.h"

 

 #include <stdio.h>

 #include <string.h>

 

 #include "../../7z.h"

 #include "../../7zAlloc.h"

+#include "../../7zBuf.h"

 #include "../../7zCrc.h"

 #include "../../7zFile.h"

 #include "../../7zVersion.h"

@@ -95,42 +98,52 @@
   dest->data[destLen] = 0;

   return res ? SZ_OK : SZ_ERROR_FAIL;

 }

+

 #endif

 

-static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)

+static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s

+    #ifdef _WIN32

+    , UINT codePage

+    #endif

+    )

 {

-  int len = 0;

-  for (len = 0; s[len] != '\0'; len++);

+  unsigned len = 0;

+  for (len = 0; s[len] != 0; len++);

 

   #ifdef _WIN32

   {

-    int size = len * 3 + 100;

+    unsigned size = len * 3 + 100;

     if (!Buf_EnsureSize(buf, size))

       return SZ_ERROR_MEM;

     {

-      char defaultChar = '_';

-      BOOL defUsed;

-      int numChars = WideCharToMultiByte(fileMode ?

-          (

-          #ifdef UNDER_CE

-          CP_ACP

-          #else

-          AreFileApisANSI() ? CP_ACP : CP_OEMCP

-          #endif

-          ) : CP_OEMCP,

-          0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);

-      if (numChars == 0 || numChars >= size)

-        return SZ_ERROR_FAIL;

-      buf->data[numChars] = 0;

+      buf->data[0] = 0;

+      if (len != 0)

+      {

+        char defaultChar = '_';

+        BOOL defUsed;

+        unsigned numChars = 0;

+        numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);

+        if (numChars == 0 || numChars >= size)

+          return SZ_ERROR_FAIL;

+        buf->data[numChars] = 0;

+      }

       return SZ_OK;

     }

   }

   #else

-  fileMode = fileMode;

   return Utf16_To_Utf8Buf(buf, s, len);

   #endif

 }

 

+#ifdef _WIN32

+  #ifndef USE_WINDOWS_FILE

+    static UINT g_FileCodePage = CP_ACP;

+  #endif

+  #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage

+#else

+  #define MY_FILE_CODE_PAGE_PARAM

+#endif

+

 static WRes MyCreateDir(const UInt16 *name)

 {

   #ifdef USE_WINDOWS_FILE

@@ -142,7 +155,7 @@
   CBuf buf;

   WRes res;

   Buf_Init(&buf);

-  RINOK(Utf16_To_Char(&buf, name, 1));

+  RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));

 

   res =

   #ifdef _WIN32

@@ -165,7 +178,7 @@
   CBuf buf;

   WRes res;

   Buf_Init(&buf);

-  RINOK(Utf16_To_Char(&buf, name, 1));

+  RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));

   res = OutFile_Open(p, (const char *)buf.data);

   Buf_Free(&buf, &g_Alloc);

   return res;

@@ -177,7 +190,11 @@
   CBuf buf;

   SRes res;

   Buf_Init(&buf);

-  res = Utf16_To_Char(&buf, s, 0);

+  res = Utf16_To_Char(&buf, s

+      #ifdef _WIN32

+      , CP_OEMCP

+      #endif

+      );

   if (res == SZ_OK)

     fputs((const char *)buf.data, stdout);

   Buf_Free(&buf, &g_Alloc);

@@ -216,17 +233,24 @@
   return s;

 }

 

+static void UIntToStr_2(char *s, unsigned value)

+{

+  s[0] = (char)('0' + (value / 10));

+  s[1] = (char)('0' + (value % 10));

+}

+

 #define PERIOD_4 (4 * 365 + 1)

 #define PERIOD_100 (PERIOD_4 * 25 - 1)

 #define PERIOD_400 (PERIOD_100 * 4 + 1)

 

-static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)

+static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)

 {

-  unsigned year, mon, day, hour, min, sec;

-  UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000;

+  unsigned year, mon, hour, min, sec;

   Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

   unsigned t;

   UInt32 v;

+  UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);

+  v64 /= 10000000;

   sec = (unsigned)(v64 % 60); v64 /= 60;

   min = (unsigned)(v64 % 60); v64 /= 60;

   hour = (unsigned)(v64 % 24); v64 /= 24;

@@ -242,36 +266,34 @@
 

   if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))

     ms[1] = 29;

-  for (mon = 1; mon <= 12; mon++)

+  for (mon = 0;; mon++)

   {

-    unsigned s = ms[mon - 1];

+    unsigned s = ms[mon];

     if (v < s)

       break;

     v -= s;

   }

-  day = (unsigned)v + 1;

   s = UIntToStr(s, year, 4); *s++ = '-';

-  s = UIntToStr(s, mon, 2);  *s++ = '-';

-  s = UIntToStr(s, day, 2);  *s++ = ' ';

-  s = UIntToStr(s, hour, 2); *s++ = ':';

-  s = UIntToStr(s, min, 2);  *s++ = ':';

-  s = UIntToStr(s, sec, 2);

+  UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;

+  UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3;

+  UIntToStr_2(s, hour); s[2] = ':'; s += 3;

+  UIntToStr_2(s, min); s[2] = ':'; s += 3;

+  UIntToStr_2(s, sec); s[2] = 0;

 }

 

-void PrintError(char *sz)

+void PrintError(const char *sz)

 {

   printf("\nERROR: %s\n", sz);

 }

 

 #ifdef USE_WINDOWS_FILE

-#define kEmptyAttribChar '.'

 static void GetAttribString(UInt32 wa, Bool isDir, char *s)

 {

-  s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar);

-  s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar);

-  s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar);

-  s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar);

-  s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar);

+  s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');

+  s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');

+  s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN   ) != 0) ? 'H': '.');

+  s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM   ) != 0) ? 'S': '.');

+  s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE  ) != 0) ? 'A': '.');

   s[5] = '\0';

 }

 #else

@@ -281,6 +303,8 @@
 }

 #endif

 

+// #define NUM_PARENTS_MAX 128

+

 int MY_CDECL main(int numargs, char *args[])

 {

   CFileInStream archiveStream;

@@ -291,6 +315,7 @@
   ISzAlloc allocTempImp;

   UInt16 *temp = NULL;

   size_t tempSize = 0;

+  // UInt32 parents[NUM_PARENTS_MAX];

 

   printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");

   if (numargs == 1)

@@ -310,13 +335,21 @@
     return 1;

   }

 

+  #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)

+  g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;

+  #endif

+

   allocImp.Alloc = SzAlloc;

   allocImp.Free = SzFree;

 

   allocTempImp.Alloc = SzAllocTemp;

   allocTempImp.Free = SzFreeTemp;

 

+  #ifdef UNDER_CE

+  if (InFile_OpenW(&archiveStream.file, L"\test.7z"))

+  #else

   if (InFile_Open(&archiveStream.file, args[2]))

+  #endif

   {

     PrintError("can not open input file");

     return 1;

@@ -335,11 +368,11 @@
   if (res == SZ_OK)

   {

     char *command = args[1];

-    int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;

+    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) extractCommand = 1;

-    else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }

+    else if (strcmp(command, "e") == 0) { }

+    else if (strcmp(command, "x") == 0) { fullPaths = 1; }

     else

     {

       PrintError("incorrect command");

@@ -358,22 +391,24 @@
       Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */

       size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

 

-      for (i = 0; i < db.db.NumFiles; i++)

+      for (i = 0; i < db.NumFiles; i++)

       {

         size_t offset = 0;

         size_t outSizeProcessed = 0;

-        const CSzFileItem *f = db.db.Files + i;

+        // const CSzFileItem *f = db.Files + i;

         size_t len;

-        if (listCommand == 0 && f->IsDir && !fullPaths)

+        int isDir = SzArEx_IsDir(&db, i);

+        if (listCommand == 0 && isDir && !fullPaths)

           continue;

         len = SzArEx_GetFileNameUtf16(&db, i, NULL);

+        // len = SzArEx_GetFullNameLen(&db, i);

 

         if (len > tempSize)

         {

           SzFree(NULL, temp);

           tempSize = len;

           temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));

-          if (temp == 0)

+          if (!temp)

           {

             res = SZ_ERROR_MEM;

             break;

@@ -381,15 +416,25 @@
         }

 

         SzArEx_GetFileNameUtf16(&db, i, temp);

+        /*

+        if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)

+        {

+          res = SZ_ERROR_FAIL;

+          break;

+        }

+        */

+

         if (listCommand)

         {

           char attr[8], s[32], t[32];

+          UInt64 fileSize;

 

-          GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);

+          GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);

 

-          UInt64ToStr(f->Size, s);

-          if (f->MTimeDefined)

-            ConvertFileTimeToString(&f->MTime, t);

+          fileSize = SzArEx_GetFileSize(&db, i);

+          UInt64ToStr(fileSize, s);

+          if (SzBitWithVals_Check(&db.MTime, i))

+            ConvertFileTimeToString(&db.MTime.Vals[i], t);

           else

           {

             size_t j;

@@ -402,7 +447,7 @@
           res = PrintString(temp);

           if (res != SZ_OK)

             break;

-          if (f->IsDir)

+          if (isDir)

             printf("/");

           printf("\n");

           continue;

@@ -414,7 +459,7 @@
         res = PrintString(temp);

         if (res != SZ_OK)

           break;

-        if (f->IsDir)

+        if (isDir)

           printf("/");

         else

         {

@@ -445,7 +490,7 @@
                 destPath = name + j + 1;

             }

     

-          if (f->IsDir)

+          if (isDir)

           {

             MyCreateDir(destPath);

             printf("\n");

@@ -471,8 +516,8 @@
             break;

           }

           #ifdef USE_WINDOWS_FILE

-          if (f->AttribDefined)

-            SetFileAttributesW(destPath, f->Attrib);

+          if (SzBitWithVals_Check(&db.Attribs, i))

+            SetFileAttributesW(destPath, db.Attribs.Vals[i]);

           #endif

         }

         printf("\n");

diff --git a/C/Util/7z/Precomp.c b/C/Util/7z/Precomp.c
new file mode 100644
index 0000000..34b60f8
--- /dev/null
+++ b/C/Util/7z/Precomp.c
@@ -0,0 +1,4 @@
+/* Precomp.c -- StdAfx

+2013-01-21 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

diff --git a/C/Util/7z/Precomp.h b/C/Util/7z/Precomp.h
new file mode 100644
index 0000000..9f398d0
--- /dev/null
+++ b/C/Util/7z/Precomp.h
@@ -0,0 +1,10 @@
+/* Precomp.h -- StdAfx

+2013-06-16 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_PRECOMP_H

+#define __7Z_PRECOMP_H

+

+#include "../../Compiler.h"

+#include "../../7zTypes.h"

+

+#endif

diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
old mode 100755
new mode 100644
index 3b85364..08e6f68
--- a/C/Util/7z/makefile
+++ b/C/Util/7z/makefile
@@ -1,4 +1,4 @@
-MY_STATIC_LINK=1

+# MY_STATIC_LINK=1

 CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT

 

 PROG = 7zDec.exe

@@ -6,12 +6,11 @@
 C_OBJS = \

   $O\7zAlloc.obj \

   $O\7zBuf.obj \

-  $O\7zBuf2.obj \

   $O\7zCrc.obj \

   $O\7zCrcOpt.obj \

   $O\7zFile.obj \

   $O\7zDec.obj \

-  $O\7zIn.obj \

+  $O\7zArcIn.obj \

   $O\7zStream.obj \

   $O\Bcj2.obj \

   $O\Bra.obj \

@@ -26,12 +25,15 @@
   $O\7zMain.obj \

 

 OBJS = \

+  $O\Precomp.obj \

   $(7Z_OBJS) \

   $(C_OBJS) \

 

 !include "../../../CPP/Build.mak"

 

 $(7Z_OBJS): $(*B).c

-	$(COMPL_O1)

+	$(CCOMPL_USE)

 $(C_OBJS): ../../$(*B).c

-	$(COMPL_O2)

+	$(CCOMPL_USE)

+$O\Precomp.obj: Precomp.c

+	$(CCOMPL_PCH)

diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc
old mode 100755
new mode 100644
index 2fb1576..63c59ca
--- a/C/Util/7z/makefile.gcc
+++ b/C/Util/7z/makefile.gcc
@@ -4,7 +4,7 @@
 RM = rm -f

 CFLAGS = -c -O2 -Wall

 

-OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.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 LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o

 

 all: $(PROG)

 

@@ -14,9 +14,12 @@
 7zMain.o: 7zMain.c

 	$(CXX) $(CFLAGS) 7zMain.c

 

-7zAlloc.o: 7zAlloc.c

+7zAlloc.o: ../../7zAlloc.c

 	$(CXX) $(CFLAGS) ../../7zAlloc.c

 

+7zArcIn.o: ../../7zArcIn.c

+	$(CXX) $(CFLAGS) ../../7zArcIn.c

+

 7zBuf.o: ../../7zBuf.c

 	$(CXX) $(CFLAGS) ../../7zBuf.c

 

@@ -32,9 +35,6 @@
 7zDec.o: ../../7zDec.c

 	$(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c

 

-7zIn.o: ../../7zIn.c

-	$(CXX) $(CFLAGS) ../../7zIn.c

-

 CpuArch.o: ../../CpuArch.c

 	$(CXX) $(CFLAGS) ../../CpuArch.c

 

diff --git a/C/Util/Lzma/Android.mk b/C/Util/Lzma/Android.mk
deleted file mode 100644
index e486b61..0000000
--- a/C/Util/Lzma/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2008 The Android Open Source Project
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := liblzma
-LOCAL_SRC_FILES := LzmaUtil.c ../../Alloc.c ../../LzFind.c ../../LzmaDec.c ../../LzmaEnc.c ../../7zFile.c ../../7zStream.c
-LOCAL_CFLAGS := -c -O2 -Wall -D_7ZIP_ST
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../
-include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
old mode 100755
new mode 100644
index f8de4a2..ee659ba
--- a/C/Util/Lzma/LzmaUtil.c
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -1,7 +1,7 @@
 /* LzmaUtil.c -- Test application for LZMA compression

-2010-09-20 : Igor Pavlov : Public domain */

+2014-12-31 : Igor Pavlov : Public domain */

 

-#define _CRT_SECURE_NO_WARNINGS

+#include "../../Precomp.h"

 

 #include <stdio.h>

 #include <stdlib.h>

@@ -92,7 +92,7 @@
         

       outPos = 0;

       

-      if (res != SZ_OK || thereIsSize && unpackSize == 0)

+      if (res != SZ_OK || (thereIsSize && unpackSize == 0))

         return res;

       

       if (inProcessed == 0 && outProcessed == 0)

diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
old mode 100755
new mode 100644
index 4815511..df1f0cb
--- a/C/Util/Lzma/LzmaUtil.dsp
+++ b/C/Util/Lzma/LzmaUtil.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 /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c

+# ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c

 # SUBTRACT CPP /YX

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

@@ -67,7 +67,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 /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c

+# ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c

 # SUBTRACT CPP /YX

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

diff --git a/C/Util/Lzma/LzmaUtil.dsw b/C/Util/Lzma/LzmaUtil.dsw
old mode 100755
new mode 100644
diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile
old mode 100755
new mode 100644
index e99e098..3b825f2
--- a/C/Util/Lzma/makefile
+++ b/C/Util/Lzma/makefile
@@ -1,4 +1,4 @@
-MY_STATIC_LINK=1

+# MY_STATIC_LINK=1

 PROG = LZMAc.exe

 

 CFLAGS = $(CFLAGS) \

diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc
old mode 100755
new mode 100644
diff --git a/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def
old mode 100755
new mode 100644
diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp
old mode 100755
new mode 100644
index bf52b63..0d4c981
--- a/C/Util/LzmaLib/LzmaLib.dsp
+++ b/C/Util/LzmaLib/LzmaLib.dsp
@@ -104,6 +104,10 @@
 # End Group

 # Begin Source File

 

+SOURCE=..\..\7zTypes.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Alloc.c

 # End Source File

 # Begin Source File

@@ -170,9 +174,5 @@
 

 SOURCE=..\..\Threads.h

 # End Source File

-# Begin Source File

-

-SOURCE=..\..\Types.h

-# End Source File

 # End Target

 # End Project

diff --git a/C/Util/LzmaLib/LzmaLib.dsw b/C/Util/LzmaLib/LzmaLib.dsw
old mode 100755
new mode 100644
diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c
old mode 100755
new mode 100644
diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
old mode 100755
new mode 100644
diff --git a/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc
old mode 100755
new mode 100644
index cb62ed9..d95e3f3
--- a/C/Util/LzmaLib/resource.rc
+++ b/C/Util/LzmaLib/resource.rc
@@ -1,4 +1,3 @@
-#include "../../../CPP/7zip/MyVersionInfo.rc"

+#include "../../7zVersion.rc"

 

 MY_VERSION_INFO_DLL("LZMA library", "LZMA")

-

diff --git a/C/Util/SfxSetup/Precomp.c b/C/Util/SfxSetup/Precomp.c
new file mode 100644
index 0000000..34b60f8
--- /dev/null
+++ b/C/Util/SfxSetup/Precomp.c
@@ -0,0 +1,4 @@
+/* Precomp.c -- StdAfx

+2013-01-21 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

diff --git a/C/Util/SfxSetup/Precomp.h b/C/Util/SfxSetup/Precomp.h
new file mode 100644
index 0000000..9f398d0
--- /dev/null
+++ b/C/Util/SfxSetup/Precomp.h
@@ -0,0 +1,10 @@
+/* Precomp.h -- StdAfx

+2013-06-16 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_PRECOMP_H

+#define __7Z_PRECOMP_H

+

+#include "../../Compiler.h"

+#include "../../7zTypes.h"

+

+#endif

diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
old mode 100755
new mode 100644
index d4eb5c4..5714e43
--- a/C/Util/SfxSetup/SfxSetup.c
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -1,5 +1,7 @@
 /* SfxSetup.c - 7z SFX Setup

-2010-11-11 : Igor Pavlov : Public domain */

+2014-12-07 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #ifndef UNICODE

 #define UNICODE

@@ -19,27 +21,28 @@
 #include "../../7zFile.h"

 #include "../../CpuArch.h"

 

-#define k_EXE_ExtIndex 1

+#define k_EXE_ExtIndex 2

 

 static const char *kExts[] =

 {

-  "bat",

-  "exe",

-  "inf",

-  "msi",

+    "bat"

+  , "cmd"

+  , "exe"

+  , "inf"

+  , "msi"

   #ifdef UNDER_CE

-  "cab",

+  , "cab"

   #endif

-  "html",

-  "htm"

+  , "html"

+  , "htm"

 };

 

 static const char *kNames[] =

 {

-  "setup",

-  "install",

-  "run",

-  "start"

+    "setup"

+  , "install"

+  , "run"

+  , "start"

 };

 

 static unsigned FindExt(const wchar_t *s, unsigned *extLen)

@@ -128,26 +131,21 @@
   *resPos = 0;

   for (;;)

   {

-    size_t numTests, pos;

+    size_t processed, pos;

     if (*resPos > kSignatureSearchLimit)

       return False;

-    

-    do

+    processed = kBufferSize - numPrevBytes;

+    if (File_Read(stream, buf + numPrevBytes, &processed) != 0)

+      return False;

+    processed += numPrevBytes;

+    if (processed < k7zStartHeaderSize ||

+        (processed == k7zStartHeaderSize && numPrevBytes != 0))

+      return False;

+    processed -= k7zStartHeaderSize;

+    for (pos = 0; pos <= processed; pos++)

     {

-      size_t processed = kBufferSize - numPrevBytes;

-      if (File_Read(stream, buf + numPrevBytes, &processed) != 0)

-        return False;

-      if (processed == 0)

-        return False;

-      numPrevBytes += processed;

-    }

-    while (numPrevBytes <= k7zStartHeaderSize);

-    

-    numTests = numPrevBytes - k7zStartHeaderSize;

-    for (pos = 0; pos < numTests; pos++)

-    {

-      for (; buf[pos] != '7' && pos < numTests; pos++);

-      if (pos == numTests)

+      for (; buf[pos] != '7' && pos <= processed; pos++);

+      if (pos > processed)

         break;

       if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)

         if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))

@@ -156,9 +154,9 @@
           return True;

         }

     }

-    *resPos += numTests;

-    numPrevBytes -= numTests;

-    memmove(buf, buf + numTests, numPrevBytes);

+    *resPos += processed;

+    numPrevBytes = k7zStartHeaderSize;

+    memmove(buf, buf + processed, k7zStartHeaderSize);

   }

 }

 

@@ -192,7 +190,7 @@
       wcscpy(path + len, fd.cFileName);

       if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)

       {

-        wcscat(path, L"\\");

+        wcscat(path, WSTRING_PATH_SEPARATOR);

         res = RemoveDirWithSubItems(path);

       }

       else

@@ -242,6 +240,9 @@
   ISzAlloc allocTempImp;

   WCHAR sfxPath[MAX_PATH + 2];

   WCHAR path[MAX_PATH * 3 + 2];

+  #ifndef UNDER_CE

+  WCHAR workCurDir[MAX_PATH + 32];

+  #endif

   size_t pathLen;

   DWORD winRes;

   const wchar_t *cmdLineParams;

@@ -296,6 +297,7 @@
       return 1;

     pathLen = wcslen(path);

     d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();

+    

     for (i = 0;; i++, d += GetTickCount())

     {

       if (i >= 100)

@@ -322,7 +324,7 @@
         continue;

       if (CreateDirectoryW(path, NULL))

       {

-        wcscat(path, L"\\");

+        wcscat(path, WSTRING_PATH_SEPARATOR);

         pathLen = wcslen(path);

         break;

       }

@@ -332,6 +334,10 @@
         break;

       }

     }

+    

+    #ifndef UNDER_CE

+    wcscpy(workCurDir, path);

+    #endif

     if (res != SZ_OK)

       errorMessage = "Can't create temp folder";

   }

@@ -371,6 +377,7 @@
   {

     res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);

   }

+  

   if (res == SZ_OK)

   {

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

@@ -380,11 +387,10 @@
     Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */

     size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

     

-    for (i = 0; i < db.db.NumFiles; i++)

+    for (i = 0; i < db.NumFiles; i++)

     {

       size_t offset = 0;

       size_t outSizeProcessed = 0;

-      const CSzFileItem *f = db.db.Files + i;

       size_t len;

       WCHAR *temp;

       len = SzArEx_GetFileNameUtf16(&db, i, NULL);

@@ -422,7 +428,7 @@
           }

         }

 

-        if (f->IsDir)

+        if (SzArEx_IsDir(&db, i))

         {

           MyCreateDir(path);

           continue;

@@ -457,6 +463,7 @@
             break;

           }

         }

+  

         processedSize = outSizeProcessed;

         if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)

         {

@@ -465,11 +472,12 @@
         }

         

         #ifdef USE_WINDOWS_FILE

-        if (f->MTimeDefined)

+        if (SzBitWithVals_Check(&db.MTime, i))

         {

+          const CNtfsFileTime *t = db.MTime.Vals + i;

           FILETIME mTime;

-          mTime.dwLowDateTime = f->MTime.Low;

-          mTime.dwHighDateTime = f->MTime.High;

+          mTime.dwLowDateTime = t->Low;

+          mTime.dwHighDateTime = t->High;

           SetFileTime(outFile.handle, NULL, NULL, &mTime);

         }

         #endif

@@ -485,8 +493,8 @@
           }

         }

         #ifdef USE_WINDOWS_FILE

-        if (f->AttribDefined)

-          SetFileAttributesW(path, f->Attrib);

+        if (SzBitWithVals_Check(&db.Attribs, i))

+          SetFileAttributesW(path, db.Attribs.Vals[i]);

         #endif

       }

     }

@@ -517,6 +525,18 @@
   if (res == SZ_OK)

   {

     HANDLE hProcess = 0;

+    

+    #ifndef UNDER_CE

+    WCHAR oldCurDir[MAX_PATH + 2];

+    oldCurDir[0] = 0;

+    {

+      DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir);

+      if (needLen == 0 || needLen > MAX_PATH)

+        oldCurDir[0] = 0;

+      SetCurrentDirectory(workCurDir);

+    }

+    #endif

+    

     if (useShellExecute)

     {

       SHELLEXECUTEINFO ei;

@@ -560,11 +580,16 @@
         hProcess = pi.hProcess;

       }

     }

+    

     if (hProcess != 0)

     {

       WaitForSingleObject(hProcess, INFINITE);

       CloseHandle(hProcess);

     }

+    

+    #ifndef UNDER_CE

+    SetCurrentDirectory(oldCurDir);

+    #endif

   }

 

   path[pathLen] = L'\0';

diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp
old mode 100755
new mode 100644
index 10814a5..1d5fdd8
--- a/C/Util/SfxSetup/SfxSetup.dsp
+++ b/C/Util/SfxSetup/SfxSetup.dsp
@@ -42,7 +42,7 @@
 # PROP Intermediate_Dir "Release"

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c

-# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /c

+# ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c

 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

@@ -68,7 +68,7 @@
 # PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c

-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c

+# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c

 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32

 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

@@ -103,6 +103,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\7zArcIn.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\7zBuf.c

 # End Source File

 # Begin Source File

@@ -135,11 +139,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\7zIn.c

+SOURCE=..\..\7zStream.c

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\7zStream.c

+SOURCE=..\..\7zTypes.h

 # End Source File

 # Begin Source File

 

@@ -185,9 +189,18 @@
 

 SOURCE=..\..\LzmaDec.h

 # End Source File

+# End Group

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

 # Begin Source File

 

-SOURCE=..\..\Types.h

+SOURCE=.\Precomp.c

+# ADD CPP /Yc"Precomp.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\Precomp.h

 # End Source File

 # End Group

 # Begin Source File

diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw
old mode 100755
new mode 100644
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
old mode 100755
new mode 100644
index 5d91be1..cc9878a
--- a/C/Util/SfxSetup/makefile
+++ b/C/Util/SfxSetup/makefile
@@ -1,16 +1,14 @@
 PROG = 7zS2.sfx

-LIBS = $(LIBS) 

-CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE

 

 C_OBJS = \

   $O\7zAlloc.obj \

+  $O\7zArcIn.obj \

   $O\7zBuf.obj \

   $O\7zBuf2.obj \

   $O\7zCrc.obj \

   $O\7zCrcOpt.obj \

   $O\7zFile.obj \

   $O\7zDec.obj \

-  $O\7zIn.obj \

   $O\7zStream.obj \

   $O\Bcj2.obj \

   $O\Bra.obj \

diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
old mode 100755
new mode 100644
index 3fbb6b6..f8bbb1f
--- a/C/Util/SfxSetup/makefile_con
+++ b/C/Util/SfxSetup/makefile_con
@@ -1,16 +1,15 @@
 PROG = 7zS2con.sfx

-LIBS = $(LIBS) 

-CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE

+CFLAGS = $(CFLAGS) -D_CONSOLE

 

 C_OBJS = \

   $O\7zAlloc.obj \

+  $O\7zArcIn.obj \

   $O\7zBuf.obj \

   $O\7zBuf2.obj \

   $O\7zCrc.obj \

   $O\7zCrcOpt.obj \

   $O\7zFile.obj \

   $O\7zDec.obj \

-  $O\7zIn.obj \

   $O\7zStream.obj \

   $O\Bcj2.obj \

   $O\Bra.obj \

diff --git a/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc
old mode 100755
new mode 100644
index efff95e..64f4e2c
--- a/C/Util/SfxSetup/resource.rc
+++ b/C/Util/SfxSetup/resource.rc
@@ -1,6 +1,5 @@
-#include "../../../CPP/7zip/MyVersionInfo.rc"

+#include "../../7zVersion.rc"

 

 MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx")

 

 1  ICON "setup.ico"

-

diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico
old mode 100755
new mode 100644
Binary files differ
diff --git a/C/Xz.c b/C/Xz.c
old mode 100755
new mode 100644
index 0bdf047..f7b5c24
--- a/C/Xz.c
+++ b/C/Xz.c
@@ -1,6 +1,8 @@
 /* Xz.c - Xz

 2009-04-15 : Igor Pavlov : Public domain */

 

+#include "Precomp.h"

+

 #include "7zCrc.h"

 #include "CpuArch.h"

 #include "Xz.h"

diff --git a/C/Xz.h b/C/Xz.h
old mode 100755
new mode 100644
index d307963..2512fd1
--- a/C/Xz.h
+++ b/C/Xz.h
@@ -1,5 +1,5 @@
 /* Xz.h - Xz interface

-2010-09-17 : Igor Pavlov : Public domain */

+2014-12-30 : Igor Pavlov : Public domain */

 

 #ifndef __XZ_H

 #define __XZ_H

@@ -209,7 +209,9 @@
   UInt64 indexPos;

   UInt64 padSize;

 

-  UInt64 numStreams;

+  UInt64 numStartedStreams;

+  UInt64 numFinishedStreams;

+  UInt64 numTotalBlocks;

 

   UInt32 crc;

   CMixCoder decoder;

@@ -220,33 +222,54 @@
   Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];

 } CXzUnpacker;

 

-SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);

+void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc);

+void XzUnpacker_Init(CXzUnpacker *p);

 void XzUnpacker_Free(CXzUnpacker *p);

 

 /*

 finishMode:

   It has meaning only if the decoding reaches output limit (*destLen).

-  LZMA_FINISH_ANY - use smallest number of input bytes

-  LZMA_FINISH_END - read EndOfStream marker after decoding

+  CODER_FINISH_ANY - use smallest number of input bytes

+  CODER_FINISH_END - read EndOfStream marker after decoding

 

 Returns:

   SZ_OK

     status:

-      LZMA_STATUS_FINISHED_WITH_MARK

-      LZMA_STATUS_NOT_FINISHED

-  SZ_ERROR_DATA - Data error

+      CODER_STATUS_NOT_FINISHED,

+      CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams,

+                                      call XzUnpacker_IsStreamWasFinished to check that current stream was finished

   SZ_ERROR_MEM  - Memory allocation error

-  SZ_ERROR_UNSUPPORTED - Unsupported properties

-  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+  SZ_ERROR_DATA - Data error

+  SZ_ERROR_UNSUPPORTED - Unsupported method or method properties

+  SZ_ERROR_CRC  - CRC error

+  // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+

+  SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:

+     - xz Stream Signature failure

+     - CRC32 of xz Stream Header is failed

+     - The size of Stream padding is not multiple of four bytes.

+    It's possible to get that error, if xz stream was finished and the stream

+    contains some another data. In that case you can call XzUnpacker_GetExtraSize()

+    function to get real size of xz stream.

 */

 

 

 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,

-    const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,

+    const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,

     ECoderStatus *status);

 

 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);

 

+/*

+Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of

+xz stream in two cases:

+XzUnpacker_Code() returns:

+  res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT

+  res == SZ_ERROR_NO_ARCHIVE

+*/

+

+UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p);

+

 EXTERN_C_END

 

 #endif

diff --git a/C/XzCrc64.c b/C/XzCrc64.c
old mode 100755
new mode 100644
index f688b07..667e41b
--- a/C/XzCrc64.c
+++ b/C/XzCrc64.c
@@ -1,33 +1,90 @@
 /* XzCrc64.c -- CRC64 calculation

-2010-04-16 : Igor Pavlov : Public domain */

+2011-06-28 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include "XzCrc64.h"

+#include "CpuArch.h"

 

 #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)

-UInt64 g_Crc64Table[256];

 

-void MY_FAST_CALL Crc64GenerateTable(void)

+#ifdef MY_CPU_LE

+  #define CRC_NUM_TABLES 4

+#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))

+  UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table);

+#endif

+

+#ifndef MY_CPU_BE

+  UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table);

+#endif

+

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

+

+static CRC_FUNC g_Crc64Update;

+UInt64 g_Crc64Table[256 * CRC_NUM_TABLES];

+

+UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)

+{

+  return g_Crc64Update(v, data, size, g_Crc64Table);

+}

+

+UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)

+{

+  return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL;

+}

+

+void MY_FAST_CALL Crc64GenerateTable()

 {

   UInt32 i;

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

   {

     UInt64 r = i;

-    int j;

+    unsigned j;

     for (j = 0; j < 8; j++)

-      r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1));

+      r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1));

     g_Crc64Table[i] = r;

   }

-}

+  for (; i < 256 * CRC_NUM_TABLES; i++)

+  {

+    UInt64 r = g_Crc64Table[i - 256];

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

+  }

+  

+  #ifdef MY_CPU_LE

 

-UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)

-{

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

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

-    v = CRC64_UPDATE_BYTE(v, *p);

-  return v;

-}

+  g_Crc64Update = XzCrc64UpdateT4;

 

-UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)

-{

-  return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size));

+  

+

+

+

+

+  #else

+  {

+    #ifndef MY_CPU_BE

+    UInt32 k = 1;

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

+      g_Crc64Update = XzCrc64UpdateT4;

+    else

+    #endif

+    {

+      for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)

+      {

+        UInt64 x = g_Crc64Table[i - 256];

+        g_Crc64Table[i] = CRC_UINT64_SWAP(x);

+      }

+      g_Crc64Update = XzCrc64UpdateT1_BeT4;

+    }

+  }

+  #endif

 }

diff --git a/C/XzCrc64.h b/C/XzCrc64.h
old mode 100755
new mode 100644
index 05d0d09..71b10d5
--- a/C/XzCrc64.h
+++ b/C/XzCrc64.h
@@ -1,12 +1,12 @@
 /* XzCrc64.h -- CRC64 calculation

-2010-04-16 : Igor Pavlov : Public domain */

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

 

 #ifndef __XZ_CRC64_H

 #define __XZ_CRC64_H

 

 #include <stddef.h>

 

-#include "Types.h"

+#include "7zTypes.h"

 

 EXTERN_C_BEGIN

 

diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c
new file mode 100644
index 0000000..65be5cd
--- /dev/null
+++ b/C/XzCrc64Opt.c
@@ -0,0 +1,69 @@
+/* XzCrc64Opt.c -- CRC64 calculation

+2011-06-28 : 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

+

+UInt64 MY_FAST_CALL XzCrc64UpdateT4(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);

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

+  }

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

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+#endif

+

+

+#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))

+

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

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

+  }

+  table -= 0x100;

+  v = CRC_UINT64_SWAP(v);

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

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+#endif

diff --git a/C/XzDec.c b/C/XzDec.c
old mode 100755
new mode 100644
index 2eca1af..e23f221
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,5 +1,7 @@
 /* XzDec.c -- Xz Decode

-2010-04-16 : Igor Pavlov : Public domain */

+2014-12-30 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 /* #define XZ_DUMP */

 

@@ -18,7 +20,8 @@
 #include "Lzma2Dec.h"

 

 #ifdef USE_SUBBLOCK

-#include "SbDec.h"

+#include "Bcj3Dec.c"

+#include "SbDec.c"

 #endif

 

 #include "Xz.h"

@@ -72,7 +75,6 @@
 {

   CBraState *p = ((CBraState *)pp);

   alloc = alloc;

-  p->encodeMode = 0;

   p->ip = 0;

   if (p->methodId == XZ_ID_Delta)

   {

@@ -195,7 +197,7 @@
   return SZ_OK;

 }

 

-SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)

+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)

 {

   CBraState *decoder;

   if (id != XZ_ID_Delta &&

@@ -207,10 +209,11 @@
       id != XZ_ID_SPARC)

     return SZ_ERROR_UNSUPPORTED;

   p->p = 0;

-  decoder = alloc->Alloc(alloc, sizeof(CBraState));

+  decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));

   if (decoder == 0)

     return SZ_ERROR_MEM;

   decoder->methodId = (UInt32)id;

+  decoder->encodeMode = encodeMode;

   p->p = decoder;

   p->Free = BraState_Free;

   p->SetProps = BraState_SetProps;

@@ -225,8 +228,8 @@
 

 static void SbState_Free(void *pp, ISzAlloc *alloc)

 {

-  CSubblockDec *p = (CSubblockDec *)pp;

-  SubblockDec_Free(p, alloc);

+  CSbDec *p = (CSbDec *)pp;

+  SbDec_Free(p);

   alloc->Free(alloc, pp);

 }

 

@@ -240,24 +243,32 @@
 

 static void SbState_Init(void *pp)

 {

-  SubblockDec_Init((CSubblockDec *)pp);

+  SbDec_Init((CSbDec *)pp);

 }

 

 static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

     int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)

 {

-  ECoderStatus status;

-  SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);

+  CSbDec *p = (CSbDec *)pp;

+  SRes res;

   srcWasFinished = srcWasFinished;

-  *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);

+  p->dest = dest;

+  p->destLen = *destLen;

+  p->src = src;

+  p->srcLen = *srcLen;

+  p->finish = finishMode; /* change it */

+  res = SbDec_Decode((CSbDec *)pp);

+  *destLen -= p->destLen;

+  *srcLen -= p->srcLen;

+  *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */

   return res;

 }

 

 SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)

 {

-  CSubblockDec *decoder;

+  CSbDec *decoder;

   p->p = 0;

-  decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));

+  decoder = alloc->Alloc(alloc, sizeof(CSbDec));

   if (decoder == 0)

     return SZ_ERROR_MEM;

   p->p = decoder;

@@ -265,7 +276,8 @@
   p->SetProps = SbState_SetProps;

   p->Init = SbState_Init;

   p->Code = SbState_Code;

-  SubblockDec_Construct(decoder);

+  SbDec_Construct(decoder);

+  SbDec_SetAlloc(decoder, alloc);

   return SZ_OK;

 }

 #endif

@@ -295,7 +307,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, finishMode, &status);

+  SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);

   srcWasFinished = srcWasFinished;

   *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);

   return res;

@@ -303,7 +315,7 @@
 

 static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)

 {

-  CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));

+  CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));

   p->p = decoder;

   if (decoder == 0)

     return SZ_ERROR_MEM;

@@ -337,7 +349,10 @@
   }

   p->numCoders = 0;

   if (p->buf)

+  {

     p->alloc->Free(p->alloc, p->buf);

+    p->buf = 0; /* 9.31: the BUG was fixed */

+  }

 }

 

 void MixCoder_Init(CMixCoder *p)

@@ -369,7 +384,7 @@
   }

   if (coderIndex == 0)

     return SZ_ERROR_UNSUPPORTED;

-  return BraState_SetFromMethod(sc, methodId, p->alloc);

+  return BraState_SetFromMethod(sc, methodId, 0, p->alloc);

 }

 

 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,

@@ -385,7 +400,7 @@
 

   if (p->buf == 0)

   {

-    p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));

+    p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));

     if (p->buf == 0)

       return SZ_ERROR_MEM;

   }

@@ -587,13 +602,20 @@
   return SZ_OK;

 }

 

-SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)

+void XzUnpacker_Init(CXzUnpacker *p)

 {

-  MixCoder_Construct(&p->decoder, alloc);

   p->state = XZ_STATE_STREAM_HEADER;

   p->pos = 0;

-  p->numStreams = 0;

-  return SZ_OK;

+  p->numStartedStreams = 0;

+  p->numFinishedStreams = 0;

+  p->numTotalBlocks = 0;

+  p->padSize = 0;

+}

+

+void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)

+{

+  MixCoder_Construct(&p->decoder, alloc);

+  XzUnpacker_Init(p);

 }

 

 void XzUnpacker_Free(CXzUnpacker *p)

@@ -602,7 +624,7 @@
 }

 

 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,

-    const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)

+    const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)

 {

   SizeT destLenOrig = *destLen;

   SizeT srcLenOrig = *srcLen;

@@ -662,7 +684,7 @@
       return SZ_OK;

     }

 

-    switch(p->state)

+    switch (p->state)

     {

       case XZ_STATE_STREAM_HEADER:

       {

@@ -676,6 +698,7 @@
         else

         {

           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));

+          p->numStartedStreams++;

           p->state = XZ_STATE_BLOCK_HEADER;

           Sha256_Init(&p->sha);

           p->indexSize = 0;

@@ -716,6 +739,7 @@
         else

         {

           RINOK(XzBlock_Parse(&p->block, p->buf));

+          p->numTotalBlocks++;

           p->state = XZ_STATE_BLOCK;

           p->packSize = 0;

           p->unpackSize = 0;

@@ -833,7 +857,7 @@
         if (p->pos == XZ_STREAM_FOOTER_SIZE)

         {

           p->state = XZ_STATE_STREAM_PADDING;

-          p->numStreams++;

+          p->numFinishedStreams++;

           p->padSize = 0;

           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))

             return SZ_ERROR_CRC;

@@ -873,3 +897,13 @@
 {

   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);

 }

+

+UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)

+{

+  UInt64 num = 0;

+  if (p->state == XZ_STATE_STREAM_PADDING)

+    num += p->padSize;

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

+    num += p->padSize + p->pos;

+  return num;

+}

diff --git a/C/XzEnc.c b/C/XzEnc.c
old mode 100755
new mode 100644
index e610140..3263519
--- a/C/XzEnc.c
+++ b/C/XzEnc.c
@@ -1,5 +1,7 @@
 /* XzEnc.c -- Xz Encode

-2009-06-04 : Igor Pavlov : Public domain */

+2014-12-30 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include <stdlib.h>

 #include <string.h>

@@ -9,7 +11,9 @@
 #include "Bra.h"

 #include "CpuArch.h"

 #ifdef USE_SUBBLOCK

-#include "SbEnc.h"

+#include "Bcj3Enc.c"

+#include "SbFind.c"

+#include "SbEnc.c"

 #endif

 

 #include "XzEnc.h"

@@ -130,7 +134,7 @@
     CXzBlockSizes *blocks;

     if (newSize / sizeof(CXzBlockSizes) != num)

       return SZ_ERROR_MEM;

-    blocks = alloc->Alloc(alloc, newSize);

+    blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize);

     if (blocks == 0)

       return SZ_ERROR_MEM;

     if (p->numBlocks != 0)

@@ -198,158 +202,147 @@
 

 /* ---------- CSeqInFilter ---------- */

 

-/*

-typedef struct _IFilter

-{

-  void *p;

-  void (*Free)(void *p, ISzAlloc *alloc);

-  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);

-  void (*Init)(void *p);

-  size_t (*Filter)(void *p, Byte *data, SizeT destLen);

-} IFilter;

-

-#define FILT_BUF_SIZE (1 << 19)

+#define FILTER_BUF_SIZE (1 << 20)

 

 typedef struct

 {

   ISeqInStream p;

   ISeqInStream *realStream;

-  UInt32 x86State;

-  UInt32 ip;

-  UInt64 processed;

-  CXzCheck check;

-  Byte buf[FILT_BUF_SIZE];

-  UInt32 bufferPos;

-  UInt32 convertedPosBegin;

-  UInt32 convertedPosEnd;

-  IFilter *filter;

+  IStateCoder StateCoder;

+  Byte *buf;

+  size_t curPos;

+  size_t endPos;

+  int srcWasFinished;

 } CSeqInFilter;

 

 static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)

 {

   CSeqInFilter *p = (CSeqInFilter *)pp;

-  size_t remSize = *size;

+  size_t sizeOriginal = *size;

+  if (sizeOriginal == 0)

+    return SZ_OK;

   *size = 0;

-

-  while (remSize > 0)

+  for (;;)

   {

-    int i;

-    if (p->convertedPosBegin != p->convertedPosEnd)

+    if (!p->srcWasFinished && p->curPos == p->endPos)

     {

-      UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin;

-      if (remSize < sizeTemp)

-        sizeTemp = (UInt32)remSize;

-      memmove(data, p->buf + p->convertedPosBegin, sizeTemp);

-      p->convertedPosBegin += sizeTemp;

-      data = (void *)((Byte *)data + sizeTemp);

-      remSize -= sizeTemp;

-      *size += sizeTemp;

-      break;

+      p->curPos = 0;

+      p->endPos = FILTER_BUF_SIZE;

+      RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos));

+      if (p->endPos == 0)

+        p->srcWasFinished = 1;

     }

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

-      p->buf[i] = p->buf[i + p->convertedPosEnd];

-    p->bufferPos = i;

-    p->convertedPosBegin = p->convertedPosEnd = 0;

     {

-      size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos;

-      RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp));

-      p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp;

-    }

-    p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);

-    if (p->convertedPosEnd == 0)

-    {

-      if (p->bufferPos == 0)

-        break;

-      else

-      {

-        p->convertedPosEnd = p->bufferPos;

-        continue;

-      }

-    }

-    if (p->convertedPosEnd > p->bufferPos)

-    {

-      for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++)

-        p->buf[p->bufferPos] = 0;

-      p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);

+      SizeT srcLen = p->endPos - p->curPos;

+      int wasFinished;

+      SRes res;

+      *size = sizeOriginal;

+      res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen,

+        p->srcWasFinished, CODER_FINISH_ANY, &wasFinished);

+      p->curPos += srcLen;

+      if (*size != 0 || srcLen == 0 || res != 0)

+        return res;

     }

   }

+}

+

+static void SeqInFilter_Construct(CSeqInFilter *p)

+{

+  p->buf = NULL;

+  p->p.Read = SeqInFilter_Read;

+}

+

+static void SeqInFilter_Free(CSeqInFilter *p)

+{

+  if (p->buf)

+  {

+    g_Alloc.Free(&g_Alloc, p->buf);

+    p->buf = NULL;

+  }

+}

+

+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc);

+

+static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)

+{

+  if (!p->buf)

+  {

+    p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE);

+    if (!p->buf)

+      return SZ_ERROR_MEM;

+  }

+  p->curPos = p->endPos = 0;

+  p->srcWasFinished = 0;

+  RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc));

+  RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc));

+  p->StateCoder.Init(p->StateCoder.p);

   return SZ_OK;

 }

-*/

 

-/*

-typedef struct

-{

-  ISeqInStream p;

-  ISeqInStream *realStream;

-  CMixCoder mixCoder;

-  Byte buf[FILT_BUF_SIZE];

-  UInt32 bufPos;

-  UInt32 bufSize;

-} CMixCoderSeqInStream;

-

-static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size)

-{

-  CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp;

-  SRes res = SZ_OK;

-  size_t remSize = *size;

-  *size = 0;

-  while (remSize > 0)

-  {

-    if (p->bufPos == p->bufSize)

-    {

-      size_t curSize;

-      p->bufPos = p->bufSize = 0;

-      if (*size != 0)

-        break;

-      curSize = FILT_BUF_SIZE;

-      RINOK(p->realStream->Read(p->realStream, p->buf, &curSize));

-      p->bufSize = (UInt32)curSize;

-    }

-    {

-      SizeT destLen = remSize;

-      SizeT srcLen = p->bufSize - p->bufPos;

-      res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0);

-      data = (void *)((Byte *)data + destLen);

-      remSize -= destLen;

-      *size += destLen;

-      p->bufPos += srcLen;

-    }

-  }

-  return res;

-}

-*/

+/* ---------- CSbEncInStream ---------- */

 

 #ifdef USE_SUBBLOCK

+

 typedef struct

 {

   ISeqInStream p;

-  CSubblockEnc sb;

-  UInt64 processed;

+  ISeqInStream *inStream;

+  CSbEnc enc;

 } CSbEncInStream;

 

-void SbEncInStream_Init(CSbEncInStream *p)

-{

-  p->processed = 0;

-  SubblockEnc_Init(&p->sb);

-}

-

 static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)

 {

   CSbEncInStream *p = (CSbEncInStream *)pp;

-  SRes res = SubblockEnc_Read(&p->sb, data, size);

-  p->processed += *size;

-  return res;

+  size_t sizeOriginal = *size;

+  if (sizeOriginal == 0)

+    return S_OK;

+  for (;;)

+  {

+    if (p->enc.needRead && !p->enc.readWasFinished)

+    {

+      size_t processed = p->enc.needReadSizeMax;

+      RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed));

+      p->enc.readPos += processed;

+      if (processed == 0)

+      {

+        p->enc.readWasFinished = True;

+        p->enc.isFinalFinished = True;

+      }

+      p->enc.needRead = False;

+    }

+    *size = sizeOriginal;

+    RINOK(SbEnc_Read(&p->enc, data, size));

+    if (*size != 0 || !p->enc.needRead)

+      return S_OK;

+  }

 }

+

+void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc)

+{

+  SbEnc_Construct(&p->enc, alloc);

+  p->p.Read = SbEncInStream_Read;

+}

+

+SRes SbEncInStream_Init(CSbEncInStream *p)

+{

+  return SbEnc_Init(&p->enc);

+}

+

+void SbEncInStream_Free(CSbEncInStream *p)

+{

+  SbEnc_Free(&p->enc);

+}

+

 #endif

 

+

 typedef struct

 {

-  /* CMixCoderSeqInStream inStream; */

   CLzma2EncHandle lzma2;

   #ifdef USE_SUBBLOCK

   CSbEncInStream sb;

   #endif

+  CSeqInFilter filter;

   ISzAlloc *alloc;

   ISzAlloc *bigAlloc;

 } CLzma2WithFilters;

@@ -361,9 +354,9 @@
   p->bigAlloc = bigAlloc;

   p->lzma2 = NULL;

   #ifdef USE_SUBBLOCK

-  p->sb.p.Read = SbEncInStream_Read;

-  SubblockEnc_Construct(&p->sb.sb, p->alloc);

+  SbEncInStream_Construct(&p->sb, alloc);

   #endif

+  SeqInFilter_Construct(&p->filter);

 }

 

 static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)

@@ -376,8 +369,9 @@
 

 static void Lzma2WithFilters_Free(CLzma2WithFilters *p)

 {

+  SeqInFilter_Free(&p->filter);

   #ifdef USE_SUBBLOCK

-  SubblockEnc_Free(&p->sb.sb);

+  SbEncInStream_Free(&p->sb);

   #endif

   if (p->lzma2)

   {

@@ -386,17 +380,28 @@
   }

 }

 

-static SRes Xz_Compress(CXzStream *xz,

-    CLzma2WithFilters *lzmaf,

-    ISeqOutStream *outStream,

-    ISeqInStream *inStream,

-    const CLzma2EncProps *lzma2Props,

-    Bool useSubblock,

-    ICompressProgress *progress)

+void XzProps_Init(CXzProps *p)

 {

-  xz->flags = XZ_CHECK_CRC32;

+  p->lzma2Props = 0;

+  p->filterProps = 0;

+  p->checkId = XZ_CHECK_CRC32;

+}

 

-  RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));

+void XzFilterProps_Init(CXzFilterProps *p)

+{

+  p->id = 0;

+  p->delta = 0;

+  p->ip= 0;

+  p->ipDefined = False;

+}

+

+static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,

+    ISeqOutStream *outStream, ISeqInStream *inStream,

+    const CXzProps *props, ICompressProgress *progress)

+{

+  xz->flags = (Byte)props->checkId;

+

+  RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props));

   RINOK(Xz_WriteHeader(xz->flags, outStream));

 

   {

@@ -404,15 +409,27 @@
     CSeqSizeOutStream seqSizeOutStream;

     CXzBlock block;

     int filterIndex = 0;

+    CXzFilter *filter = NULL;

+    const CXzFilterProps *fp = props->filterProps;

     

     XzBlock_ClearFlags(&block);

-    XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));

+    XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0));

     

-    if (useSubblock)

+    if (fp)

     {

-      CXzFilter *f = &block.filters[filterIndex++];

-      f->id = XZ_ID_Subblock;

-      f->propsSize = 0;

+      filter = &block.filters[filterIndex++];

+      filter->id = fp->id;

+      filter->propsSize = 0;

+      if (fp->id == XZ_ID_Delta)

+      {

+        filter->props[0] = (Byte)(fp->delta - 1);

+        filter->propsSize = 1;

+      }

+      else if (fp->ipDefined)

+      {

+        SetUi32(filter->props, fp->ip);

+        filter->propsSize = 4;

+      }

     }

 

     {

@@ -432,20 +449,30 @@
     checkInStream.realStream = inStream;

     SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));

     

-    #ifdef USE_SUBBLOCK

-    if (useSubblock)

+    if (fp)

     {

-      lzmaf->sb.sb.inStream = &checkInStream.p;

-      SubblockEnc_Init(&lzmaf->sb.sb);

+      #ifdef USE_SUBBLOCK

+      if (fp->id == XZ_ID_Subblock)

+      {

+        lzmaf->sb.inStream = &checkInStream.p;

+        RINOK(SbEncInStream_Init(&lzmaf->sb));

+      }

+      else

+      #endif

+      {

+        lzmaf->filter.realStream = &checkInStream.p;

+        RINOK(SeqInFilter_Init(&lzmaf->filter, filter));

+      }

     }

-    #endif

-    

+

     {

       UInt64 packPos = seqSizeOutStream.processed;

       SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,

+        fp ?

         #ifdef USE_SUBBLOCK

-        useSubblock ? &lzmaf->sb.p:

+        (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:

         #endif

+        &lzmaf->filter.p:

         &checkInStream.p,

         progress);

       RINOK(res);

@@ -467,8 +494,7 @@
 }

 

 SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,

-    const CLzma2EncProps *lzma2Props, Bool useSubblock,

-    ICompressProgress *progress)

+    const CXzProps *props, ICompressProgress *progress)

 {

   SRes res;

   CXzStream xz;

@@ -477,8 +503,7 @@
   Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);

   res = Lzma2WithFilters_Create(&lzmaf);

   if (res == SZ_OK)

-    res = Xz_Compress(&xz, &lzmaf, outStream, inStream,

-        lzma2Props, useSubblock, progress);

+    res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress);

   Lzma2WithFilters_Free(&lzmaf);

   Xz_Free(&xz, &g_Alloc);

   return res;

diff --git a/C/XzEnc.h b/C/XzEnc.h
old mode 100755
new mode 100644
index aad9aa4..e9cea34
--- a/C/XzEnc.h
+++ b/C/XzEnc.h
@@ -1,5 +1,5 @@
 /* XzEnc.h -- Xz Encode

-2009-04-15 : Igor Pavlov : Public domain */

+2011-02-07 : Igor Pavlov : Public domain */

 

 #ifndef __XZ_ENC_H

 #define __XZ_ENC_H

@@ -8,18 +8,32 @@
 

 #include "Xz.h"

 

-#ifdef __cplusplus

-extern "C" {

-#endif

+EXTERN_C_BEGIN

+

+typedef struct

+{

+  UInt32 id;

+  UInt32 delta;

+  UInt32 ip;

+  int ipDefined;

+} CXzFilterProps;

+

+void XzFilterProps_Init(CXzFilterProps *p);

+

+typedef struct

+{

+  const CLzma2EncProps *lzma2Props;

+  const CXzFilterProps *filterProps;

+  unsigned checkId;

+} CXzProps;

+

+void XzProps_Init(CXzProps *p);

 

 SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,

-    const CLzma2EncProps *lzma2Props, Bool useSubblock,

-    ICompressProgress *progress);

+    const CXzProps *props, ICompressProgress *progress);

 

 SRes Xz_EncodeEmpty(ISeqOutStream *outStream);

 

-#ifdef __cplusplus

-}

-#endif

+EXTERN_C_END

 

 #endif

diff --git a/C/XzIn.c b/C/XzIn.c
old mode 100755
new mode 100644
index 356d019..c99d71c
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,7 @@
 /* XzIn.c - Xz input

-2009-06-19 : Igor Pavlov : Public domain */

+2014-12-30 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

 

 #include <string.h>

 

@@ -70,7 +72,7 @@
 

 static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)

 {

-  size_t i, numBlocks, crcStartPos, pos = 1;

+  size_t i, numBlocks, pos = 1;

   UInt32 crc;

 

   if (size < 5 || buf[0] != 0)

@@ -89,7 +91,6 @@
       return SZ_ERROR_ARCHIVE;

   }

   

-  crcStartPos = pos;

   Xz_Free(p, alloc);

   if (numBlocks != 0)

   {

@@ -152,39 +153,38 @@
   

   if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

   {

-    Int64 i = 0;

+    UInt32 total = 0;

     *startOffset += XZ_STREAM_FOOTER_SIZE;

     for (;;)

     {

-      int j;

-      size_t processedSize;

+      size_t i;

       #define TEMP_BUF_SIZE (1 << 10)

       Byte tempBuf[TEMP_BUF_SIZE];

-      if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))

+      if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))

         return SZ_ERROR_NO_ARCHIVE;

-      processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;

-      i += processedSize;

-      *startOffset = -(Int64)processedSize;

+      i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;

+      total += (UInt32)i;

+      *startOffset = -(Int64)i;

       RINOK(SeekFromCur(stream, startOffset));

-      RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE));

-      for (j = (int)processedSize; j >= 0; j--)

-        if (tempBuf[j -1] != 0)

+      RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE));

+      for (; i != 0; i--)

+        if (tempBuf[i - 1] != 0)

           break;

-      if (j != 0)

+      if (i != 0)

       {

-        if ((j & 3) != 0)

+        if ((i & 3) != 0)

           return SZ_ERROR_NO_ARCHIVE;

-        *startOffset += j;

-        if (*startOffset < 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));

-        if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

-          return SZ_ERROR_NO_ARCHIVE;

+        *startOffset += i;

         break;

       }

     }

+    if (*startOffset < 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));

+    if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

+      return SZ_ERROR_NO_ARCHIVE;

   }

   

   p->flags = (CXzStreamFlags)GetBe16(buf + 8);

@@ -291,7 +291,8 @@
       if (data == 0)

         return SZ_ERROR_MEM;

       p->numAllocated = newNum;

-      memcpy(data, p->streams, p->num * sizeof(CXzStream));

+      if (p->num != 0)

+        memcpy(data, p->streams, p->num * sizeof(CXzStream));

       alloc->Free(alloc, p->streams);

       p->streams = (CXzStream *)data;

     }

diff --git a/CPP/7zip/7zip.mak b/CPP/7zip/7zip.mak
new file mode 100644
index 0000000..7fec27c
--- /dev/null
+++ b/CPP/7zip/7zip.mak
@@ -0,0 +1,240 @@
+OBJS = \

+  $O\StdAfx.obj \

+  $(CURRENT_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(WIN_CTRL_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(AR_OBJS) \

+  $(AR_COMMON_OBJS) \

+  $(UI_COMMON_OBJS) \

+  $(AGENT_OBJS) \

+  $(CONSOLE_OBJS) \

+  $(EXPLORER_OBJS) \

+  $(FM_OBJS) \

+  $(GUI_OBJS) \

+  $(7Z_OBJS) \

+  $(CAB_OBJS) \

+  $(CHM_OBJS) \

+  $(COM_OBJS) \

+  $(ISO_OBJS) \

+  $(NSIS_OBJS) \

+  $(RAR_OBJS) \

+  $(TAR_OBJS) \

+  $(UDF_OBJS) \

+  $(WIM_OBJS) \

+  $(ZIP_OBJS) \

+  $(COMPRESS_OBJS) \

+  $(CRYPTO_OBJS) \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+  $O\resource.res \

+

+!include "../../../Build.mak"

+

+# MAK_SINGLE_FILE = 1

+

+!IFDEF MAK_SINGLE_FILE

+

+!IFDEF CURRENT_OBJS

+$(CURRENT_OBJS): ./$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+

+!IFDEF COMMON_OBJS

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF WIN_OBJS

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF WIN_CTRL_OBJS

+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF 7ZIP_COMMON_OBJS

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF AR_OBJS

+$(AR_OBJS): ../../Archive/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF AR_COMMON_OBJS

+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF 7Z_OBJS

+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF CAB_OBJS

+$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF CHM_OBJS

+$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF COM_OBJS

+$(COM_OBJS): ../../Archive/Com/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF ISO_OBJS

+$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF NSIS_OBJS

+$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF RAR_OBJS

+$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF TAR_OBJS

+$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF UDF_OBJS

+$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF WIM_OBJS

+$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF ZIP_OBJS

+$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF COMPRESS_OBJS

+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

+	$(COMPL_O2)

+!ENDIF

+

+!IFDEF CRYPTO_OBJS

+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp

+	$(COMPL_O2)

+!ENDIF

+

+!IFDEF UI_COMMON_OBJS

+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF AGENT_OBJS

+$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF CONSOLE_OBJS

+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF EXPLORER_OBJS

+$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF FM_OBJS

+$(FM_OBJS): ../../UI/FileManager/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF GUI_OBJS

+$(GUI_OBJS): ../../UI/GUI/$(*B).cpp

+	$(COMPL)

+!ENDIF

+

+!IFDEF C_OBJS

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+!ENDIF

+

+

+!ELSE

+

+{.}.cpp{$O}.obj::

+	$(COMPLB)

+{../../../Common}.cpp{$O}.obj::

+	$(COMPLB)

+{../../../Windows}.cpp{$O}.obj::

+	$(COMPLB)

+{../../../Windows/Control}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Common}.cpp{$O}.obj::

+	$(COMPLB)

+

+{../../UI/Common}.cpp{$O}.obj::

+	$(COMPLB)

+{../../UI/Agent}.cpp{$O}.obj::

+	$(COMPLB)

+{../../UI/Console}.cpp{$O}.obj::

+	$(COMPLB)

+{../../UI/Explorer}.cpp{$O}.obj::

+	$(COMPLB)

+{../../UI/FileManager}.cpp{$O}.obj::

+	$(COMPLB)

+{../../UI/GUI}.cpp{$O}.obj::

+	$(COMPLB)

+

+

+{../../Archive}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Common}.cpp{$O}.obj::

+	$(COMPLB)

+

+{../../Archive/7z}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Cab}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Chm}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Com}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Iso}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Nsis}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Rar}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Tar}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Udf}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Wim}.cpp{$O}.obj::

+	$(COMPLB)

+{../../Archive/Zip}.cpp{$O}.obj::

+	$(COMPLB)

+

+{../../Compress}.cpp{$O}.obj::

+	$(COMPLB_O2)

+{../../Crypto}.cpp{$O}.obj::

+	$(COMPLB_O2)

+{../../../../C}.c{$O}.obj::

+	$(CCOMPLB)

+

+!ENDIF

+

+!include "Asm.mak"

diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
old mode 100755
new mode 100644
index a388e1f..3301b93
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -3,19 +3,18 @@
 #ifndef __7Z_COMPRESSION_MODE_H

 #define __7Z_COMPRESSION_MODE_H

 

-#include "../../../Common/MyString.h"

-

-#include "../../../Windows/PropVariant.h"

-

+#include "../../Common/MethodId.h"

 #include "../../Common/MethodProps.h"

 

 namespace NArchive {

 namespace N7z {

 

-struct CMethodFull: public CMethod

+struct CMethodFull: public CProps

 {

+  CMethodId Id;

   UInt32 NumInStreams;

   UInt32 NumOutStreams;

+

   bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

 };

 

diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
old mode 100755
new mode 100644
index 3fcdd5f..d58fb02
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -16,29 +16,33 @@
     CBindInfoEx &bindInfo)

 {

   bindInfo.Clear();

-  int i;

+  bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());

+  unsigned i;

   for (i = 0; i < folder.BindPairs.Size(); i++)

   {

-    NCoderMixer::CBindPair bindPair;

+    NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];

     bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;

     bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;

-    bindInfo.BindPairs.Add(bindPair);

   }

+

+  bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());

+  bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());

+

   UInt32 outStreamIndex = 0;

   for (i = 0; i < folder.Coders.Size(); i++)

   {

-    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+    NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];

     const CCoderInfo &coderInfo = folder.Coders[i];

     coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;

     coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;

-    bindInfo.Coders.Add(coderStreamsInfo);

-    bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);

+    bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;

     for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)

       if (folder.FindBindPairForOutStream(outStreamIndex) < 0)

         bindInfo.OutStreams.Add(outStreamIndex);

   }

+  bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());

   for (i = 0; i < folder.PackStreams.Size(); i++)

-    bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);

+    bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];

 }

 

 static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,

@@ -58,7 +62,7 @@
 {

   if (a1.Coders.Size() != a2.Coders.Size())

     return false;

-  int i;

+  unsigned i;

   for (i = 0; i < a1.Coders.Size(); i++)

     if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))

       return false;

@@ -90,45 +94,49 @@
     DECL_EXTERNAL_CODECS_LOC_VARS

     IInStream *inStream,

     UInt64 startPos,

-    const UInt64 *packSizes,

-    const CFolder &folderInfo,

+    const CFolders &folders, int folderIndex,

     ISequentialOutStream *outStream,

     ICompressProgressInfo *compressProgress

-    #ifndef _NO_CRYPTO

-    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-    #endif

+    _7Z_DECODER_CRYPRO_VARS_DECL

     #if !defined(_7ZIP_ST) && !defined(_SFX)

     , bool mtMode, UInt32 numThreads

     #endif

     )

 {

-  if (!folderInfo.CheckStructure())

+  const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];

+  CFolder folderInfo;

+  folders.ParseFolderInfo(folderIndex, folderInfo);

+

+  if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))

     return E_NOTIMPL;

+  

+  /*

+  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 (int j = 0; j < folderInfo.PackStreams.Size(); j++)

+  for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)

   {

-    CLockedSequentialInStreamImp *lockedStreamImpSpec = new

-        CLockedSequentialInStreamImp;

+    CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;

     CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;

-    lockedStreamImpSpec->Init(&lockedInStream, startPos);

-    startPos += packSizes[j];

-    

-    CLimitedSequentialInStream *streamSpec = new

-        CLimitedSequentialInStream;

+    lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);

+    CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;

     CMyComPtr<ISequentialInStream> inStream = streamSpec;

     streamSpec->SetStream(lockedStreamImp);

-    streamSpec->Init(packSizes[j]);

+    streamSpec->Init(packPositions[j + 1] - packPositions[j]);

     inStreams.Add(inStream);

   }

   

-  int numCoders = folderInfo.Coders.Size();

+  unsigned numCoders = folderInfo.Coders.Size();

   

   CBindInfoEx bindInfo;

   ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);

@@ -139,7 +147,7 @@
     createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);

   if (createNewCoders)

   {

-    int i;

+    unsigned i;

     _decoders.Clear();

     // _decoders2.Clear();

     

@@ -204,17 +212,19 @@
       decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

       if (setCompressCodecsInfo)

       {

-        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));

+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));

       }

       #endif

     }

     _bindInfoExPrev = bindInfo;

     _bindInfoExPrevIsDefined = true;

   }

-  int i;

+  unsigned i;

   _mixerCoderCommon->ReInit();

   

-  UInt32 packStreamIndex = 0, unpackStreamIndex = 0;

+  UInt32 packStreamIndex = 0;

+  UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];

+  UInt32 unpackStreamIndex = unpackStreamIndexStart;

   UInt32 coderIndex = 0;

   // UInt32 coder2Index = 0;

   

@@ -229,7 +239,7 @@
       if (setDecoderProperties)

       {

         const CByteBuffer &props = coderInfo.Props;

-        size_t size = props.GetCapacity();

+        size_t size = props.Size();

         if (size > 0xFFFFFFFF)

           return E_NOTIMPL;

         // if (size > 0)

@@ -257,22 +267,23 @@
       decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);

       if (cryptoSetPassword)

       {

-        if (getTextPassword == 0)

-          return E_FAIL;

+        isEncrypted = true;

+        if (!getTextPassword)

+          return E_NOTIMPL;

         CMyComBSTR passwordBSTR;

         RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));

-        CByteBuffer buffer;

         passwordIsDefined = true;

-        const UString password(passwordBSTR);

-        const UInt32 sizeInBytes = password.Length() * 2;

-        buffer.SetCapacity(sizeInBytes);

-        for (int i = 0; i < password.Length(); i++)

+        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 = password[i];

+          wchar_t c = passwordBSTR[i];

           ((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)buffer.Size()));

       }

     }

     #endif

@@ -281,32 +292,30 @@
     

     UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;

     UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;

-    CRecordVector<const UInt64 *> packSizesPointers;

-    CRecordVector<const UInt64 *> unpackSizesPointers;

-    packSizesPointers.Reserve(numInStreams);

-    unpackSizesPointers.Reserve(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.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);

+      unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];

     

     for (j = 0; j < numInStreams; j++, packStreamIndex++)

     {

       int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);

       if (bindPairIndex >= 0)

-        packSizesPointers.Add(

-        &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);

+        packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];

       else

       {

         int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);

         if (index < 0)

-          return E_FAIL;

-        packSizesPointers.Add(&packSizes[index]);

+          return S_FALSE; // check it

+        packSizes[j] = packPositions[index + 1] - packPositions[index];

+        packSizesPointers[j] = &packSizes[j];

       }

     }

     

-    _mixerCoderCommon->SetCoderInfo(i,

-        &packSizesPointers.Front(),

-        &unpackSizesPointers.Front());

+    _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);

   }

   UInt32 mainCoder, temp;

   bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);

@@ -320,13 +329,15 @@
   

   if (numCoders == 0)

     return 0;

-  CRecordVector<ISequentialInStream *> inStreamPointers;

-  inStreamPointers.Reserve(inStreams.Size());

-  for (i = 0; i < inStreams.Size(); i++)

-    inStreamPointers.Add(inStreams[i]);

+  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.Front(), NULL,

-    inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);

+  return _mixerCoder->Code(

+      inStreamPointers, NULL, num,

+      &outStreamPointer, NULL, 1,

+      compressProgress);

 }

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
old mode 100755
new mode 100644
index da213a1..f27170d
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -14,7 +14,7 @@
 

 #include "../../Common/CreateCoder.h"

 

-#include "7zItem.h"

+#include "7zIn.h"

 

 namespace NArchive {

 namespace N7z {

@@ -50,13 +50,10 @@
       DECL_EXTERNAL_CODECS_LOC_VARS

       IInStream *inStream,

       UInt64 startPos,

-      const UInt64 *packSizes,

-      const CFolder &folder,

+      const CFolders &folders, int folderIndex,

       ISequentialOutStream *outStream,

       ICompressProgressInfo *compressProgress

-      #ifndef _NO_CRYPTO

-      , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined

-      #endif

+      _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
old mode 100755
new mode 100644
index 4b93449..365489c
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -23,30 +23,39 @@
     const CRecordVector<CMethodId> decompressionMethods,

     CFolder &folder)

 {

-  folder.Coders.Clear();

   // bindInfo.CoderMethodIDs.Clear();

   // folder.OutStreams.Clear();

-  folder.PackStreams.Clear();

-  folder.BindPairs.Clear();

-  int i;

+  folder.BindPairs.SetSize(bindInfo.BindPairs.Size());

+  unsigned i;

   for (i = 0; i < bindInfo.BindPairs.Size(); i++)

   {

-    CBindPair bindPair;

-    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;

-    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;

-    folder.BindPairs.Add(bindPair);

+    CBindPair &bp = folder.BindPairs[i];

+    const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];

+    bp.InIndex = mixerBp.InIndex;

+    bp.OutIndex = mixerBp.OutIndex;

   }

+  folder.Coders.SetSize(bindInfo.Coders.Size());

   for (i = 0; i < bindInfo.Coders.Size(); i++)

   {

-    CCoderInfo coderInfo;

+    CCoderInfo &coderInfo = folder.Coders[i];

     const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];

     coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;

     coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;

     coderInfo.MethodID = decompressionMethods[i];

-    folder.Coders.Add(coderInfo);

+    // coderInfo.Props can be nonFree;

   }

+  folder.PackStreams.SetSize(bindInfo.InStreams.Size());

   for (i = 0; i < bindInfo.InStreams.Size(); i++)

-    folder.PackStreams.Add(bindInfo.InStreams[i]);

+    folder.PackStreams[i] = bindInfo.InStreams[i];

+}

+

+static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)

+{

+  CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

+  coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);

+  if (setCoderProperties)

+    return props.SetCoderProps(setCoderProperties, dataSizeReduce);

+  return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;

 }

 

 HRESULT CEncoder::CreateMixerCoder(

@@ -56,11 +65,10 @@
   _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;

   _mixerCoder = _mixerCoderSpec;

   RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));

-  for (int i = 0; i < _options.Methods.Size(); i++)

+  FOR_VECTOR (i, _options.Methods)

   {

     const CMethodFull &methodFull = _options.Methods[i];

-    _codersInfo.Add(CCoderInfo());

-    CCoderInfo &encodingInfo = _codersInfo.Back();

+    CCoderInfo &encodingInfo = _codersInfo.AddNew();

     encodingInfo.MethodID = methodFull.Id;

     CMyComPtr<ICompressCoder> encoder;

     CMyComPtr<ICompressCoder2> encoder2;

@@ -86,13 +94,12 @@
     }

     #endif

         

-

-    RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));

+    RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon));

 

     /*

     CMyComPtr<ICryptoResetSalt> resetSalt;

     encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);

-    if (resetSalt != NULL)

+    if (resetSalt)

     {

       resetSalt->ResetSalt();

     }

@@ -103,7 +110,7 @@
     encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

     if (setCompressCodecsInfo)

     {

-      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));

+      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));

     }

     #endif

     

@@ -112,10 +119,9 @@
 

     if (cryptoSetPassword)

     {

-      CByteBuffer buffer;

-      const UInt32 sizeInBytes = _options.Password.Length() * 2;

-      buffer.SetCapacity(sizeInBytes);

-      for (int i = 0; i < _options.Password.Length(); i++)

+      const UInt32 sizeInBytes = _options.Password.Len() * 2;

+      CByteBuffer buffer(sizeInBytes);

+      for (unsigned i = 0; i < _options.Password.Len(); i++)

       {

         wchar_t c = _options.Password[i];

         ((Byte *)buffer)[i * 2] = (Byte)c;

@@ -137,13 +143,15 @@
     ISequentialInStream *inStream,

     const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

     CFolder &folderItem,

+    CRecordVector<UInt64> &coderUnpackSizes,

+    UInt64 &unpackSize,

     ISequentialOutStream *outStream,

     CRecordVector<UInt64> &packSizes,

     ICompressProgressInfo *compressProgress)

 {

   RINOK(EncoderConstr());

 

-  if (_mixerCoderSpec == NULL)

+  if (!_mixerCoderSpec)

   {

     RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));

   }

@@ -153,13 +161,13 @@
   CObjectVector<CInOutTempBuffer> inOutTempBuffers;

   CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;

   CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;

-  int numMethods = _bindInfo.Coders.Size();

-  int i;

+  unsigned numMethods = _bindInfo.Coders.Size();

+  unsigned i;

   for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

   {

-    inOutTempBuffers.Add(CInOutTempBuffer());

-    inOutTempBuffers.Back().Create();

-    inOutTempBuffers.Back().InitWriting();

+    CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();

+    iotb.Create();

+    iotb.InitWriting();

   }

   for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

   {

@@ -178,7 +186,7 @@
   UInt32 mainCoderIndex, mainStreamIndex;

   _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);

   

-  if (inStreamSize != NULL)

+  if (inStreamSize)

   {

     CRecordVector<const UInt64 *> sizePointers;

     for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)

@@ -195,17 +203,24 @@
   

   CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;

   CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;

-  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;

-  CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;

+  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;

+  CMyComPtr<ISequentialOutStream> outStreamSizeCount;

 

   inStreamSizeCountSpec->Init(inStream);

-  outStreamSizeCountSpec->SetStream(outStream);

-  outStreamSizeCountSpec->Init();

 

   CRecordVector<ISequentialInStream *> inStreamPointers;

   CRecordVector<ISequentialOutStream *> outStreamPointers;

   inStreamPointers.Add(inStreamSizeCount);

-  outStreamPointers.Add(outStreamSizeCount);

+  

+  if (_bindInfo.OutStreams.Size() != 0)

+  {

+    outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;

+    outStreamSizeCount = outStreamSizeCountSpec;

+    outStreamSizeCountSpec->SetStream(outStream);

+    outStreamSizeCountSpec->Init();

+    outStreamPointers.Add(outStreamSizeCount);

+  }

+

   for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

     outStreamPointers.Add(tempBuffers[i - 1]);

 

@@ -215,14 +230,14 @@
     

     CMyComPtr<ICryptoResetInitVector> resetInitVector;

     _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);

-    if (resetInitVector != NULL)

+    if (resetInitVector)

     {

       resetInitVector->ResetInitVector();

     }

 

     CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

     _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

-    if (writeCoderProperties != NULL)

+    if (writeCoderProperties)

     {

       CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;

       CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

@@ -248,7 +263,8 @@
   

   ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);

   

-  packSizes.Add(outStreamSizeCountSpec->GetSize());

+  if (_bindInfo.OutStreams.Size() != 0)

+    packSizes.Add(outStreamSizeCountSpec->GetSize());

   

   for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

   {

@@ -256,19 +272,23 @@
     RINOK(inOutTempBuffer.WriteToStream(outStream));

     packSizes.Add(inOutTempBuffer.GetDataSize());

   }

-  

+

+  unpackSize = 0;

   for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)

   {

     int binder = _bindInfo.FindBinderForInStream(

         _bindReverseConverter->DestOutToSrcInMap[i]);

     UInt64 streamSize;

     if (binder < 0)

+    {

       streamSize = inStreamSizeCountSpec->GetSize();

+      unpackSize = streamSize;

+    }

     else

       streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);

-    folderItem.UnpackSizes.Add(streamSize);

+    coderUnpackSizes.Add(streamSize);

   }

-  for (i = numMethods - 1; i >= 0; i--)

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

     folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;

   return S_OK;

 }

@@ -315,7 +335,7 @@
   {

 

   UInt32 numInStreams = 0, numOutStreams = 0;

-  int i;

+  unsigned i;

   for (i = 0; i < _options.Methods.Size(); i++)

   {

     const CMethodFull &methodFull = _options.Methods[i];

@@ -331,7 +351,7 @@
         bindPair.OutIndex = numOutStreams;

         _bindInfo.BindPairs.Add(bindPair);

       }

-      else

+      else if (coderStreamsInfo.NumOutStreams != 0)

         _bindInfo.OutStreams.Insert(0, numOutStreams);

       for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)

         _bindInfo.OutStreams.Add(numOutStreams + j);

@@ -390,7 +410,7 @@
 

   if (_options.PasswordIsDefined)

   {

-    int numCryptoStreams = _bindInfo.OutStreams.Size();

+    unsigned numCryptoStreams = _bindInfo.OutStreams.Size();

 

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

     {

diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
old mode 100755
new mode 100644
index c75f02f..0f28cfb
--- a/CPP/7zip/Archive/7z/7zEncode.h
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -45,6 +45,8 @@
       ISequentialInStream *inStream,

       const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

       CFolder &folderItem,

+      CRecordVector<UInt64> &coderUnpackSizes,

+      UInt64 &unpackSize,

       ISequentialOutStream *outStream,

       CRecordVector<UInt64> &packSizes,

       ICompressProgressInfo *compressProgress);

diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
old mode 100755
new mode 100644
index 6e31943..9310762
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -37,8 +37,8 @@
   {

     if (fileIndex != kNumNoIndex)

     {

-      ExtractStatuses.Reserve(1);

-      ExtractStatuses.Add(true);

+      ExtractStatuses.ClearAndSetSize(1);

+      ExtractStatuses[0] = true;

     }

   };

 };

@@ -51,7 +51,7 @@
   CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;

   UInt64 importantTotalUnpacked = 0;

 

-  bool allFilesMode = (numItems == (UInt32)-1);

+  bool allFilesMode = (numItems == (UInt32)(Int32)-1);

   if (allFilesMode)

     numItems =

     #ifdef _7Z_VOL

@@ -67,7 +67,7 @@
   if(_volumes.Size() != 1)

     return E_FAIL;

   const CVolume &volume = _volumes.Front();

-  const CArchiveDatabaseEx &_db = volume.Database;

+  const CDbEx &_db = volume.Database;

   IInStream *_inStream = volume.Stream;

   */

   

@@ -86,10 +86,10 @@
 

       int volumeIndex = ref.VolumeIndex;

       const CVolume &volume = _volumes[volumeIndex];

-      const CArchiveDatabaseEx &db = volume.Database;

+      const CDbEx &db = volume.Database;

       UInt32 fileIndex = ref.ItemIndex;

       #else

-      const CArchiveDatabaseEx &db = _db;

+      const CDbEx &db = _db;

       UInt32 fileIndex = ref2Index;

       #endif

 

@@ -115,8 +115,7 @@
             volumeIndex,

             #endif

             kNumNoIndex, folderIndex));

-        const CFolder &folderInfo = db.Folders[folderIndex];

-        UInt64 unpackSize = folderInfo.GetUnpackSize();

+        UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);

         importantTotalUnpacked += unpackSize;

         extractFolderInfoVector.Back().UnpackSize = unpackSize;

       }

@@ -156,7 +155,7 @@
   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(extractCallback, false);

 

-  for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)

+  for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)

   {

     lps->OutSize = totalUnpacked;

     lps->InSize = totalPacked;

@@ -174,9 +173,9 @@
 

     #ifdef _7Z_VOL

     const CVolume &volume = _volumes[efi.VolumeIndex];

-    const CArchiveDatabaseEx &db = volume.Database;

+    const CDbEx &db = volume.Database;

     #else

-    const CArchiveDatabaseEx &db = _db;

+    const CDbEx &db = _db;

     #endif

 

     CNum startIndex;

@@ -200,13 +199,8 @@
       continue;

 

     CNum folderIndex = efi.FolderIndex;

-    const CFolder &folderInfo = db.Folders[folderIndex];

-

     curPacked = _db.GetFolderFullPackSize(folderIndex);

 

-    CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex];

-    UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0);

-

     #ifndef _NO_CRYPTO

     CMyComPtr<ICryptoGetTextPassword> getTextPassword;

     if (extractCallback)

@@ -216,26 +210,24 @@
     try

     {

       #ifndef _NO_CRYPTO

-      bool passwordIsDefined;

+        bool isEncrypted = false;

+        bool passwordIsDefined = false;

       #endif

 

       HRESULT result = decoder.Decode(

           EXTERNAL_CODECS_VARS

           #ifdef _7Z_VOL

-          volume.Stream,

+            volume.Stream,

           #else

-          _inStream,

+            _inStream,

           #endif

-          folderStartPackPos,

-          &db.PackSizes[packStreamIndex],

-          folderInfo,

+          db.ArcInfo.DataStartPosition,

+          db, folderIndex,

           outStream,

           progress

-          #ifndef _NO_CRYPTO

-          , getTextPassword, passwordIsDefined

-          #endif

+          _7Z_DECODER_CRYPRO_VARS

           #if !defined(_7ZIP_ST) && !defined(_SFX)

-          , true, _numThreads

+            , true, _numThreads

           #endif

           );

 

@@ -246,7 +238,7 @@
       }

       if (result == E_NOTIMPL)

       {

-        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod));

+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));

         continue;

       }

       if (result != S_OK)

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
old mode 100755
new mode 100644
index c49d341..7971191
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -106,8 +106,8 @@
 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)

 {

   *value = 0;

-  int index2 = (int)subStream;

-  if (index2 < 0 || subStream > Sizes.Size())

+  unsigned index2 = (unsigned)subStream;

+  if (subStream > Sizes.Size())

     return E_FAIL;

   if (index2 < Sizes.Size())

   {

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
old mode 100755
new mode 100644
index fc27b9b..e516dff
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -47,7 +47,7 @@
   UInt64 GetFullSize() const

   {

     UInt64 size = 0;

-    for (int i = 0; i < Sizes.Size(); i++)

+    FOR_VECTOR (i, Sizes)

       size += Sizes[i];

     return size;

   }

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
old mode 100755
new mode 100644
index 403ca60..d206d7c
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -14,7 +14,7 @@
 }

 

 HRESULT CFolderOutStream::Init(

-    const CArchiveDatabaseEx *db,

+    const CDbEx *db,

     UInt32 ref2Offset, UInt32 startIndex,

     const CBoolVector *extractStatuses,

     IArchiveExtractCallback *extractCallback,

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
old mode 100755
new mode 100644
index c964b1d..c00aba7
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -19,12 +19,12 @@
 {

   COutStreamWithCRC *_crcStreamSpec;

   CMyComPtr<ISequentialOutStream> _crcStream;

-  const CArchiveDatabaseEx *_db;

+  const CDbEx *_db;

   const CBoolVector *_extractStatuses;

   CMyComPtr<IArchiveExtractCallback> _extractCallback;

   UInt32 _ref2Offset;

   UInt32 _startIndex;

-  int _currentIndex;

+  unsigned _currentIndex;

   bool _testMode;

   bool _checkCrc;

   bool _fileIsOpen;

@@ -43,7 +43,7 @@
   STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

 

   HRESULT Init(

-      const CArchiveDatabaseEx *db,

+      const CDbEx *db,

       UInt32 ref2Offset, UInt32 startIndex,

       const CBoolVector *extractStatuses,

       IArchiveExtractCallback *extractCallback,

diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
old mode 100755
new mode 100644
index c404b9c..6104440
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -23,26 +23,23 @@
 #endif

 

 using namespace NWindows;

-

-extern UString ConvertMethodIdToString(UInt64 id);

+using namespace NCOM;

 

 namespace NArchive {

 namespace N7z {

 

 CHandler::CHandler()

 {

-  _crcSize = 4;

-

   #ifndef _NO_CRYPTO

+  _isEncrypted = false;

   _passwordIsDefined = false;

   #endif

 

   #ifdef EXTRACT_ONLY

+  _crcSize = 4;

   #ifdef __7Z_SET_PROPERTIES

   _numThreads = NSystem::GetNumberOfProcessors();

   #endif

-  #else

-  Init();

   #endif

 }

 

@@ -54,11 +51,12 @@
 

 #ifdef _SFX

 

-IMP_IInArchive_ArcProps_NO

+IMP_IInArchive_ArcProps_NO_Table

 

-STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)

+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)

 {

-  return E_NOTIMPL;

+  *numProps = 0;

+  return S_OK;

 }

 

 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,

@@ -67,141 +65,485 @@
   return E_NOTIMPL;

 }

 

-

 #else

 

-STATPROPSTG kArcProps[] =

+static const Byte kArcProps[] =

 {

-  { NULL, kpidMethod, VT_BSTR},

-  { NULL, kpidSolid, VT_BOOL},

-  { NULL, kpidNumBlocks, VT_UI4},

-  { NULL, kpidPhySize, VT_UI8},

-  { NULL, kpidHeadersSize, VT_UI8},

-  { NULL, kpidOffset, VT_UI8}

+  kpidHeadersSize,

+  kpidMethod,

+  kpidSolid,

+  kpidNumBlocks

+  // , kpidIsTree

 };

 

-STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

-{

-  COM_TRY_BEGIN

-  NCOM::CPropVariant prop;

-  switch(propID)

-  {

-    case kpidMethod:

-    {

-      UString resString;

-      CRecordVector<UInt64> ids;

-      int i;

-      for (i = 0; i < _db.Folders.Size(); i++)

-      {

-        const CFolder &f = _db.Folders[i];

-        for (int j = f.Coders.Size() - 1; j >= 0; j--)

-          ids.AddToUniqueSorted(f.Coders[j].MethodID);

-      }

-

-      for (i = 0; i < ids.Size(); i++)

-      {

-        UInt64 id = ids[i];

-        UString methodName;

-        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);

-        if (methodName.IsEmpty())

-          methodName = ConvertMethodIdToString(id);

-        if (!resString.IsEmpty())

-          resString += L' ';

-        resString += methodName;

-      }

-      prop = resString;

-      break;

-    }

-    case kpidSolid: prop = _db.IsSolid(); break;

-    case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;

-    case kpidHeadersSize:  prop = _db.HeadersSize; break;

-    case kpidPhySize:  prop = _db.PhySize; break;

-    case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;

-  }

-  prop.Detach(value);

-  return S_OK;

-  COM_TRY_END

-}

-

 IMP_IInArchive_ArcProps

 

-#endif

-

-static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)

+static inline char GetHex(unsigned value)

 {

-  UInt64 value;

-  if (v.GetItem(index, value))

-  {

-    FILETIME ft;

-    ft.dwLowDateTime = (DWORD)value;

-    ft.dwHighDateTime = (DWORD)(value >> 32);

-    prop = ft;

-  }

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

 }

 

-#ifndef _SFX

-

-static UString ConvertUInt32ToString(UInt32 value)

+static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)

 {

-  wchar_t buffer[32];

-  ConvertUInt64ToString(value, buffer);

-  return buffer;

+  int len = 0;

+  do

+  {

+    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;

+    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;

+  }

+  while (id != 0);

+  return (unsigned)-len;

 }

 

-static UString GetStringForSizeValue(UInt32 value)

+static void ConvertMethodIdToString(AString &res, UInt64 id)

 {

-  for (int i = 31; i >= 0; i--)

-    if ((UInt32(1) << i) == value)

-      return ConvertUInt32ToString(i);

-  UString result;

-  if (value % (1 << 20) == 0)

-  {

-    result += ConvertUInt32ToString(value >> 20);

-    result += L"m";

-  }

-  else if (value % (1 << 10) == 0)

-  {

-    result += ConvertUInt32ToString(value >> 10);

-    result += L"k";

-  }

-  else

-  {

-    result += ConvertUInt32ToString(value);

-    result += L"b";

-  }

-  return result;

+  const unsigned kLen = 32;

+  char s[kLen];

+  unsigned len = kLen - 1;

+  s[len] = 0;

+  res += s + len - ConvertMethodIdToString_Back(s + len, id);

 }

 

-static const UInt64 k_Copy = 0x0;

-static const UInt64 k_Delta = 3;

-static const UInt64 k_LZMA2 = 0x21;

-static const UInt64 k_LZMA  = 0x030101;

-static const UInt64 k_PPMD  = 0x030401;

-

-static wchar_t GetHex(Byte value)

+static unsigned GetStringForSizeValue(char *s, UInt32 val)

 {

-  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));

+  unsigned i;

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

+    if (((UInt32)1 << i) == val)

+    {

+      if (i < 10)

+      {

+        s[0] = (char)('0' + i);

+        s[1] = 0;

+        return 1;

+      }

+           if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }

+      else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }

+      else             { s[0] = '3'; s[1] = (char)('0' + i - 30); }

+      s[2] = 0;

+      return 2;

+    }

+  char c = 'b';

+  if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }

+  else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }

+  ::ConvertUInt32ToString(val, s);

+  unsigned pos = MyStringLen(s);

+  s[pos++] = c;

+  s[pos] = 0;

+  return pos;

 }

+

+/*

 static inline void AddHexToString(UString &res, Byte value)

 {

   res += GetHex((Byte)(value >> 4));

   res += GetHex((Byte)(value & 0xF));

 }

+*/

+

+static char *AddProp32(char *s, const char *name, UInt32 v)

+{

+  *s++ = ':';

+  s = MyStpCpy(s, name);

+  ::ConvertUInt32ToString(v, s);

+  return s + MyStringLen(s);

+}

+ 

+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())

+    ConvertMethodIdToString(s, id);

+  else

+    for (unsigned i = 0; i < methodName.Len(); i++)

+      s += (char)methodName[i];

+}

 

 #endif

 

-bool CHandler::IsEncrypted(UInt32 index2) const

+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

 {

-  CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

-  if (folderIndex != kNumNoIndex)

-    return _db.Folders[folderIndex].IsEncrypted();

+  #ifndef _SFX

+  COM_TRY_BEGIN

+  #endif

+  NCOM::CPropVariant prop;

+  switch (propID)

+  {

+    #ifndef _SFX

+    case kpidMethod:

+    {

+      AString s;

+      const CParsedMethods &pm = _db.ParsedMethods;

+      FOR_VECTOR (i, pm.IDs)

+      {

+        UInt64 id = pm.IDs[i];

+        if (!s.IsEmpty())

+          s += ' ';

+        char temp[16];

+        if (id == k_LZMA2)

+        {

+          s += "LZMA2:";

+          if ((pm.Lzma2Prop & 1) == 0)

+            ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);

+          else

+            GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));

+          s += temp;

+        }

+        else if (id == k_LZMA)

+        {

+          s += "LZMA:";

+          GetStringForSizeValue(temp, pm.LzmaDic);

+          s += temp;

+        }

+        else

+          AddMethodName(s, id);

+      }

+      prop = s;

+      break;

+    }

+    case kpidSolid: prop = _db.IsSolid(); break;

+    case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;

+    case kpidHeadersSize:  prop = _db.HeadersSize; break;

+    case kpidPhySize:  prop = _db.PhySize; break;

+    case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;

+    /*

+    case kpidIsTree: if (_db.IsTree) prop = true; break;

+    case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;

+    case kpidIsAux: if (_db.IsTree) prop = true; break;

+    */

+    // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;

+    #endif

+    

+    case kpidWarningFlags:

+    {

+      UInt32 v = 0;

+      if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;

+      if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;

+      if (v != 0)

+        prop = v;

+      break;

+    }

+    

+    case kpidErrorFlags:

+    {

+      UInt32 v = 0;

+      if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;

+      if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;

+      if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;

+      // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;

+      if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;

+      prop = v;

+      break;

+    }

+  }

+  prop.Detach(value);

+  return S_OK;

+  #ifndef _SFX

+  COM_TRY_END

+  #endif

+}

+

+static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)

+{

+  UInt64 value;

+  if (v.GetItem(index, value))

+    PropVarEm_Set_FileTime64(prop, value);

+}

+

+bool CHandler::IsFolderEncrypted(CNum folderIndex) const

+{

+  if (folderIndex == kNumNoIndex)

+    return false;

+  size_t startPos = _db.FoCodersDataOffset[folderIndex];

+  const Byte *p = _db.CodersData + startPos;

+  size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;

+  CInByte2 inByte;

+  inByte.Init(p, size);

+  

+  CNum numCoders = inByte.ReadNum();

+  for (; numCoders != 0; numCoders--)

+  {

+    Byte mainByte = inByte.ReadByte();

+    unsigned idSize = (mainByte & 0xF);

+    const Byte *longID = inByte.GetPtr();

+    UInt64 id64 = 0;

+    for (unsigned j = 0; j < idSize; j++)

+      id64 = ((id64 << 8) | longID[j]);

+    inByte.SkipDataNoCheck(idSize);

+    if (id64 == k_AES)

+      return true;

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

+      inByte.SkipDataNoCheck(inByte.ReadNum());

+  }

   return false;

 }

 

-STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)

+STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)

 {

-  COM_TRY_BEGIN

-  NCOM::CPropVariant prop;

+  *numProps = 0;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)

+{

+  *name = NULL;

+  *propID = kpidNtSecure;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)

+{

+  /*

+  const CFileItem &file = _db.Files[index];

+  *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);

+  *parent = (UInt32)(Int32)file.Parent;

+  */

+  *parentType = NParentType::kDir;

+  *parent = (UInt32)(Int32)-1;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)

+{

+  *data = NULL;

+  *dataSize = 0;

+  *propType = 0;

+

+  if (/* _db.IsTree && propID == kpidName ||

+      !_db.IsTree && */ propID == kpidPath)

+  {

+    if (_db.NameOffsets && _db.NamesBuf)

+    {

+      size_t offset = _db.NameOffsets[index];

+      size_t size = (_db.NameOffsets[index + 1] - offset) * 2;

+      if (size < ((UInt32)1 << 31))

+      {

+        *data = (const void *)(_db.NamesBuf + offset * 2);

+        *dataSize = (UInt32)size;

+        *propType = NPropDataType::kUtf16z;

+      }

+    }

+    return S_OK;

+  }

+  /*

+  if (propID == kpidNtSecure)

+  {

+    if (index < (UInt32)_db.SecureIDs.Size())

+    {

+      int id = _db.SecureIDs[index];

+      size_t offs = _db.SecureOffsets[id];

+      size_t size = _db.SecureOffsets[id + 1] - offs;

+      if (size >= 0)

+      {

+        *data = _db.SecureBuf + offs;

+        *dataSize = (UInt32)size;

+        *propType = NPropDataType::kRaw;

+      }

+    }

+  }

+  */

+  return S_OK;

+}

+

+#ifndef _SFX

+

+HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const

+{

+  PropVariant_Clear(prop);

+  if (folderIndex == kNumNoIndex)

+    return S_OK;

+  // for (int ttt = 0; ttt < 1; ttt++) {

+  const unsigned kTempSize = 256;

+  char temp[kTempSize];

+  unsigned pos = kTempSize;

+  temp[--pos] = 0;

+ 

+  size_t startPos = _db.FoCodersDataOffset[folderIndex];

+  const Byte *p = _db.CodersData + startPos;

+  size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;

+  CInByte2 inByte;

+  inByte.Init(p, size);

+  

+  // numCoders == 0 ???

+  CNum numCoders = inByte.ReadNum();

+  bool needSpace = false;

+  for (; numCoders != 0; numCoders--, needSpace = true)

+  {

+    if (pos < 32) // max size of property

+      break;

+    Byte mainByte = inByte.ReadByte();

+    unsigned idSize = (mainByte & 0xF);

+    const Byte *longID = inByte.GetPtr();

+    UInt64 id64 = 0;

+    for (unsigned j = 0; j < idSize; j++)

+      id64 = ((id64 << 8) | longID[j]);

+    inByte.SkipDataNoCheck(idSize);

+

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

+    {

+      inByte.ReadNum(); // NumInStreams

+      inByte.ReadNum(); // NumOutStreams

+    }

+  

+    CNum propsSize = 0;

+    const Byte *props = NULL;

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

+    {

+      propsSize = inByte.ReadNum();

+      props = inByte.GetPtr();

+      inByte.SkipDataNoCheck(propsSize);

+    }

+    

+    const char *name = NULL;

+    char s[32];

+    s[0] = 0;

+    

+    if (id64 <= (UInt32)0xFFFFFFFF)

+    {

+      UInt32 id = (UInt32)id64;

+      if (id == k_LZMA)

+      {

+        name = "LZMA";

+        if (propsSize == 5)

+        {

+          UInt32 dicSize = GetUi32((const Byte *)props + 1);

+          char *dest = s + GetStringForSizeValue(s, dicSize);

+          UInt32 d = props[0];

+          if (d != 0x5D)

+          {

+            UInt32 lc = d % 9;

+            d /= 9;

+            UInt32 pb = d / 5;

+            UInt32 lp = d % 5;

+            if (lc != 3) dest = AddProp32(dest, "lc", lc);

+            if (lp != 0) dest = AddProp32(dest, "lp", lp);

+            if (pb != 2) dest = AddProp32(dest, "pb", pb);

+          }

+        }

+      }

+      else if (id == k_LZMA2)

+      {

+        name = "LZMA2";

+        if (propsSize == 1)

+        {

+          Byte p = props[0];

+          if ((p & 1) == 0)

+            ConvertUInt32ToString((UInt32)((p >> 1) + 12), s);

+          else

+            GetStringForSizeValue(s, 3 << ((p >> 1) + 11));

+        }

+      }

+      else if (id == k_PPMD)

+      {

+        name = "PPMD";

+        if (propsSize == 5)

+        {

+          Byte order = *props;

+          char *dest = s;

+          *dest++ = 'o';

+          ConvertUInt32ToString(order, dest);

+          dest += MyStringLen(dest);

+          dest = MyStpCpy(dest, ":mem");

+          GetStringForSizeValue(dest, GetUi32(props + 1));

+        }

+      }

+      else if (id == k_Delta)

+      {

+        name = "Delta";

+        if (propsSize == 1)

+          ConvertUInt32ToString((UInt32)props[0] + 1, s);

+      }

+      else if (id == k_BCJ2) name = "BCJ2";

+      else if (id == k_BCJ) name = "BCJ";

+      else if (id == k_AES)

+      {

+        name = "7zAES";

+        if (propsSize >= 1)

+        {

+          Byte firstByte = props[0];

+          UInt32 numCyclesPower = firstByte & 0x3F;

+          ConvertUInt32ToString(numCyclesPower, s);

+        }

+      }

+    }

+    

+    if (name)

+    {

+      unsigned nameLen = MyStringLen(name);

+      unsigned propsLen = MyStringLen(s);

+      unsigned totalLen = nameLen + propsLen;

+      if (propsLen != 0)

+        totalLen++;

+      if (needSpace)

+        totalLen++;

+      if (totalLen + 5 >= pos)

+        break;

+      pos -= totalLen;

+      MyStringCopy(temp + pos, name);

+      if (propsLen != 0)

+      {

+        char *dest = temp + pos + nameLen;

+        *dest++ = ':';

+        MyStringCopy(dest, s);

+      }

+      if (needSpace)

+        temp[pos + totalLen - 1] = ' ';

+    }

+    else

+    {

+      UString 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())

+        pos -= ConvertMethodIdToString_Back(temp + pos, id64);

+      else

+      {

+        unsigned len = methodName.Len();

+        if (len + 5 > pos)

+          break;

+        pos -= len;

+        for (unsigned i = 0; i < len; i++)

+          temp[pos + i] = (char)methodName[i];

+      }

+    }

+  }

+  if (numCoders != 0 && pos >= 4)

+  {

+    temp[--pos] = ' ';

+    temp[--pos] = '.';

+    temp[--pos] = '.';

+    temp[--pos] = '.';

+  }

+  return PropVarEm_Set_Str(prop, temp + pos);

+  // }

+}

+

+#endif

+

+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  PropVariant_Clear(value);

+  // COM_TRY_BEGIN

+  // NCOM::CPropVariant prop;

   

   /*

   const CRef2 &ref2 = _refs[index];

@@ -215,14 +557,10 @@
 

   switch(propID)

   {

-    case kpidPath:

-      if (!item.Name.IsEmpty())

-        prop = NItemName::GetOSName(item.Name);

-      break;

-    case kpidIsDir:  prop = item.IsDir; break;

+    case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;

     case kpidSize:

     {

-      prop = item.Size;

+      PropVarEm_Set_UInt64(value, item.Size);

       // prop = ref2.Size;

       break;

     }

@@ -234,122 +572,49 @@
         if (folderIndex != kNumNoIndex)

         {

           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)

-            prop = _db.GetFolderFullPackSize(folderIndex);

+            PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));

           /*

           else

-            prop = (UInt64)0;

+            PropVarEm_Set_UInt64(value, 0);

           */

         }

         else

-          prop = (UInt64)0;

+          PropVarEm_Set_UInt64(value, 0);

       }

       break;

     }

-    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }

-    case kpidCTime:  SetPropFromUInt64Def(_db.CTime, index2, prop); break;

-    case kpidATime:  SetPropFromUInt64Def(_db.ATime, index2, prop); break;

-    case kpidMTime:  SetPropFromUInt64Def(_db.MTime, index2, prop); break;

-    case kpidAttrib:  if (item.AttribDefined) prop = item.Attrib; break;

-    case kpidCRC:  if (item.CrcDefined) prop = item.Crc; break;

-    case kpidEncrypted:  prop = IsEncrypted(index2); break;

-    case kpidIsAnti:  prop = _db.IsItemAnti(index2); break;

-    #ifndef _SFX

-    case kpidMethod:

+    // case kpidIsAux: prop = _db.IsItemAux(index2); break;

+    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }

+    case kpidCTime:  SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;

+    case kpidATime:  SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;

+    case kpidMTime:  SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;

+    case kpidAttrib:  if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;

+    case kpidCRC:  if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;

+    case kpidEncrypted:  PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;

+    case kpidIsAnti:  PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;

+    /*

+    case kpidIsAltStream:  prop = item.IsAltStream; break;

+    case kpidNtSecure:

       {

-        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

-        if (folderIndex != kNumNoIndex)

+        int id = _db.SecureIDs[index];

+        size_t offs = _db.SecureOffsets[id];

+        size_t size = _db.SecureOffsets[id + 1] - offs;

+        if (size >= 0)

         {

-          const CFolder &folderInfo = _db.Folders[folderIndex];

-          UString methodsString;

-          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)

-          {

-            const CCoderInfo &coder = folderInfo.Coders[i];

-            if (!methodsString.IsEmpty())

-              methodsString += L' ';

-

-            UString methodName, propsString;

-            bool methodIsKnown = FindMethod(

-              EXTERNAL_CODECS_VARS

-              coder.MethodID, methodName);

-            

-            if (!methodIsKnown)

-              methodsString += ConvertMethodIdToString(coder.MethodID);

-            else

-            {

-              methodsString += methodName;

-              if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)

-                propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);

-              else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)

-              {

-                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);

-                propsString = GetStringForSizeValue(dicSize);

-              }

-              else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)

-              {

-                Byte p = coder.Props[0];

-                UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));

-                propsString = GetStringForSizeValue(dicSize);

-              }

-              else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)

-              {

-                Byte order = *(const Byte *)coder.Props;

-                propsString = L'o';

-                propsString += ConvertUInt32ToString(order);

-                propsString += L":mem";

-                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);

-                propsString += GetStringForSizeValue(dicSize);

-              }

-              else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)

-              {

-                const Byte *data = (const Byte *)coder.Props;

-                Byte firstByte = *data++;

-                UInt32 numCyclesPower = firstByte & 0x3F;

-                propsString = ConvertUInt32ToString(numCyclesPower);

-                /*

-                if ((firstByte & 0xC0) != 0)

-                {

-                  UInt32 saltSize = (firstByte >> 7) & 1;

-                  UInt32 ivSize = (firstByte >> 6) & 1;

-                  if (coder.Props.GetCapacity() >= 2)

-                  {

-                    Byte secondByte = *data++;

-                    saltSize += (secondByte >> 4);

-                    ivSize += (secondByte & 0x0F);

-                  }

-                }

-                */

-              }

-            }

-            if (!propsString.IsEmpty())

-            {

-              methodsString += L':';

-              methodsString += propsString;

-            }

-            else if (coder.Props.GetCapacity() > 0)

-            {

-              methodsString += L":[";

-              for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)

-              {

-                if (bi > 5 && bi + 1 < coder.Props.GetCapacity())

-                {

-                  methodsString += L"..";

-                  break;

-                }

-                else

-                  AddHexToString(methodsString, coder.Props[bi]);

-              }

-              methodsString += L']';

-            }

-          }

-          prop = methodsString;

+          prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);

         }

+        break;

       }

-      break;

+    */

+

+    case kpidPath: return _db.GetPath_Prop(index, value);

+    #ifndef _SFX

+    case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);

     case kpidBlock:

       {

         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

         if (folderIndex != kNumNoIndex)

-          prop = (UInt32)folderIndex;

+          PropVarEm_Set_UInt32(value, (UInt32)folderIndex);

       }

       break;

     case kpidPackedSize0:

@@ -358,6 +623,7 @@
     case kpidPackedSize3:

     case kpidPackedSize4:

       {

+        /*

         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

         if (folderIndex != kNumNoIndex)

         {

@@ -372,13 +638,14 @@
         }

         else

           prop = (UInt64)0;

+        */

       }

       break;

     #endif

   }

-  prop.Detach(value);

+  // prop.Detach(value);

   return S_OK;

-  COM_TRY_END

+  // COM_TRY_END

 }

 

 STDMETHODIMP CHandler::Open(IInStream *stream,

@@ -390,6 +657,7 @@
   #ifndef _SFX

   _fileInfoPopIDs.Clear();

   #endif

+  

   try

   {

     CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;

@@ -397,31 +665,30 @@
     #ifndef _NO_CRYPTO

     CMyComPtr<ICryptoGetTextPassword> getTextPassword;

     if (openArchiveCallback)

-    {

-      openArchiveCallbackTemp.QueryInterface(

-          IID_ICryptoGetTextPassword, &getTextPassword);

-    }

+      openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);

     #endif

+

     CInArchive archive;

+    _db.IsArc = false;

     RINOK(archive.Open(stream, maxCheckStartPosition));

-    #ifndef _NO_CRYPTO

-    _passwordIsDefined = false;

-    UString password;

-    #endif

+    _db.IsArc = true;

+    

     HRESULT result = archive.ReadDatabase(

-      EXTERNAL_CODECS_VARS

-      _db

-      #ifndef _NO_CRYPTO

-      , getTextPassword, _passwordIsDefined

-      #endif

-      );

+        EXTERNAL_CODECS_VARS

+        _db

+        #ifndef _NO_CRYPTO

+          , getTextPassword, _isEncrypted, _passwordIsDefined

+        #endif

+        );

     RINOK(result);

-    _db.Fill();

+    

     _inStream = stream;

   }

   catch(...)

   {

     Close();

+    // return E_INVALIDARG;

+    // we must return out_of_memory here

     return S_FALSE;

   }

   // _inStream = stream;

@@ -437,6 +704,10 @@
   COM_TRY_BEGIN

   _inStream.Release();

   _db.Clear();

+  #ifndef _NO_CRYPTO

+  _isEncrypted = false;

+  _passwordIsDefined = false;

+  #endif

   return S_OK;

   COM_TRY_END

 }

@@ -444,16 +715,16 @@
 #ifdef __7Z_SET_PROPERTIES

 #ifdef EXTRACT_ONLY

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

   const UInt32 numProcessors = NSystem::GetNumberOfProcessors();

   _numThreads = numProcessors;

 

-  for (int i = 0; i < numProperties; i++)

+  for (UInt32 i = 0; i < numProps; i++)

   {

     UString name = names[i];

-    name.MakeUpper();

+    name.MakeLower_Ascii();

     if (name.IsEmpty())

       return E_INVALIDARG;

     const PROPVARIANT &value = values[i];

@@ -461,9 +732,9 @@
     int index = ParseStringToUInt32(name, number);

     if (index == 0)

     {

-      if(name.Left(2).CompareNoCase(L"MT") == 0)

+      if (name.IsPrefixedBy(L"mt"))

       {

-        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));

+        RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));

         continue;

       }

       else

diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
old mode 100755
new mode 100644
index c0fd0e0..e7a80d8
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,6 +18,16 @@
 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

@@ -31,11 +41,53 @@
 #endif

 

 

+#ifndef EXTRACT_ONLY

+

+class COutHandler: public CMultiMethodProps

+{

+  HRESULT SetSolidFromString(const UString &s);

+  HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);

+public:

+  bool _removeSfxBlock;

+  

+  UInt64 _numSolidFiles;

+  UInt64 _numSolidBytes;

+  bool _numSolidBytesDefined;

+  bool _solidExtension;

+

+  bool _compressHeaders;

+  bool _encryptHeadersSpecified;

+  bool _encryptHeaders;

+  // bool _useParents; 9.26

+

+  CBoolPair Write_CTime;

+  CBoolPair Write_ATime;

+  CBoolPair Write_MTime;

+

+  bool _volumeMode;

+

+  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }

+  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }

+  void InitSolid()

+  {

+    InitSolidFiles();

+    InitSolidSize();

+    _solidExtension = false;

+    _numSolidBytesDefined = false;

+  }

+

+  void InitProps();

+

+  COutHandler() { InitProps(); }

+

+  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);

+};

+

+#endif

+

 class CHandler:

-  #ifndef EXTRACT_ONLY

-  public NArchive::COutHandler,

-  #endif

   public IInArchive,

+  public IArchiveGetRawProps,

   #ifdef __7Z_SET_PROPERTIES

   public ISetProperties,

   #endif

@@ -44,9 +96,13 @@
   #endif

   PUBLIC_ISetCompressCodecsInfo

   public CMyUnknownImp

+  #ifndef EXTRACT_ONLY

+  , public COutHandler

+  #endif

 {

 public:

   MY_QUERYINTERFACE_BEGIN2(IInArchive)

+  MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)

   #ifdef __7Z_SET_PROPERTIES

   MY_QUERYINTERFACE_ENTRY(ISetProperties)

   #endif

@@ -58,9 +114,10 @@
   MY_ADDREF_RELEASE

 

   INTERFACE_IInArchive(;)

+  INTERFACE_IArchiveGetRawProps(;)

 

   #ifdef __7Z_SET_PROPERTIES

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);

   #endif

 

   #ifndef EXTRACT_ONLY

@@ -73,8 +130,9 @@
 

 private:

   CMyComPtr<IInStream> _inStream;

-  NArchive::N7z::CArchiveDatabaseEx _db;

+  NArchive::N7z::CDbEx _db;

   #ifndef _NO_CRYPTO

+  bool _isEncrypted;

   bool _passwordIsDefined;

   #endif

 

@@ -90,24 +148,26 @@
   

   CRecordVector<CBind> _binds;

 

-  HRESULT SetCompressionMethod(CCompressionMethodMode &method,

+  HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);

+  HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);

+  void AddDefaultMethod();

+  HRESULT SetMainMethod(CCompressionMethodMode &method,

       CObjectVector<COneMethodInfo> &methodsInfo

       #ifndef _7ZIP_ST

       , UInt32 numThreads

       #endif

       );

 

-  HRESULT SetCompressionMethod(

-      CCompressionMethodMode &method,

-      CCompressionMethodMode &headerMethod);

 

   #endif

 

-  bool IsEncrypted(UInt32 index2) const;

+  bool IsFolderEncrypted(CNum folderIndex) const;

   #ifndef _SFX

 

   CRecordVector<UInt64> _fileInfoPopIDs;

   void FillPopIDs();

+  void AddMethodName(AString &s, UInt64 id);

+  HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;

 

   #endif

 

diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
old mode 100755
new mode 100644
index 59d6269..aff5809
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -2,12 +2,9 @@
 

 #include "StdAfx.h"

 

-#include "../../../Windows/PropVariant.h"

-

 #include "../../../Common/ComTry.h"

 #include "../../../Common/StringToInt.h"

-

-#include "../../ICoder.h"

+#include "../../../Common/Wildcard.h"

 

 #include "../Common/ItemNameUtils.h"

 #include "../Common/ParseProperties.h"

@@ -21,24 +18,19 @@
 namespace NArchive {

 namespace N7z {

 

-static const wchar_t *kLZMAMethodName = L"LZMA";

-static const wchar_t *kCopyMethod = L"Copy";

-static const wchar_t *kDefaultMethodName = kLZMAMethodName;

+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 UInt32 kLzmaAlgorithmX5 = 1;

-static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";

-static const UInt32 kDictionaryForHeaders =

+static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";

+static const UInt32 k_NumFastBytes_ForHeaders = 273;

+static const UInt32 k_Level_ForHeaders = 5;

+static const UInt32 k_Dictionary_ForHeaders =

   #ifdef UNDER_CE

-  1 << 18

+  1 << 18;

   #else

-  1 << 20

+  1 << 20;

   #endif

-;

-static const UInt32 kNumFastBytesForHeaders = 273;

-static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;

-

-static inline bool IsCopyMethod(const UString &methodName)

-  { return (methodName.CompareNoCase(kCopyMethod) == 0); }

 

 STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)

 {

@@ -46,132 +38,112 @@
   return S_OK;

 }

 

-HRESULT CHandler::SetCompressionMethod(

-    CCompressionMethodMode &methodMode,

-    CCompressionMethodMode &headerMethod)

+HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)

 {

-  HRESULT res = SetCompressionMethod(methodMode, _methods

-  #ifndef _7ZIP_ST

-  , _numThreads

-  #endif

-  );

-  RINOK(res);

-  methodMode.Binds = _binds;

-

-  if (_compressHeaders)

-  {

-    // headerMethod.Methods.Add(methodMode.Methods.Back());

-

-    CObjectVector<COneMethodInfo> headerMethodInfoVector;

-    COneMethodInfo oneMethodInfo;

-    oneMethodInfo.MethodName = kLZMAMethodName;

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kMatchFinder;

-      prop.Value = kLzmaMatchFinderForHeaders;

-      oneMethodInfo.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kAlgorithm;

-      prop.Value = kAlgorithmForHeaders;

-      oneMethodInfo.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kNumFastBytes;

-      prop.Value = (UInt32)kNumFastBytesForHeaders;

-      oneMethodInfo.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kDictionarySize;

-      prop.Value = (UInt32)kDictionaryForHeaders;

-      oneMethodInfo.Props.Add(prop);

-    }

-    headerMethodInfoVector.Add(oneMethodInfo);

-    HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector

-      #ifndef _7ZIP_ST

-      , 1

-      #endif

-    );

-    RINOK(res);

-  }

+  if (!FindMethod(

+      EXTERNAL_CODECS_VARS

+      m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))

+    return E_INVALIDARG;

+  (CProps &)dest = (CProps &)m;

   return S_OK;

 }

 

-HRESULT CHandler::SetCompressionMethod(

+HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)

+{

+  if (!_compressHeaders)

+    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.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);

+  m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);

+  m.AddNumThreadsProp(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);

+  }

+}

+

+HRESULT CHandler::SetMainMethod(

     CCompressionMethodMode &methodMode,

-    CObjectVector<COneMethodInfo> &methodsInfo

+    CObjectVector<COneMethodInfo> &methods

     #ifndef _7ZIP_ST

     , UInt32 numThreads

     #endif

     )

 {

-  UInt32 level = _level;

-  

-  if (methodsInfo.IsEmpty())

-  {

-    COneMethodInfo oneMethodInfo;

-    oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);

-    methodsInfo.Add(oneMethodInfo);

-  }

+  AddDefaultMethod();

+

+  const UInt64 kSolidBytes_Min = (1 << 24);

+  const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;

 

   bool needSolid = false;

-  for(int i = 0; i < methodsInfo.Size(); i++)

+  FOR_VECTOR (i, methods)

   {

-    COneMethodInfo &oneMethodInfo = methodsInfo[i];

-    SetCompressionMethod2(oneMethodInfo

+    COneMethodInfo &oneMethodInfo = methods[i];

+    SetGlobalLevelAndThreads(oneMethodInfo

       #ifndef _7ZIP_ST

       , numThreads

       #endif

       );

 

-    if (!IsCopyMethod(oneMethodInfo.MethodName))

-      needSolid = true;

-

     CMethodFull methodFull;

-

-    if (!FindMethod(

-        EXTERNAL_CODECS_VARS

-        oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))

-      return E_INVALIDARG;

-    methodFull.Props = oneMethodInfo.Props;

+    RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));

     methodMode.Methods.Add(methodFull);

 

-    if (!_numSolidBytesDefined)

+    if (methodFull.Id != k_Copy)

+      needSolid = true;

+

+    if (_numSolidBytesDefined)

+      continue;

+

+    UInt32 dicSize;

+    switch (methodFull.Id)

     {

-      for (int j = 0; j < methodFull.Props.Size(); j++)

-      {

-        const CProp &prop = methodFull.Props[j];

-        if ((prop.Id == NCoderPropID::kDictionarySize ||

-             prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)

-        {

-          _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;

-          const UInt64 kMinSize = (1 << 24);

-          if (_numSolidBytes < kMinSize)

-            _numSolidBytes = kMinSize;

-          _numSolidBytesDefined = true;

-          break;

-        }

-      }

+      case k_LZMA:

+      case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;

+      case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;

+      case k_Deflate: dicSize = (UInt32)1 << 15; break;

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

+    _numSolidBytesDefined = true;

   }

 

-  if (!needSolid && !_numSolidBytesDefined)

-  {

-    _numSolidBytesDefined = true;

-    _numSolidBytes  = 0;

-  }

+  if (!_numSolidBytesDefined)

+    if (needSolid)

+      _numSolidBytes = kSolidBytes_Max;

+    else

+      _numSolidBytes = 0;

+  _numSolidBytesDefined = true;

   return S_OK;

 }

 

-static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined)

+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined)

 {

-  ft = 0;

-  ftDefined = false;

-  if (!writeTime)

-    return S_OK;

+  // ft = 0;

+  // ftDefined = false;

   NCOM::CPropVariant prop;

   RINOK(updateCallback->GetProperty(index, propID, &prop));

   if (prop.vt == VT_FILETIME)

@@ -181,15 +153,87 @@
   }

   else if (prop.vt != VT_EMPTY)

     return E_INVALIDARG;

+  else

+  {

+    ft = 0;

+    ftDefined = false;

+  }

   return S_OK;

 }

 

+/*

+

+#ifdef _WIN32

+static const wchar_t kDirDelimiter1 = L'\\';

+#endif

+static const wchar_t kDirDelimiter2 = L'/';

+

+static inline bool IsCharDirLimiter(wchar_t c)

+{

+  return (

+    #ifdef _WIN32

+    c == kDirDelimiter1 ||

+    #endif

+    c == kDirDelimiter2);

+}

+

+static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)

+{

+  CTreeFolder &tf = treeFolders[cur];

+  tf.SortIndex = curSortIndex++;

+  for (int i = 0; i < tf.SubFolders.Size(); i++)

+    curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);

+  tf.SortIndexEnd = curSortIndex;

+  return curSortIndex;

+}

+

+static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)

+{

+  const CIntVector &subFolders = treeFolders[cur].SubFolders;

+  int left = 0, right = subFolders.Size();

+  insertPos = -1;

+  for (;;)

+  {

+    if (left == right)

+    {

+      insertPos = left;

+      return -1;

+    }

+    int mid = (left + right) / 2;

+    int midFolder = subFolders[mid];

+    int compare = CompareFileNames(name, treeFolders[midFolder].Name);

+    if (compare == 0)

+      return midFolder;

+    if (compare < 0)

+      right = mid;

+    else

+      left = mid + 1;

+  }

+}

+

+static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)

+{

+  int insertPos;

+  int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);

+  if (folderIndex < 0)

+  {

+    folderIndex = treeFolders.Size();

+    CTreeFolder &newFolder = treeFolders.AddNew();

+    newFolder.Parent = cur;

+    newFolder.Name = name;

+    treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);

+  }

+  // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;

+  return folderIndex;

+}

+*/

+

 STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,

     IArchiveUpdateCallback *updateCallback)

 {

   COM_TRY_BEGIN

 

-  const CArchiveDatabaseEx *db = 0;

+  const CDbEx *db = 0;

   #ifdef _7Z_VOL

   if (_volumes.Size() > 1)

     return E_FAIL;

@@ -204,8 +248,35 @@
     db = &_db;

   #endif

 

+  /*

+  CMyComPtr<IArchiveGetRawProps> getRawProps;

+  updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);

+

+  CUniqBlocks secureBlocks;

+  secureBlocks.AddUniq(NULL, 0);

+

+  CObjectVector<CTreeFolder> treeFolders;

+  {

+    CTreeFolder folder;

+    folder.Parent = -1;

+    treeFolders.Add(folder);

+  }

+  */

+

   CObjectVector<CUpdateItem> updateItems;

-  

+

+  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 (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();

+    if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();

+    if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();

+  }

+

+  UString s;

+

   for (UInt32 i = 0; i < numItems; i++)

   {

     Int32 newData, newProps;

@@ -221,24 +292,32 @@
     ui.IsAnti = false;

     ui.Size = 0;

 

+    UString name;

+    // bool isAltStream = false;

     if (ui.IndexInArchive != -1)

     {

-      if (db == 0 || ui.IndexInArchive >= db->Files.Size())

+      if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size())

         return E_INVALIDARG;

       const CFileItem &fi = db->Files[ui.IndexInArchive];

-      ui.Name = fi.Name;

+      if (!ui.NewProps)

+      {

+        _db.GetPath(ui.IndexInArchive, name);

+      }

       ui.IsDir = fi.IsDir;

       ui.Size = fi.Size;

+      // isAltStream = fi.IsAltStream;

       ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);

       

-      ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);

-      ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);

-      ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);

+      if (!ui.NewProps)

+      {

+        ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);

+        ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);

+        ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);

+      }

     }

 

     if (ui.NewProps)

     {

-      bool nameIsDefined;

       bool folderStatusIsDefined;

       {

         NCOM::CPropVariant prop;

@@ -255,21 +334,35 @@
       }

       

       // we need MTime to sort files.

-      RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined));

-      RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined));

-      RINOK(GetTime(updateCallback, i, true,       kpidMTime, ui.MTime, ui.MTimeDefined));

+      if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined));

+      if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined));

+      if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined));

+

+      /*

+      if (getRawProps)

+      {

+        const void *data;

+        UInt32 dataSize;

+        UInt32 propType;

+

+        getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);

+        if (dataSize != 0 && propType != NPropDataType::kRaw)

+          return E_FAIL;

+        ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);

+      }

+      */

 

       {

         NCOM::CPropVariant prop;

         RINOK(updateCallback->GetProperty(i, kpidPath, &prop));

         if (prop.vt == VT_EMPTY)

-          nameIsDefined = false;

+        {

+        }

         else if (prop.vt != VT_BSTR)

           return E_INVALIDARG;

         else

         {

-          ui.Name = NItemName::MakeLegalName(prop.bstrVal);

-          nameIsDefined = true;

+          name = NItemName::MakeLegalName(prop.bstrVal);

         }

       }

       {

@@ -297,6 +390,19 @@
           ui.IsAnti = (prop.boolVal != VARIANT_FALSE);

       }

 

+      /*

+      {

+        NCOM::CPropVariant prop;

+        RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));

+        if (prop.vt == VT_EMPTY)

+          isAltStream = false;

+        else if (prop.vt != VT_BOOL)

+          return E_INVALIDARG;

+        else

+          isAltStream = (prop.boolVal != VARIANT_FALSE);

+      }

+      */

+

       if (ui.IsAnti)

       {

         ui.AttribDefined = false;

@@ -311,6 +417,80 @@
       if (!folderStatusIsDefined && ui.AttribDefined)

         ui.SetDirStatusFromAttrib();

     }

+    else

+    {

+      /*

+      if (_db.SecureIDs.IsEmpty())

+        ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);

+      else

+      {

+        int id = _db.SecureIDs[ui.IndexInArchive];

+        size_t offs = _db.SecureOffsets[id];

+        size_t size = _db.SecureOffsets[id + 1] - offs;

+        ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);

+      }

+      */

+    }

+

+    /*

+    {

+      int folderIndex = 0;

+      if (_useParents)

+      {

+        int j;

+        s.Empty();

+        for (j = 0; j < name.Len(); j++)

+        {

+          wchar_t c = name[j];

+          if (IsCharDirLimiter(c))

+          {

+            folderIndex = AddFolder(treeFolders, folderIndex, s);

+            s.Empty();

+            continue;

+          }

+          s += c;

+        }

+        if (isAltStream)

+        {

+          int colonPos = s.Find(':');

+          if (colonPos < 0)

+          {

+            // isAltStream = false;

+            return E_INVALIDARG;

+          }

+          UString mainName = s.Left(colonPos);

+          int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);

+          if (treeFolders[newFolderIndex].UpdateItemIndex < 0)

+          {

+            for (int j = updateItems.Size() - 1; j >= 0; j--)

+            {

+              CUpdateItem &ui2 = updateItems[j];

+              if (ui2.ParentFolderIndex == folderIndex

+                  && ui2.Name == mainName)

+              {

+                ui2.TreeFolderIndex = newFolderIndex;

+                treeFolders[newFolderIndex].UpdateItemIndex = j;

+              }

+            }

+          }

+          folderIndex = newFolderIndex;

+          s.Delete(0, colonPos + 1);

+        }

+        ui.Name = s;

+      }

+      else

+        ui.Name = name;

+      ui.IsAltStream = isAltStream;

+      ui.ParentFolderIndex = folderIndex;

+      ui.TreeFolderIndex = -1;

+      if (ui.IsDir && !s.IsEmpty())

+      {

+        ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);

+        treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();

+      }

+    }

+    */

+    ui.Name = name;

 

     if (ui.NewData)

     {

@@ -325,8 +505,27 @@
     updateItems.Add(ui);

   }

 

+  /*

+  FillSortIndex(treeFolders, 0, 0);

+  for (i = 0; i < (UInt32)updateItems.Size(); i++)

+  {

+    CUpdateItem &ui = updateItems[i];

+    ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;

+    ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;

+  }

+  */

+

   CCompressionMethodMode methodMode, headerMethod;

-  RINOK(SetCompressionMethod(methodMode, headerMethod));

+

+  HRESULT res = SetMainMethod(methodMode, _methods

+    #ifndef _7ZIP_ST

+    , _numThreads

+    #endif

+    );

+  RINOK(res);

+  methodMode.Binds = _binds;

+

+  RINOK(SetHeaderMethod(headerMethod));

   #ifndef _7ZIP_ST

   methodMode.NumThreads = _numThreads;

   headerMethod.NumThreads = 1;

@@ -335,17 +534,17 @@
   CMyComPtr<ICryptoGetTextPassword2> getPassword2;

   updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);

 

+  methodMode.PasswordIsDefined = false;

+  methodMode.Password.Empty();

   if (getPassword2)

   {

     CMyComBSTR password;

     Int32 passwordIsDefined;

     RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));

     methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);

-    if (methodMode.PasswordIsDefined)

+    if (methodMode.PasswordIsDefined && (BSTR)password)

       methodMode.Password = password;

   }

-  else

-    methodMode.PasswordIsDefined = false;

 

   bool compressMainHeader = _compressHeaders;  // check it

 

@@ -373,13 +572,16 @@
   CUpdateOptions options;

   options.Method = &methodMode;

   options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;

-  options.UseFilters = _level != 0 && _autoFilter;

-  options.MaxFilter = _level >= 8;

+  int level = GetLevel();

+  options.UseFilters = level != 0 && _autoFilter;

+  options.MaxFilter = level >= 8;

 

   options.HeaderOptions.CompressMainHeader = compressMainHeader;

-  options.HeaderOptions.WriteCTime = WriteCTime;

-  options.HeaderOptions.WriteATime = WriteATime;

-  options.HeaderOptions.WriteMTime = WriteMTime;

+  /*

+  options.HeaderOptions.WriteCTime = Write_CTime;

+  options.HeaderOptions.WriteATime = Write_ATime;

+  options.HeaderOptions.WriteMTime = Write_MTime;

+  */

   

   options.NumSolidFiles = _numSolidFiles;

   options.NumSolidBytes = _numSolidBytes;

@@ -388,12 +590,24 @@
   options.VolumeMode = _volumeMode;

 

   COutArchive archive;

-  CArchiveDatabase newDatabase;

+  CArchiveDatabaseOut newDatabase;

 

   CMyComPtr<ICryptoGetTextPassword> getPassword;

   updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);

   

-  HRESULT res = Update(

+  /*

+  if (secureBlocks.Sorted.Size() > 1)

+  {

+    secureBlocks.GetReverseMap();

+    for (int i = 0; i < updateItems.Size(); i++)

+    {

+      int &secureIndex = updateItems[i].SecureIndex;

+      secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];

+    }

+  }

+  */

+

+  res = Update(

       EXTERNAL_CODECS_VARS

       #ifdef _7Z_VOL

       volume ? volume->Stream: 0,

@@ -403,6 +617,8 @@
       db,

       #endif

       updateItems,

+      // treeFolders,

+      // secureBlocks,

       archive, newDatabase, outStream, updateCallback, options

       #ifndef _NO_CRYPTO

       , getPassword

@@ -426,7 +642,7 @@
   if (index == 0)

     return E_INVALIDARG;

   srcString.Delete(0, index);

-  if (srcString[0] == 'S')

+  if (srcString[0] == 's')

   {

     srcString.Delete(0);

     int index = ParseStringToUInt32(srcString, stream);

@@ -437,38 +653,173 @@
   return S_OK;

 }

 

-static HRESULT GetBindInfo(UString &srcString, CBind &bind)

+void COutHandler::InitProps()

 {

-  RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));

-  if (srcString[0] != ':')

-    return E_INVALIDARG;

-  srcString.Delete(0);

-  RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));

-  if (!srcString.IsEmpty())

-    return E_INVALIDARG;

+  CMultiMethodProps::Init();

+

+  _removeSfxBlock = false;

+  _compressHeaders = true;

+  _encryptHeadersSpecified = false;

+  _encryptHeaders = false;

+  // _useParents = false;

+  

+  Write_CTime.Init();

+  Write_ATime.Init();

+  Write_MTime.Init();

+

+  _volumeMode = false;

+  InitSolid();

+}

+

+HRESULT COutHandler::SetSolidFromString(const UString &s)

+{

+  UString s2 = s;

+  s2.MakeLower_Ascii();

+  for (unsigned i = 0; i < s2.Len();)

+  {

+    const wchar_t *start = ((const wchar_t *)s2) + i;

+    const wchar_t *end;

+    UInt64 v = ConvertStringToUInt64(start, &end);

+    if (start == end)

+    {

+      if (s2[i++] != 'e')

+        return E_INVALIDARG;

+      _solidExtension = true;

+      continue;

+    }

+    i += (int)(end - start);

+    if (i == s2.Len())

+      return E_INVALIDARG;

+    wchar_t c = s2[i++];

+    if (c == 'f')

+    {

+      if (v < 1)

+        v = 1;

+      _numSolidFiles = v;

+    }

+    else

+    {

+      unsigned numBits;

+      switch (c)

+      {

+        case 'b': numBits =  0; break;

+        case 'k': numBits = 10; break;

+        case 'm': numBits = 20; break;

+        case 'g': numBits = 30; break;

+        case 't': numBits = 40; break;

+        default: return E_INVALIDARG;

+      }

+      _numSolidBytes = (v << numBits);

+      _numSolidBytesDefined = true;

+    }

+  }

   return S_OK;

 }

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)

+HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)

+{

+  bool isSolid;

+  switch (value.vt)

+  {

+    case VT_EMPTY: isSolid = true; break;

+    case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;

+    case VT_BSTR:

+      if (StringToBool(value.bstrVal, isSolid))

+        break;

+      return SetSolidFromString(value.bstrVal);

+    default: return E_INVALIDARG;

+  }

+  if (isSolid)

+    InitSolid();

+  else

+    _numSolidFiles = 1;

+  return S_OK;

+}

+

+static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)

+{

+  RINOK(PROPVARIANT_to_bool(prop, dest.Val));

+  dest.Def = true;

+  return S_OK;

+}

+

+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)

+{

+  UString name = nameSpec;

+  name.MakeLower_Ascii();

+  if (name.IsEmpty())

+    return E_INVALIDARG;

+  

+  if (name[0] == L's')

+  {

+    name.Delete(0);

+    if (name.IsEmpty())

+      return SetSolidFromPROPVARIANT(value);

+    if (value.vt != VT_EMPTY)

+      return E_INVALIDARG;

+    return SetSolidFromString(name);

+  }

+  

+  UInt32 number;

+  int index = ParseStringToUInt32(name, number);

+  UString realName = name.Ptr(index);

+  if (index == 0)

+  {

+    if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);

+    if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);

+    // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);

+    

+    if (name.IsEqualTo("hcf"))

+    {

+      bool compressHeadersFull = true;

+      RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));

+      return compressHeadersFull ? S_OK: E_INVALIDARG;

+    }

+    

+    if (name.IsEqualTo("he"))

+    {

+      RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));

+      _encryptHeadersSpecified = true;

+      return S_OK;

+    }

+    

+    if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime);

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

+  }

+  return CMultiMethodProps::SetProperty(name, value);

+}

+

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

   _binds.Clear();

-  BeforeSetProperty();

+  InitProps();

 

-  for (int i = 0; i < numProperties; i++)

+  for (UInt32 i = 0; i < numProps; i++)

   {

     UString name = names[i];

-    name.MakeUpper();

+    name.MakeLower_Ascii();

     if (name.IsEmpty())

       return E_INVALIDARG;

 

     const PROPVARIANT &value = values[i];

 

-    if (name[0] == 'B')

+    if (name[0] == 'b')

     {

+      if (value.vt != VT_EMPTY)

+        return E_INVALIDARG;

       name.Delete(0);

       CBind bind;

-      RINOK(GetBindInfo(name, bind));

+      RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));

+      if (name[0] != ':')

+        return E_INVALIDARG;

+      name.Delete(0);

+      RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));

+      if (!name.IsEmpty())

+        return E_INVALIDARG;

       _binds.Add(bind);

       continue;

     }

@@ -476,6 +827,47 @@
     RINOK(SetProperty(name, value));

   }

 

+  unsigned numEmptyMethods = GetNumEmptyMethods();

+  if (numEmptyMethods > 0)

+  {

+    unsigned k;

+    for (k = 0; k < _binds.Size(); k++)

+    {

+      const CBind &bind = _binds[k];

+      if (bind.InCoder < (UInt32)numEmptyMethods ||

+          bind.OutCoder < (UInt32)numEmptyMethods)

+        return E_INVALIDARG;

+    }

+    for (k = 0; k < _binds.Size(); k++)

+    {

+      CBind &bind = _binds[k];

+      bind.InCoder -= (UInt32)numEmptyMethods;

+      bind.OutCoder -= (UInt32)numEmptyMethods;

+    }

+    _methods.DeleteFrontal(numEmptyMethods);

+  }

+  

+  AddDefaultMethod();

+

+  if (!_filterMethod.MethodName.IsEmpty())

+  {

+    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())

+      return E_INVALIDARG;

+  }

+

   return S_OK;

   COM_TRY_END

 }

diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp
old mode 100755
new mode 100644
index d93670c..de39909
--- a/CPP/7zip/Archive/7z/7zHeader.cpp
+++ b/CPP/7zip/Archive/7z/7zHeader.cpp
@@ -1,6 +1,7 @@
 // 7zHeader.cpp

 

 #include "StdAfx.h"

+

 #include "7zHeader.h"

 

 namespace NArchive {

@@ -11,4 +12,8 @@
 Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};

 #endif

 

+// We can change signature. So file doesn't contain correct signature.

+// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };

+// static SignatureInitializer g_SignatureInitializer;

+

 }}

diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
old mode 100755
new mode 100644
index 57f455b..78b5061
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -3,12 +3,12 @@
 #ifndef __7Z_HEADER_H

 #define __7Z_HEADER_H

 

-#include "../../../Common/Types.h"

+#include "../../../Common/MyTypes.h"

 

 namespace NArchive {

 namespace N7z {

 

-const int kSignatureSize = 6;

+const unsigned kSignatureSize = 6;

 extern Byte kSignature[kSignatureSize];

 

 // #define _7Z_VOL

@@ -82,13 +82,17 @@
     kCTime,

     kATime,

     kMTime,

-    kWinAttributes,

+    kWinAttrib,

     kComment,

 

     kEncodedHeader,

 

     kStartPos,

     kDummy

+

+    // kNtSecure,

+    // kParent,

+    // kIsAux

   };

 }

 

diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
old mode 100755
new mode 100644
index f418bb1..5a85507
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -2,6 +2,12 @@
 

 #include "StdAfx.h"

 

+#ifdef _WIN32

+#include <wchar.h>

+#else

+#include <ctype.h>

+#endif

+

 #include "../../../../C/7zCrc.h"

 #include "../../../../C/CpuArch.h"

 

@@ -20,15 +26,21 @@
 #define FORMAT_7Z_RECOVERY

 #endif

 

+using namespace NWindows;

+using namespace NCOM;

+

 namespace NArchive {

 namespace N7z {

 

-static void BoolVector_Fill_False(CBoolVector &v, int size)

+static const UInt32 k_LZMA2 = 0x21;

+static const UInt32 k_LZMA  = 0x030101;

+

+static void BoolVector_Fill_False(CBoolVector &v, unsigned size)

 {

-  v.Clear();

-  v.Reserve(size);

-  for (int i = 0; i < size; i++)

-    v.Add(false);

+  v.ClearAndSetSize(size);

+  bool *p = &v[0];

+  for (unsigned i = 0; i < size; i++)

+    p[i] = false;

 }

 

 static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)

@@ -40,11 +52,11 @@
   return res;

 }

 

-bool CFolder::CheckStructure() const

+bool CFolder::CheckStructure(unsigned numUnpackSizes) const

 {

-  const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it

-  const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax

-  const int kNumBindsMax = 32;

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

@@ -53,7 +65,7 @@
     CBoolVector v;

     BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());

     

-    int i;

+    unsigned i;

     for (i = 0; i < BindPairs.Size(); i++)

       if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))

         return false;

@@ -61,19 +73,19 @@
       if (BoolVector_GetAndSet(v, PackStreams[i]))

         return false;

     

-    BoolVector_Fill_False(v, UnpackSizes.Size());

+    BoolVector_Fill_False(v, numUnpackSizes);

     for (i = 0; i < BindPairs.Size(); i++)

       if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))

         return false;

   }

   

   UInt32 mask[kMaskSize];

-  int i;

+  unsigned i;

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

     mask[i] = 0;

 

   {

-    CIntVector inStreamToCoder, outStreamToCoder;

+    CUIntVector inStreamToCoder, outStreamToCoder;

     for (i = 0; i < Coders.Size(); i++)

     {

       CNum j;

@@ -92,7 +104,7 @@
   }

   

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

-    for (int j = 0; j < kMaskSize; j++)

+    for (unsigned j = 0; j < kMaskSize; j++)

       if (((1 << j) & mask[i]) != 0)

         mask[i] |= mask[j];

 

@@ -104,43 +116,23 @@
 }

 

 class CInArchiveException {};

+class CUnsupportedFeatureException: public CInArchiveException {};

 

 static void ThrowException() { throw CInArchiveException(); }

 static inline void ThrowEndOfData()   { ThrowException(); }

-static inline void ThrowUnsupported() { ThrowException(); }

+static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }

 static inline void ThrowIncorrect()   { ThrowException(); }

-static inline void ThrowUnsupportedVersion() { ThrowException(); }

-

-/*

-class CInArchiveException

-{

-public:

-  enum CCauseType

-  {

-    kUnsupportedVersion = 0,

-    kUnsupported,

-    kIncorrect,

-    kEndOfData

-  } Cause;

-  CInArchiveException(CCauseType cause): Cause(cause) {};

-};

-

-static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); }

-static void ThrowEndOfData()   { ThrowException(CInArchiveException::kEndOfData); }

-static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); }

-static void ThrowIncorrect()   { ThrowException(CInArchiveException::kIncorrect); }

-static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); }

-*/

 

 class CStreamSwitch

 {

   CInArchive *_archive;

   bool _needRemove;

+  bool _needUpdatePos;

 public:

-  CStreamSwitch(): _needRemove(false) {}

+  CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}

   ~CStreamSwitch() { Remove(); }

   void Remove();

-  void Set(CInArchive *archive, const Byte *data, size_t size);

+  void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);

   void Set(CInArchive *archive, const CByteBuffer &byteBuffer);

   void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);

 };

@@ -149,22 +141,25 @@
 {

   if (_needRemove)

   {

-    _archive->DeleteByteStream();

+    if (_archive->_inByteBack->GetRem() != 0)

+      _archive->ThereIsHeaderError = true;

+    _archive->DeleteByteStream(_needUpdatePos);

     _needRemove = false;

   }

 }

 

-void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)

+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)

 {

   Remove();

   _archive = archive;

   _archive->AddByteStream(data, size);

   _needRemove = true;

+  _needUpdatePos = needUpdatePos;

 }

 

 void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)

 {

-  Set(archive, byteBuffer, byteBuffer.GetCapacity());

+  Set(archive, byteBuffer, byteBuffer.Size(), false);

 }

 

 void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)

@@ -173,13 +168,22 @@
   Byte external = archive->ReadByte();

   if (external != 0)

   {

-    int dataIndex = (int)archive->ReadNum();

-    if (dataIndex < 0 || dataIndex >= dataVector->Size())

+    CNum dataIndex = archive->ReadNum();

+    if (dataIndex >= dataVector->Size())

       ThrowIncorrect();

     Set(archive, (*dataVector)[dataIndex]);

   }

 }

 

+void CInArchive::AddByteStream(const Byte *buf, size_t size)

+{

+  if (_numInByteBufs == kNumBufLevelsMax)

+    ThrowIncorrect();

+  _inByteBack = &_inByteVector[_numInByteBufs++];

+  _inByteBack->Init(buf, size);

+}

+  

+

 Byte CInByte2::ReadByte()

 {

   if (_pos >= _size)

@@ -191,8 +195,8 @@
 {

   if (size > _size - _pos)

     ThrowEndOfData();

-  for (size_t i = 0; i < size; i++)

-    data[i] = _buffer[_pos++];

+  memcpy(data, _buffer + _pos, size);

+  _pos += size;

 }

 

 void CInByte2::SkipData(UInt64 size)

@@ -207,31 +211,75 @@
   SkipData(ReadNumber());

 }

 

-UInt64 CInByte2::ReadNumber()

+static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)

 {

-  if (_pos >= _size)

-    ThrowEndOfData();

-  Byte firstByte = _buffer[_pos++];

-  Byte mask = 0x80;

-  UInt64 value = 0;

-  for (int i = 0; i < 8; i++)

+  if (size == 0)

+  {

+    processed = 0;

+    return 0;

+  }

+  Byte firstByte = *p++;

+  size--;

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

+  {

+    processed = 1;

+    return firstByte;

+  }

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

     {

       UInt64 highPart = firstByte & (mask - 1);

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

+      processed = i + 1;

       return value;

     }

-    if (_pos >= _size)

-      ThrowEndOfData();

-    value |= ((UInt64)_buffer[_pos++] << (8 * i));

+    if (size == 0)

+    {

+      processed = 0;

+      return 0;

+    }

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

+    p++;

+    size--;

     mask >>= 1;

   }

+  processed = 9;

   return value;

 }

 

+UInt64 CInByte2::ReadNumber()

+{

+  size_t processed;

+  UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);

+  if (processed == 0)

+    ThrowEndOfData();

+  _pos += processed;

+  return res;

+}

+

 CNum CInByte2::ReadNum()

 {

+  /*

+  if (_pos < _size)

+  {

+    Byte val = _buffer[_pos];

+    if ((unsigned)val < 0x80)

+    {

+      _pos++;

+      return (unsigned)val;

+    }

+  }

+  */

   UInt64 value = ReadNumber();

   if (value > kNumMax)

     ThrowUnsupported();

@@ -256,48 +304,21 @@
   return res;

 }

 

-void CInByte2::ReadString(UString &s)

-{

-  const Byte *buf = _buffer + _pos;

-  size_t rem = (_size - _pos) / 2 * 2;

-  {

-    size_t i;

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

-      if (buf[i] == 0 && buf[i + 1] == 0)

-        break;

-    if (i == rem)

-      ThrowEndOfData();

-    rem = i;

-  }

-  int len = (int)(rem / 2);

-  if (len < 0 || (size_t)len * 2 != rem)

-    ThrowUnsupported();

-  wchar_t *p = s.GetBuffer(len);

-  int i;

-  for (i = 0; i < len; i++, buf += 2)

-    p[i] = (wchar_t)Get16(buf);

-  s.ReleaseBuffer(len);

-  _pos += rem + 2;

-}

+#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false;

 

 static inline bool TestSignature(const Byte *p)

 {

-  for (int i = 0; i < kSignatureSize; i++)

-    if (p[i] != kSignature[i])

-      return false;

-  return CrcCalc(p + 12, 20) == GetUi32(p + 8);

+  CHECK_SIGNATURE

+  return CrcCalc(p + 12, 20) == Get32(p + 8);

 }

 

 #ifdef FORMAT_7Z_RECOVERY

 static inline bool TestSignature2(const Byte *p)

 {

-  int i;

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

-    if (p[i] != kSignature[i])

-      return false;

-  if (CrcCalc(p + 12, 20) == GetUi32(p + 8))

+  CHECK_SIGNATURE;

+  if (CrcCalc(p + 12, 20) == Get32(p + 8))

     return true;

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

+  for (unsigned i = 8; i < kHeaderSize; i++)

     if (p[i] != 0)

       return false;

   return (p[6] != 0 || p[7] != 0);

@@ -312,48 +333,52 @@
 

   if (TestSignature2(_header))

     return S_OK;

+  if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)

+    return S_FALSE;

 

-  CByteBuffer byteBuffer;

-  const UInt32 kBufferSize = (1 << 16);

-  byteBuffer.SetCapacity(kBufferSize);

-  Byte *buffer = byteBuffer;

-  UInt32 numPrevBytes = kHeaderSize;

-  memcpy(buffer, _header, kHeaderSize);

-  UInt64 curTestPos = _arhiveBeginStreamPosition;

+  const UInt32 kBufSize = 1 << 15;

+  CByteArr buf(kBufSize);

+  memcpy(buf, _header, kHeaderSize);

+  UInt64 offset = 0;

+  

   for (;;)

   {

-    if (searchHeaderSizeLimit != NULL)

-      if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)

-        break;

-    do

+    UInt32 readSize = kBufSize - kHeaderSize;

     {

-      UInt32 numReadBytes = kBufferSize - numPrevBytes;

-      UInt32 processedSize;

-      RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));

-      numPrevBytes += processedSize;

-      if (processedSize == 0)

+      UInt64 rem = *searchHeaderSizeLimit - offset;

+      if (readSize > rem)

+        readSize = (UInt32)rem;

+      if (readSize == 0)

         return S_FALSE;

     }

-    while (numPrevBytes <= kHeaderSize);

-    UInt32 numTests = numPrevBytes - kHeaderSize;

-    for (UInt32 pos = 0; pos < numTests; pos++)

+    UInt32 processed = 0;

+    RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));

+    if (processed == 0)

+      return S_FALSE;

+    for (UInt32 pos = 0;;)

     {

-      for (; buffer[pos] != '7' && pos < numTests; pos++);

-      if (pos == numTests)

-        break;

-      if (TestSignature(buffer + pos))

+      const Byte *p = buf + pos + 1;

+      const Byte *lim = buf + processed;

+      for (; p <= lim; p += 4)

       {

-        memcpy(_header, buffer + pos, kHeaderSize);

-        curTestPos += pos;

-        _arhiveBeginStreamPosition = curTestPos;

-        return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);

+        if (p[0] == '7') break;

+        if (p[1] == '7') { p += 1; break; }

+        if (p[2] == '7') { p += 2; break; }

+        if (p[3] == '7') { p += 3; break; }

+      };

+      if (p > lim)

+        break;

+      pos = (UInt32)(p - buf);

+      if (TestSignature(p))

+      {

+        memcpy(_header, p, kHeaderSize);

+        _arhiveBeginStreamPosition += offset + pos;

+        return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);

       }

     }

-    curTestPos += numTests;

-    numPrevBytes -= numTests;

-    memmove(buffer, buffer + numTests, numPrevBytes);

+    offset += processed;

+    memmove(buf, buf + processed, kHeaderSize);

   }

-  return S_FALSE;

 }

 

 // S_FALSE means that file is not archive

@@ -362,6 +387,8 @@
   HeadersSize = 0;

   Close();

   RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))

+  RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))

+  RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))

   RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));

   _stream = stream;

   return S_OK;

@@ -369,7 +396,9 @@
   

 void CInArchive::Close()

 {

+  _numInByteBufs = 0;

   _stream.Release();

+  ThereIsHeaderError = false;

 }

 

 void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)

@@ -382,30 +411,32 @@
   }

 }

 

-void CInArchive::GetNextFolderItem(CFolder &folder)

+// CFolder &folder can be non empty. So we must set all fields

+

+void CInByte2::ParseFolder(CFolder &folder)

 {

   CNum numCoders = ReadNum();

 

-  folder.Coders.Clear();

-  folder.Coders.Reserve((int)numCoders);

+  folder.Coders.SetSize(numCoders);

+

   CNum numInStreams = 0;

   CNum numOutStreams = 0;

   CNum i;

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

   {

-    folder.Coders.Add(CCoderInfo());

-    CCoderInfo &coder = folder.Coders.Back();

-

+    CCoderInfo &coder = folder.Coders[i];

     {

       Byte mainByte = ReadByte();

-      int idSize = (mainByte & 0xF);

-      Byte longID[15];

-      ReadBytes(longID, idSize);

-      if (idSize > 8)

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

         ThrowUnsupported();

+      unsigned idSize = (mainByte & 0xF);

+      if (idSize > 8 || idSize > GetRem())

+        ThrowUnsupported();

+      const Byte *longID = GetPtr();

       UInt64 id = 0;

-      for (int j = 0; j < idSize; j++)

-        id |= (UInt64)longID[idSize - 1 - j] << (8 * j);

+      for (unsigned j = 0; j < idSize; j++)

+        id = ((id << 8) | longID[j]);

+      SkipDataNoCheck(idSize);

       coder.MethodID = id;

 

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

@@ -421,53 +452,171 @@
       if ((mainByte & 0x20) != 0)

       {

         CNum propsSize = ReadNum();

-        coder.Props.SetCapacity((size_t)propsSize);

+        coder.Props.Alloc((size_t)propsSize);

         ReadBytes((Byte *)coder.Props, (size_t)propsSize);

       }

-      if ((mainByte & 0x80) != 0)

-        ThrowUnsupported();

+      else

+        coder.Props.Free();

     }

     numInStreams += coder.NumInStreams;

     numOutStreams += coder.NumOutStreams;

   }

 

   CNum numBindPairs = numOutStreams - 1;

-  folder.BindPairs.Clear();

-  folder.BindPairs.Reserve(numBindPairs);

+  folder.BindPairs.SetSize(numBindPairs);

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

   {

-    CBindPair bp;

+    CBindPair &bp = folder.BindPairs[i];

     bp.InIndex = ReadNum();

     bp.OutIndex = ReadNum();

-    folder.BindPairs.Add(bp);

   }

 

   if (numInStreams < numBindPairs)

     ThrowUnsupported();

   CNum numPackStreams = numInStreams - numBindPairs;

-  folder.PackStreams.Reserve(numPackStreams);

+  folder.PackStreams.SetSize(numPackStreams);

   if (numPackStreams == 1)

   {

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

       if (folder.FindBindPairForInStream(i) < 0)

       {

-        folder.PackStreams.Add(i);

+        folder.PackStreams[0] = i;

         break;

       }

-    if (folder.PackStreams.Size() != 1)

+    if (i == numInStreams)

       ThrowUnsupported();

   }

   else

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

-      folder.PackStreams.Add(ReadNum());

+      folder.PackStreams[i] = ReadNum();

 }

 

-void CInArchive::WaitAttribute(UInt64 attribute)

+void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const

+{

+  size_t startPos = FoCodersDataOffset[folderIndex];

+  CInByte2 inByte;

+  inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);

+  inByte.ParseFolder(folder);

+  if (inByte.GetRem() != 0)

+    throw 20120424;

+}

+

+

+void CDatabase::GetPath(unsigned index, UString &path) const

+{

+  path.Empty();

+  if (!NameOffsets || !NamesBuf)

+    return;

+

+  size_t offset = NameOffsets[index];

+  size_t size = NameOffsets[index + 1] - offset - 1;

+

+  if (size >= (1 << 20))

+    return;

+

+  wchar_t *s = path.GetBuffer((unsigned)size);

+

+  const Byte *p = ((const Byte *)NamesBuf + offset * 2);

+

+  #if defined(_WIN32) && defined(MY_CPU_LE)

+  

+  wmemcpy(s, (const wchar_t *)p, size);

+  

+  #else

+

+  for (size_t i = 0; i < size; i++)

+  {

+    *s = Get16(p);

+    p += 2;

+    s++;

+  }

+

+  #endif

+

+  path.ReleaseBuffer((unsigned)size);

+}

+

+HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()

+{

+  PropVariant_Clear(path);

+  if (!NameOffsets || !NamesBuf)

+    return S_OK;

+

+  size_t offset = NameOffsets[index];

+  size_t size = NameOffsets[index + 1] - offset;

+

+  if (size >= (1 << 14))

+    return S_OK;

+

+  RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1));

+  wchar_t *s = path->bstrVal;

+

+  const Byte *p = ((const Byte *)NamesBuf + offset * 2);

+

+  for (size_t i = 0; i < size; i++)

+  {

+    wchar_t c = Get16(p);

+    p += 2;

+    #if WCHAR_PATH_SEPARATOR != L'/'

+    if (c == L'/')

+      c = WCHAR_PATH_SEPARATOR;

+    #endif

+    *s++ = c;

+  }

+

+  return S_OK;

+

+  /*

+  unsigned cur = index;

+  unsigned size = 0;

+  

+  for (int i = 0;; i++)

+  {

+    size_t len = NameOffsets[cur + 1] - NameOffsets[cur];

+    size += (unsigned)len;

+    if (i > 256 || len > (1 << 14) || size > (1 << 14))

+      return PropVarEm_Set_Str(path, "[TOO-LONG]");

+    cur = Files[cur].Parent;

+    if (cur < 0)

+      break;

+  }

+  size--;

+

+  RINOK(PropVarEm_Alloc_Bstr(path, size));

+  wchar_t *s = path->bstrVal;

+  s += size;

+  *s = 0;

+  cur = index;

+  

+  for (;;)

+  {

+    unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);

+    const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;

+    do

+    {

+      p -= 2;

+      --s;

+      wchar_t c = Get16(p);

+      if (c == '/')

+        c = WCHAR_PATH_SEPARATOR;

+      *s = c;

+    }

+    while (--len);

+    const CFileItem &file = Files[cur];

+    cur = file.Parent;

+    if (cur < 0)

+      return S_OK;

+    *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);

+  }

+  */

+}

+

+void CInArchive::WaitId(UInt64 id)

 {

   for (;;)

   {

     UInt64 type = ReadID();

-    if (type == attribute)

+    if (type == id)

       return;

     if (type == NID::kEnd)

       ThrowIncorrect();

@@ -475,90 +624,209 @@
   }

 }

 

-void CInArchive::ReadHashDigests(int numItems,

-    CBoolVector &digestsDefined,

-    CRecordVector<UInt32> &digests)

+void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)

 {

-  ReadBoolVector2(numItems, digestsDefined);

-  digests.Clear();

-  digests.Reserve(numItems);

-  for (int i = 0; i < numItems; i++)

+  ReadBoolVector2(numItems, crcs.Defs);

+  crcs.Vals.ClearAndSetSize(numItems);

+  UInt32 *p = &crcs.Vals[0];

+  const bool *defs = &crcs.Defs[0];

+  for (unsigned i = 0; i < numItems; i++)

   {

     UInt32 crc = 0;

-    if (digestsDefined[i])

+    if (defs[i])

       crc = ReadUInt32();

-    digests.Add(crc);

+    p[i] = crc;

   }

 }

 

-void CInArchive::ReadPackInfo(

-    UInt64 &dataOffset,

-    CRecordVector<UInt64> &packSizes,

-    CBoolVector &packCRCsDefined,

-    CRecordVector<UInt32> &packCRCs)

+void CInArchive::ReadPackInfo(CFolders &f)

 {

-  dataOffset = ReadNumber();

   CNum numPackStreams = ReadNum();

-

-  WaitAttribute(NID::kSize);

-  packSizes.Clear();

-  packSizes.Reserve(numPackStreams);

+  

+  WaitId(NID::kSize);

+  f.PackPositions.Alloc(numPackStreams + 1);

+  f.NumPackStreams = numPackStreams;

+  UInt64 sum = 0;

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

-    packSizes.Add(ReadNumber());

+  {

+    f.PackPositions[i] = sum;

+    UInt64 packSize = ReadNumber();

+    sum += packSize;

+    if (sum < packSize)

+      ThrowIncorrect();

+  }

+  f.PackPositions[numPackStreams] = sum;

 

   UInt64 type;

   for (;;)

   {

     type = ReadID();

     if (type == NID::kEnd)

-      break;

+      return;

     if (type == NID::kCRC)

     {

-      ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);

+      CUInt32DefVector PackCRCs;

+      ReadHashDigests(numPackStreams, PackCRCs);

       continue;

     }

     SkipData();

   }

-  if (packCRCsDefined.IsEmpty())

-  {

-    BoolVector_Fill_False(packCRCsDefined, numPackStreams);

-    packCRCs.Reserve(numPackStreams);

-    packCRCs.Clear();

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

-      packCRCs.Add(0);

-  }

 }

 

 void CInArchive::ReadUnpackInfo(

     const CObjectVector<CByteBuffer> *dataVector,

-    CObjectVector<CFolder> &folders)

+    CFolders &folders)

 {

-  WaitAttribute(NID::kFolder);

+  WaitId(NID::kFolder);

   CNum numFolders = ReadNum();

 

+  CNum numCodersOutStreams = 0;

   {

     CStreamSwitch streamSwitch;

     streamSwitch.Set(this, dataVector);

-    folders.Clear();

-    folders.Reserve(numFolders);

-    for (CNum i = 0; i < numFolders; i++)

+    const Byte *startBufPtr = _inByteBack->GetPtr();

+    folders.NumFolders = numFolders;

+

+    folders.FoStartPackStreamIndex.Alloc(numFolders + 1);

+    folders.FoToMainUnpackSizeIndex.Alloc(numFolders);

+    folders.FoCodersDataOffset.Alloc(numFolders + 1);

+    folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);

+

+    CRecordVector<bool> InStreamUsed;

+    CRecordVector<bool> OutStreamUsed;

+

+    CNum packStreamIndex = 0;

+    CNum fo;

+    CInByte2 *inByte = _inByteBack;

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

     {

-      folders.Add(CFolder());

-      GetNextFolderItem(folders.Back());

+      UInt32 numOutStreams = 0;

+      UInt32 indexOfMainStream = 0;

+      UInt32 numPackStreams = 0;

+      folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;

+

+      numOutStreams = 0;

+      CNum numInStreams = 0;

+      CNum numCoders = inByte->ReadNum();

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

+      {

+        Byte mainByte = inByte->ReadByte();

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

+          ThrowUnsupported();

+        unsigned idSize = (mainByte & 0xF);

+        if (idSize > 8)

+          ThrowUnsupported();

+        if (idSize > inByte->GetRem())

+          ThrowEndOfData();

+        const Byte *longID = inByte->GetPtr();

+        UInt64 id = 0;

+        for (unsigned j = 0; j < idSize; j++)

+          id = ((id << 8) | longID[j]);

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

+        }

+        numInStreams += coderInStreams;

+        if (numInStreams < coderInStreams)

+          ThrowUnsupported();

+        numOutStreams += coderOutStreams;

+        if (numOutStreams < coderOutStreams)

+          ThrowUnsupported();

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

+        {

+          CNum propsSize = inByte->ReadNum();

+          if (propsSize > inByte->GetRem())

+            ThrowEndOfData();

+          if (id == k_LZMA2 && propsSize == 1)

+          {

+            Byte v = *_inByteBack->GetPtr();

+            if (folders.ParsedMethods.Lzma2Prop < v)

+              folders.ParsedMethods.Lzma2Prop = v;

+          }

+          else if (id == k_LZMA && propsSize == 5)

+          {

+            UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);

+            if (folders.ParsedMethods.LzmaDic < dicSize)

+              folders.ParsedMethods.LzmaDic = dicSize;

+          }

+          inByte->SkipDataNoCheck((size_t)propsSize);

+        }

+      }

+      

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

+      {

+        indexOfMainStream = 0;

+        numPackStreams = 1;

+      }

+      else

+      {

+        UInt32 i;

+        if (numOutStreams == 0)

+          ThrowUnsupported();

+        CNum numBindPairs = numOutStreams - 1;

+        if (numInStreams < numBindPairs)

+          ThrowUnsupported();

+        if (numInStreams >= 256 || numOutStreams >= 256)

+          ThrowUnsupported();

+        

+        InStreamUsed.ClearAndSetSize(numInStreams);

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

+          InStreamUsed[i] = false;

+        

+        OutStreamUsed.ClearAndSetSize(numOutStreams);

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

+          OutStreamUsed[i] = false;

+        

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

+        {

+          CNum index = ReadNum();

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

+            ThrowUnsupported();

+          InStreamUsed[index] = true;

+          index = ReadNum();

+          if (index >= numOutStreams || OutStreamUsed[index])

+            ThrowUnsupported();

+          OutStreamUsed[index] = true;

+        }

+        

+        numPackStreams = numInStreams - numBindPairs;

+        

+        if (numPackStreams != 1)

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

+            inByte->ReadNum(); // PackStreams

+          

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

+          if (!OutStreamUsed[i])

+          {

+            indexOfMainStream = i;

+            break;

+          }

+        if (i == numOutStreams)

+          ThrowUnsupported();

+      }

+      folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;

+      numCodersOutStreams += numOutStreams;

+      folders.FoStartPackStreamIndex[fo] = packStreamIndex;

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

   }

 

-  WaitAttribute(NID::kCodersUnpackSize);

-

-  CNum i;

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

-  {

-    CFolder &folder = folders[i];

-    CNum numOutStreams = folder.GetNumOutStreams();

-    folder.UnpackSizes.Reserve(numOutStreams);

-    for (CNum j = 0; j < numOutStreams; j++)

-      folder.UnpackSizes.Add(ReadNumber());

-  }

+  WaitId(NID::kCodersUnpackSize);

+  folders.CoderUnpackSizes.Alloc(numCodersOutStreams);

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

+    folders.CoderUnpackSizes[i] = ReadNumber();

 

   for (;;)

   {

@@ -567,15 +835,7 @@
       return;

     if (type == NID::kCRC)

     {

-      CBoolVector crcsDefined;

-      CRecordVector<UInt32> crcs;

-      ReadHashDigests(numFolders, crcsDefined, crcs);

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

-      {

-        CFolder &folder = folders[i];

-        folder.UnpackCRCDefined = crcsDefined[i];

-        folder.UnpackCRC = crcs[i];

-      }

+      ReadHashDigests(numFolders, folders.FolderCRCs);

       continue;

     }

     SkipData();

@@ -583,170 +843,217 @@
 }

 

 void CInArchive::ReadSubStreamsInfo(

-    const CObjectVector<CFolder> &folders,

-    CRecordVector<CNum> &numUnpackStreamsInFolders,

+    CFolders &folders,

     CRecordVector<UInt64> &unpackSizes,

-    CBoolVector &digestsDefined,

-    CRecordVector<UInt32> &digests)

+    CUInt32DefVector &digests)

 {

-  numUnpackStreamsInFolders.Clear();

-  numUnpackStreamsInFolders.Reserve(folders.Size());

+  folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);

+  CNum i;

+  for (i = 0; i < folders.NumFolders; i++)

+    folders.NumUnpackStreamsVector[i] = 1;

+  

   UInt64 type;

+  

   for (;;)

   {

     type = ReadID();

     if (type == NID::kNumUnpackStream)

     {

-      for (int i = 0; i < folders.Size(); i++)

-        numUnpackStreamsInFolders.Add(ReadNum());

+      for (i = 0; i < folders.NumFolders; i++)

+        folders.NumUnpackStreamsVector[i] = ReadNum();

       continue;

     }

-    if (type == NID::kCRC || type == NID::kSize)

-      break;

-    if (type == NID::kEnd)

+    if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)

       break;

     SkipData();

   }

 

-  if (numUnpackStreamsInFolders.IsEmpty())

-    for (int i = 0; i < folders.Size(); i++)

-      numUnpackStreamsInFolders.Add(1);

-

-  int i;

-  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

+  if (type == NID::kSize)

   {

-    // v3.13 incorrectly worked with empty folders

-    // v4.07: we check that folder is empty

-    CNum numSubstreams = numUnpackStreamsInFolders[i];

-    if (numSubstreams == 0)

-      continue;

-    UInt64 sum = 0;

-    for (CNum j = 1; j < numSubstreams; j++)

-      if (type == NID::kSize)

+    for (i = 0; i < folders.NumFolders; i++)

+    {

+      // v3.13 incorrectly worked with empty folders

+      // v4.07: we check that folder is empty

+      CNum numSubstreams = folders.NumUnpackStreamsVector[i];

+      if (numSubstreams == 0)

+        continue;

+      UInt64 sum = 0;

+      for (CNum j = 1; j < numSubstreams; j++)

       {

         UInt64 size = ReadNumber();

         unpackSizes.Add(size);

         sum += size;

+        if (sum < size)

+          ThrowIncorrect();

       }

-    unpackSizes.Add(folders[i].GetUnpackSize() - sum);

-  }

-  if (type == NID::kSize)

+      UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);

+      if (folderUnpackSize < sum)

+        ThrowIncorrect();

+      unpackSizes.Add(folderUnpackSize - sum);

+    }

     type = ReadID();

-

-  int numDigests = 0;

-  int numDigestsTotal = 0;

-  for (i = 0; i < folders.Size(); i++)

+  }

+  else

   {

-    CNum numSubstreams = numUnpackStreamsInFolders[i];

-    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)

+    for (i = 0; i < folders.NumFolders; i++)

+    {

+      /* v9.26 - v9.29 incorrectly worked:

+         if (folders.NumUnpackStreamsVector[i] == 0), it threw error */

+      CNum val = folders.NumUnpackStreamsVector[i];

+      if (val > 1)

+        ThrowIncorrect();

+      if (val == 1)

+        unpackSizes.Add(folders.GetFolderUnpackSize(i));

+    }

+  }

+

+  unsigned numDigests = 0;

+  for (i = 0; i < folders.NumFolders; i++)

+  {

+    CNum numSubstreams = folders.NumUnpackStreamsVector[i];

+    if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))

       numDigests += numSubstreams;

-    numDigestsTotal += numSubstreams;

   }

 

   for (;;)

   {

+    if (type == NID::kEnd)

+      break;

     if (type == NID::kCRC)

     {

-      CBoolVector digestsDefined2;

-      CRecordVector<UInt32> digests2;

-      ReadHashDigests(numDigests, digestsDefined2, digests2);

-      int digestIndex = 0;

-      for (i = 0; i < folders.Size(); i++)

+      // CUInt32DefVector digests2;

+      // ReadHashDigests(numDigests, digests2);

+      CBoolVector digests2;

+      ReadBoolVector2(numDigests, digests2);

+

+      digests.ClearAndSetSize(unpackSizes.Size());

+      

+      unsigned k = 0;

+      unsigned k2 = 0;

+      

+      for (i = 0; i < folders.NumFolders; i++)

       {

-        CNum numSubstreams = numUnpackStreamsInFolders[i];

-        const CFolder &folder = folders[i];

-        if (numSubstreams == 1 && folder.UnpackCRCDefined)

+        CNum numSubstreams = folders.NumUnpackStreamsVector[i];

+        if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))

         {

-          digestsDefined.Add(true);

-          digests.Add(folder.UnpackCRC);

+          digests.Defs[k] = true;

+          digests.Vals[k] = folders.FolderCRCs.Vals[i];

+          k++;

         }

-        else

-          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)

-          {

-            digestsDefined.Add(digestsDefined2[digestIndex]);

-            digests.Add(digests2[digestIndex]);

-          }

+        else for (CNum j = 0; j < numSubstreams; j++)

+        {

+          bool defined = digests2[k2++];

+          digests.Defs[k] = defined;

+          UInt32 crc = 0;

+          if (defined)

+            crc = ReadUInt32();

+          digests.Vals[k] = crc;

+          k++;

+        }

       }

-    }

-    else if (type == NID::kEnd)

-    {

-      if (digestsDefined.IsEmpty())

-      {

-        BoolVector_Fill_False(digestsDefined, numDigestsTotal);

-        digests.Clear();

-        for (int i = 0; i < numDigestsTotal; i++)

-          digests.Add(0);

-      }

-      return;

+      // if (k != unpackSizes.Size()) throw 1234567;

     }

     else

       SkipData();

+    

     type = ReadID();

   }

+

+  if (digests.Defs.Size() != unpackSizes.Size())

+  {

+    digests.ClearAndSetSize(unpackSizes.Size());

+    unsigned k = 0;

+    for (i = 0; i < folders.NumFolders; i++)

+    {

+      CNum numSubstreams = folders.NumUnpackStreamsVector[i];

+      if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))

+      {

+        digests.Defs[k] = true;

+        digests.Vals[k] = folders.FolderCRCs.Vals[i];

+        k++;

+      }

+      else for (CNum j = 0; j < numSubstreams; j++)

+      {

+        digests.Defs[k] = false;

+        digests.Vals[k] = 0;

+        k++;

+      }

+    }

+  }

 }

 

 void CInArchive::ReadStreamsInfo(

     const CObjectVector<CByteBuffer> *dataVector,

     UInt64 &dataOffset,

-    CRecordVector<UInt64> &packSizes,

-    CBoolVector &packCRCsDefined,

-    CRecordVector<UInt32> &packCRCs,

-    CObjectVector<CFolder> &folders,

-    CRecordVector<CNum> &numUnpackStreamsInFolders,

+    CFolders &folders,

     CRecordVector<UInt64> &unpackSizes,

-    CBoolVector &digestsDefined,

-    CRecordVector<UInt32> &digests)

+    CUInt32DefVector &digests)

 {

-  for (;;)

+  UInt64 type = ReadID();

+  

+  if (type == NID::kPackInfo)

   {

-    UInt64 type = ReadID();

-    if (type > ((UInt32)1 << 30))

-      ThrowIncorrect();

-    switch((UInt32)type)

+    dataOffset = ReadNumber();

+    ReadPackInfo(folders);

+    type = ReadID();

+  }

+

+  if (type == NID::kUnpackInfo)

+  {

+    ReadUnpackInfo(dataVector, folders);

+    type = ReadID();

+  }

+

+  if (folders.NumFolders != 0 && !folders.PackPositions)

+  {

+    // if there are folders, we need PackPositions also

+    folders.PackPositions.Alloc(1);

+    folders.PackPositions[0] = 0;

+  }

+  

+  if (type == NID::kSubStreamsInfo)

+  {

+    ReadSubStreamsInfo(folders, unpackSizes, digests);

+    type = ReadID();

+  }

+  else

+  {

+    folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);

+    /* If digests.Defs.Size() == 0, it means that there are no crcs.

+       So we don't need to fill digests with values. */

+    // digests.Vals.ClearAndSetSize(folders.NumFolders);

+    // BoolVector_Fill_False(digests.Defs, folders.NumFolders);

+    for (CNum i = 0; i < folders.NumFolders; i++)

     {

-      case NID::kEnd:

-        return;

-      case NID::kPackInfo:

-      {

-        ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs);

-        break;

-      }

-      case NID::kUnpackInfo:

-      {

-        ReadUnpackInfo(dataVector, folders);

-        break;

-      }

-      case NID::kSubStreamsInfo:

-      {

-        ReadSubStreamsInfo(folders, numUnpackStreamsInFolders,

-            unpackSizes, digestsDefined, digests);

-        break;

-      }

-      default:

-        ThrowIncorrect();

+      folders.NumUnpackStreamsVector[i] = 1;

+      unpackSizes.Add(folders.GetFolderUnpackSize(i));

+      // digests.Vals[i] = 0;

     }

   }

+  

+  if (type != NID::kEnd)

+    ThrowIncorrect();

 }

 

-void CInArchive::ReadBoolVector(int numItems, CBoolVector &v)

+void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)

 {

-  v.Clear();

-  v.Reserve(numItems);

+  v.ClearAndSetSize(numItems);

   Byte b = 0;

   Byte mask = 0;

-  for (int i = 0; i < numItems; i++)

+  bool *p = &v[0];

+  for (unsigned i = 0; i < numItems; i++)

   {

     if (mask == 0)

     {

       b = ReadByte();

       mask = 0x80;

     }

-    v.Add((b & mask) != 0);

+    p[i] = ((b & mask) != 0);

     mask >>= 1;

   }

 }

 

-void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)

+void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)

 {

   Byte allAreDefined = ReadByte();

   if (allAreDefined == 0)

@@ -754,27 +1061,30 @@
     ReadBoolVector(numItems, v);

     return;

   }

-  v.Clear();

-  v.Reserve(numItems);

-  for (int i = 0; i < numItems; i++)

-    v.Add(true);

+  v.ClearAndSetSize(numItems);

+  bool *p = &v[0];

+  for (unsigned i = 0; i < numItems; i++)

+    p[i] = true;

 }

 

 void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,

-    CUInt64DefVector &v, int numFiles)

+    CUInt64DefVector &v, unsigned numItems)

 {

-  ReadBoolVector2(numFiles, v.Defined);

+  ReadBoolVector2(numItems, v.Defs);

 

   CStreamSwitch streamSwitch;

   streamSwitch.Set(this, &dataVector);

-  v.Values.Reserve(numFiles);

+  

+  v.Vals.ClearAndSetSize(numItems);

+  UInt64 *p = &v.Vals[0];

+  const bool *defs = &v.Defs[0];

 

-  for (int i = 0; i < numFiles; i++)

+  for (unsigned i = 0; i < numItems; i++)

   {

     UInt64 t = 0;

-    if (v.Defined[i])

+    if (defs[i])

       t = ReadUInt64();

-    v.Values.Add(t);

+    p[i] = t;

   }

 }

 

@@ -782,35 +1092,19 @@
     DECL_EXTERNAL_CODECS_LOC_VARS

     UInt64 baseOffset,

     UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector

-    #ifndef _NO_CRYPTO

-    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-    #endif

+    _7Z_DECODER_CRYPRO_VARS_DECL

     )

 {

-  CRecordVector<UInt64> packSizes;

-  CBoolVector packCRCsDefined;

-  CRecordVector<UInt32> packCRCs;

-  CObjectVector<CFolder> folders;

-  

-  CRecordVector<CNum> numUnpackStreamsInFolders;

+  CFolders folders;

   CRecordVector<UInt64> unpackSizes;

-  CBoolVector digestsDefined;

-  CRecordVector<UInt32> digests;

+  CUInt32DefVector  digests;

   

   ReadStreamsInfo(NULL,

     dataOffset,

-    packSizes,

-    packCRCsDefined,

-    packCRCs,

     folders,

-    numUnpackStreamsInFolders,

     unpackSizes,

-    digestsDefined,

     digests);

   

-  // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;

-  

-  CNum packIndex = 0;

   CDecoder decoder(

     #ifdef _ST_MODE

     false

@@ -818,17 +1112,15 @@
     true

     #endif

     );

-  UInt64 dataStartPos = baseOffset + dataOffset;

-  for (int i = 0; i < folders.Size(); i++)

+

+  for (CNum i = 0; i < folders.NumFolders; i++)

   {

-    const CFolder &folder = folders[i];

-    dataVector.Add(CByteBuffer());

-    CByteBuffer &data = dataVector.Back();

-    UInt64 unpackSize64 = folder.GetUnpackSize();

+    CByteBuffer &data = dataVector.AddNew();

+    UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);

     size_t unpackSize = (size_t)unpackSize64;

     if (unpackSize != unpackSize64)

       ThrowUnsupported();

-    data.SetCapacity(unpackSize);

+    data.Alloc(unpackSize);

     

     CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;

     CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;

@@ -836,43 +1128,35 @@
     

     HRESULT result = decoder.Decode(

       EXTERNAL_CODECS_LOC_VARS

-      _stream, dataStartPos,

-      &packSizes[packIndex], folder, outStream, NULL

-      #ifndef _NO_CRYPTO

-      , getTextPassword, passwordIsDefined

-      #endif

+      _stream, baseOffset + dataOffset,

+      folders, i,

+      outStream, NULL

+      _7Z_DECODER_CRYPRO_VARS

       #if !defined(_7ZIP_ST) && !defined(_SFX)

       , false, 1

       #endif

       );

     RINOK(result);

     

-    if (folder.UnpackCRCDefined)

-      if (CrcCalc(data, unpackSize) != folder.UnpackCRC)

+    if (folders.FolderCRCs.ValidAndDefined(i))

+      if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])

         ThrowIncorrect();

-    for (int j = 0; j < folder.PackStreams.Size(); j++)

-    {

-      UInt64 packSize = packSizes[packIndex++];

-      dataStartPos += packSize;

-      HeadersSize += packSize;

-    }

   }

+  HeadersSize += folders.PackPositions[folders.NumPackStreams];

   return S_OK;

 }

 

 HRESULT CInArchive::ReadHeader(

     DECL_EXTERNAL_CODECS_LOC_VARS

-    CArchiveDatabaseEx &db

-    #ifndef _NO_CRYPTO

-    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-    #endif

+    CDbEx &db

+    _7Z_DECODER_CRYPRO_VARS_DECL

     )

 {

   UInt64 type = ReadID();

 

   if (type == NID::kArchiveProperties)

   {

-    ReadArchiveProperties(db.ArchiveInfo);

+    ReadArchiveProperties(db.ArcInfo);

     type = ReadID();

   }

  

@@ -882,70 +1166,53 @@
   {

     HRESULT result = ReadAndDecodePackedStreams(

         EXTERNAL_CODECS_LOC_VARS

-        db.ArchiveInfo.StartPositionAfterHeader,

-        db.ArchiveInfo.DataStartPosition2,

+        db.ArcInfo.StartPositionAfterHeader,

+        db.ArcInfo.DataStartPosition2,

         dataVector

-        #ifndef _NO_CRYPTO

-        , getTextPassword, passwordIsDefined

-        #endif

+        _7Z_DECODER_CRYPRO_VARS

         );

     RINOK(result);

-    db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;

+    db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;

     type = ReadID();

   }

 

   CRecordVector<UInt64> unpackSizes;

-  CBoolVector digestsDefined;

-  CRecordVector<UInt32> digests;

+  CUInt32DefVector digests;

   

   if (type == NID::kMainStreamsInfo)

   {

     ReadStreamsInfo(&dataVector,

-        db.ArchiveInfo.DataStartPosition,

-        db.PackSizes,

-        db.PackCRCsDefined,

-        db.PackCRCs,

-        db.Folders,

-        db.NumUnpackStreamsVector,

+        db.ArcInfo.DataStartPosition,

+        (CFolders &)db,

         unpackSizes,

-        digestsDefined,

         digests);

-    db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader;

+    db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;

     type = ReadID();

   }

-  else

-  {

-    for (int i = 0; i < db.Folders.Size(); i++)

-    {

-      db.NumUnpackStreamsVector.Add(1);

-      CFolder &folder = db.Folders[i];

-      unpackSizes.Add(folder.GetUnpackSize());

-      digestsDefined.Add(folder.UnpackCRCDefined);

-      digests.Add(folder.UnpackCRC);

-    }

-  }

 

   db.Files.Clear();

 

-  if (type == NID::kEnd)

-    return S_OK;

-  if (type != NID::kFilesInfo)

-    ThrowIncorrect();

+  if (type == NID::kFilesInfo)

+  {

   

   CNum numFiles = ReadNum();

+  db.Files.ClearAndSetSize(numFiles);

+  CNum i;

+  /*

   db.Files.Reserve(numFiles);

   CNum i;

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

     db.Files.Add(CFileItem());

+  */

 

-  db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);

-  if (!db.PackSizes.IsEmpty())

-    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);

-  if (numFiles > 0  && !digests.IsEmpty())

-    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);

+  db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);

+  // if (!db.PackSizes.IsEmpty())

+    db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);

+  if (numFiles > 0  && !digests.Defs.IsEmpty())

+    db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);

 

   CBoolVector emptyStreamVector;

-  BoolVector_Fill_False(emptyStreamVector, (int)numFiles);

+  BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles);

   CBoolVector emptyFileVector;

   CBoolVector antiFileVector;

   CNum numEmptyStreams = 0;

@@ -956,7 +1223,10 @@
     if (type == NID::kEnd)

       break;

     UInt64 size = ReadNumber();

-    size_t ppp = _inByteBack->_pos;

+    if (size > _inByteBack->GetRem())

+      ThrowIncorrect();

+    CStreamSwitch switchProp;

+    switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);

     bool addPropIdToList = true;

     bool isKnownType = true;

     if (type > ((UInt32)1 << 30))

@@ -967,11 +1237,29 @@
       {

         CStreamSwitch streamSwitch;

         streamSwitch.Set(this, &dataVector);

-        for (int i = 0; i < db.Files.Size(); i++)

-          _inByteBack->ReadString(db.Files[i].Name);

+        size_t rem = _inByteBack->GetRem();

+        db.NamesBuf.Alloc(rem);

+        ReadBytes(db.NamesBuf, rem);

+        db.NameOffsets.Alloc(db.Files.Size() + 1);

+        size_t pos = 0;

+        unsigned i;

+        for (i = 0; i < db.Files.Size(); i++)

+        {

+          size_t curRem = (rem - pos) / 2;

+          const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);

+          size_t j;

+          for (j = 0; j < curRem && buf[j] != 0; j++);

+          if (j == curRem)

+            ThrowEndOfData();

+          db.NameOffsets[i] = pos / 2;

+          pos += j * 2 + 2;

+        }

+        db.NameOffsets[i] = pos / 2;

+        if (pos != rem)

+          ThereIsHeaderError = true;

         break;

       }

-      case NID::kWinAttributes:

+      case NID::kWinAttrib:

       {

         CBoolVector boolVector;

         ReadBoolVector2(db.Files.Size(), boolVector);

@@ -986,9 +1274,40 @@
         }

         break;

       }

+      /*

+      case NID::kIsAux:

+      {

+        ReadBoolVector(db.Files.Size(), db.IsAux);

+        break;

+      }

+      case NID::kParent:

+      {

+        db.IsTree = true;

+        // CBoolVector boolVector;

+        // ReadBoolVector2(db.Files.Size(), boolVector);

+        // CStreamSwitch streamSwitch;

+        // streamSwitch.Set(this, &dataVector);

+        CBoolVector boolVector;

+        ReadBoolVector2(db.Files.Size(), boolVector);

+

+        db.ThereAreAltStreams = false;

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

+        {

+          CFileItem &file = db.Files[i];

+          // file.Parent = -1;

+          // if (boolVector[i])

+          file.Parent = (int)ReadUInt32();

+          file.IsAltStream = !boolVector[i];

+          if (file.IsAltStream)

+            db.ThereAreAltStreams = true;

+        }

+        break;

+      }

+      */

       case NID::kEmptyStream:

       {

         ReadBoolVector(numFiles, emptyStreamVector);

+        numEmptyStreams = 0;

         for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)

           if (emptyStreamVector[i])

             numEmptyStreams++;

@@ -1000,34 +1319,83 @@
       }

       case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;

       case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;

-      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break;

-      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break;

-      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break;

-      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break;

+      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break;

+      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;

+      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;

+      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;

       case NID::kDummy:

       {

         for (UInt64 j = 0; j < size; j++)

           if (ReadByte() != 0)

-            ThrowIncorrect();

+            ThereIsHeaderError = true;

         addPropIdToList = false;

         break;

       }

+      /*

+      case NID::kNtSecure:

+      {

+        try

+        {

+          {

+            CStreamSwitch streamSwitch;

+            streamSwitch.Set(this, &dataVector);

+            UInt32 numDescriptors = ReadUInt32();

+            size_t offset = 0;

+            db.SecureOffsets.Clear();

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

+            {

+              UInt32 size = ReadUInt32();

+              db.SecureOffsets.Add(offset);

+              offset += size;

+            }

+            // ThrowIncorrect();;

+            db.SecureOffsets.Add(offset);

+            db.SecureBuf.SetCapacity(offset);

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

+            {

+              offset = db.SecureOffsets[i];

+              ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);

+            }

+            db.SecureIDs.Clear();

+            for (unsigned i = 0; i < db.Files.Size(); i++)

+            {

+              db.SecureIDs.Add(ReadNum());

+              // db.SecureIDs.Add(ReadUInt32());

+            }

+            // ReadUInt32();

+            if (_inByteBack->GetRem() != 0)

+              ThrowIncorrect();;

+          }

+        }

+        catch(CInArchiveException &)

+        {

+          ThereIsHeaderError = true;

+          addPropIdToList = isKnownType = false;

+          db.ClearSecure();

+        }

+        break;

+      }

+      */

       default:

         addPropIdToList = isKnownType = false;

     }

     if (isKnownType)

     {

-      if(addPropIdToList)

-        db.ArchiveInfo.FileInfoPopIDs.Add(type);

+      if (addPropIdToList)

+        db.ArcInfo.FileInfoPopIDs.Add(type);

     }

     else

-      SkipData(size);

-    bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||

-        db.ArchiveInfo.Version.Minor > 2);

-    if (checkRecordsSize && _inByteBack->_pos - ppp != size)

+    {

+      db.UnsupportedFeatureWarning = true;

+      _inByteBack->SkipRem();

+    }

+    // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02)

+    if (_inByteBack->GetRem() != 0)

       ThrowIncorrect();

   }

 

+  type = ReadID(); // Read (NID::kEnd) end of headers

+

   CNum emptyFileIndex = 0;

   CNum sizeIndex = 0;

 

@@ -1041,13 +1409,15 @@
     CFileItem &file = db.Files[i];

     bool isAnti;

     file.HasStream = !emptyStreamVector[i];

+    file.Crc = 0;

     if (file.HasStream)

     {

       file.IsDir = false;

       isAnti = false;

       file.Size = unpackSizes[sizeIndex];

-      file.Crc = digests[sizeIndex];

-      file.CrcDefined = digestsDefined[sizeIndex];

+      file.CrcDefined = digests.ValidAndDefined(sizeIndex);

+      if (file.CrcDefined)

+        file.Crc = digests.Vals[sizeIndex];

       sizeIndex++;

     }

     else

@@ -1061,156 +1431,181 @@
     if (numAntiItems != 0)

       db.IsAnti.Add(isAnti);

   }

+  }

+  db.FillLinks();

+  /*

+  if (type != NID::kEnd)

+    ThrowIncorrect();

+  if (_inByteBack->GetRem() != 0)

+    ThrowIncorrect();

+  */

   return S_OK;

 }

 

-

-void CArchiveDatabaseEx::FillFolderStartPackStream()

+void CDbEx::FillLinks()

 {

-  FolderStartPackStreamIndex.Clear();

-  FolderStartPackStreamIndex.Reserve(Folders.Size());

-  CNum startPos = 0;

-  for (int i = 0; i < Folders.Size(); i++)

-  {

-    FolderStartPackStreamIndex.Add(startPos);

-    startPos += (CNum)Folders[i].PackStreams.Size();

-  }

-}

-

-void CArchiveDatabaseEx::FillStartPos()

-{

-  PackStreamStartPositions.Clear();

-  PackStreamStartPositions.Reserve(PackSizes.Size());

-  UInt64 startPos = 0;

-  for (int i = 0; i < PackSizes.Size(); i++)

-  {

-    PackStreamStartPositions.Add(startPos);

-    startPos += PackSizes[i];

-  }

-}

-

-void CArchiveDatabaseEx::FillFolderStartFileIndex()

-{

-  FolderStartFileIndex.Clear();

-  FolderStartFileIndex.Reserve(Folders.Size());

-  FileIndexToFolderIndexMap.Clear();

-  FileIndexToFolderIndexMap.Reserve(Files.Size());

+  FolderStartFileIndex.ClearAndSetSize(NumFolders);

   

-  int folderIndex = 0;

+  FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());

+  

+  CNum folderIndex = 0;

   CNum indexInFolder = 0;

-  for (int i = 0; i < Files.Size(); i++)

+  unsigned i;

+  for (i = 0; i < Files.Size(); i++)

   {

-    const CFileItem &file = Files[i];

-    bool emptyStream = !file.HasStream;

-    if (emptyStream && indexInFolder == 0)

-    {

-      FileIndexToFolderIndexMap.Add(kNumNoIndex);

-      continue;

-    }

+    bool emptyStream = !Files[i].HasStream;

     if (indexInFolder == 0)

     {

+      if (emptyStream)

+      {

+        FileIndexToFolderIndexMap[i] = kNumNoIndex;

+        continue;

+      }

       // v3.13 incorrectly worked with empty folders

-      // v4.07: Loop for skipping empty folders

+      // v4.07: we skip empty folders

       for (;;)

       {

-        if (folderIndex >= Folders.Size())

+        if (folderIndex >= NumFolders)

           ThrowIncorrect();

-        FolderStartFileIndex.Add(i); // check it

+        FolderStartFileIndex[folderIndex] = i;

         if (NumUnpackStreamsVector[folderIndex] != 0)

           break;

         folderIndex++;

       }

     }

-    FileIndexToFolderIndexMap.Add(folderIndex);

+    FileIndexToFolderIndexMap[i] = folderIndex;

     if (emptyStream)

       continue;

-    indexInFolder++;

-    if (indexInFolder >= NumUnpackStreamsVector[folderIndex])

+    if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])

     {

       folderIndex++;

       indexInFolder = 0;

     }

   }

+

+  if (indexInFolder != 0)

+    folderIndex++;

+  /*

+  if (indexInFolder != 0)

+    ThrowIncorrect();

+  */

+  for (;;)

+  {

+    if (folderIndex >= NumFolders)

+      return;

+    FolderStartFileIndex[folderIndex] = i;

+    /*

+    if (NumUnpackStreamsVector[folderIndex] != 0)

+      ThrowIncorrect();;

+    */

+    folderIndex++;

+  }

 }

 

 HRESULT CInArchive::ReadDatabase2(

     DECL_EXTERNAL_CODECS_LOC_VARS

-    CArchiveDatabaseEx &db

-    #ifndef _NO_CRYPTO

-    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-    #endif

+    CDbEx &db

+    _7Z_DECODER_CRYPRO_VARS_DECL

     )

 {

   db.Clear();

-  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;

+  db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;

 

-  db.ArchiveInfo.Version.Major = _header[6];

-  db.ArchiveInfo.Version.Minor = _header[7];

+  db.ArcInfo.Version.Major = _header[6];

+  db.ArcInfo.Version.Minor = _header[7];

 

-  if (db.ArchiveInfo.Version.Major != kMajorVersion)

-    ThrowUnsupportedVersion();

+  if (db.ArcInfo.Version.Major != kMajorVersion)

+  {

+    // db.UnsupportedVersion = true;

+    return S_FALSE;

+  }

 

-  UInt32 crcFromArchive = Get32(_header + 8);

-  UInt64 nextHeaderOffset = Get64(_header + 0xC);

-  UInt64 nextHeaderSize = Get64(_header + 0x14);

-  UInt32 nextHeaderCRC = Get32(_header + 0x1C);

-  UInt32 crc = CrcCalc(_header + 0xC, 20);

+  UInt64 nextHeaderOffset = Get64(_header + 12);

+  UInt64 nextHeaderSize = Get64(_header + 20);

+  UInt32 nextHeaderCRC = Get32(_header + 28);

 

   #ifdef FORMAT_7Z_RECOVERY

-  if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)

+  UInt32 crcFromArc = Get32(_header + 8);

+  if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)

   {

-    UInt64 cur, cur2;

+    UInt64 cur, fileSize;

     RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));

-    const int kCheckSize = 500;

+    const unsigned kCheckSize = 512;

     Byte buf[kCheckSize];

-    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));

-    int checkSize = kCheckSize;

-    if (cur2 - cur < kCheckSize)

-      checkSize = (int)(cur2 - cur);

-    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));

-    

+    RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));

+    UInt64 rem = fileSize - cur;

+    unsigned checkSize = kCheckSize;

+    if (rem < kCheckSize)

+      checkSize = (unsigned)(rem);

+    if (checkSize < 3)

+      return S_FALSE;

+    RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL));

     RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));

 

-    int i;

-    for (i = (int)checkSize - 2; i >= 0; i--)

-      if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)

-        break;

-    if (i < 0)

+    if (buf[checkSize - 1] != 0)

       return S_FALSE;

+

+    unsigned i;

+    for (i = checkSize - 2;; i--)

+    {

+      if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo ||

+          buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)

+        break;

+      if (i == 0)

+        return S_FALSE;

+    }

     nextHeaderSize = checkSize - i;

-    nextHeaderOffset = cur2 - cur + i;

+    nextHeaderOffset = rem - nextHeaderSize;

     nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);

     RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));

+    db.StartHeaderWasRecovered = true;

   }

   else

   #endif

   {

-    if (crc != crcFromArchive)

-      ThrowIncorrect();

+    // Crc was tested already at signature check

+    // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();

   }

 

-  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;

+  db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;

+  db.PhySize = kHeaderSize;

 

+  db.IsArc = false;

+  if ((Int64)nextHeaderOffset < 0 ||

+      nextHeaderSize > ((UInt64)1 << 62))

+    return S_FALSE;

   if (nextHeaderSize == 0)

+  {

+    if (nextHeaderOffset != 0)

+      return S_FALSE;

+    db.IsArc = true;

     return S_OK;

-

-  if (nextHeaderSize > (UInt64)0xFFFFFFFF)

-    return S_FALSE;

-

-  if ((Int64)nextHeaderOffset < 0)

-    return S_FALSE;

-

-  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));

-

-  CByteBuffer buffer2;

-  buffer2.SetCapacity((size_t)nextHeaderSize);

-

-  RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize));

+  }

+  

+  if (!db.StartHeaderWasRecovered)

+    db.IsArc = true;

+  

   HeadersSize += kHeaderSize + nextHeaderSize;

   db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;

+  if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)

+  {

+    db.UnexpectedEnd = true;

+    return S_FALSE;

+  }

+  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));

 

-  if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)

+  size_t nextHeaderSize_t = (size_t)nextHeaderSize;

+  if (nextHeaderSize_t != nextHeaderSize)

+    return E_OUTOFMEMORY;

+  CByteBuffer buffer2(nextHeaderSize_t);

+

+  RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t));

+

+  if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)

     ThrowIncorrect();

+

+  if (!db.StartHeaderWasRecovered)

+    db.PhySizeWasConfirmed = true;

   

   CStreamSwitch streamSwitch;

   streamSwitch.Set(this, buffer2);

@@ -1224,12 +1619,10 @@
       ThrowIncorrect();

     HRESULT result = ReadAndDecodePackedStreams(

         EXTERNAL_CODECS_LOC_VARS

-        db.ArchiveInfo.StartPositionAfterHeader,

-        db.ArchiveInfo.DataStartPosition2,

+        db.ArcInfo.StartPositionAfterHeader,

+        db.ArcInfo.DataStartPosition2,

         dataVector

-        #ifndef _NO_CRYPTO

-        , getTextPassword, passwordIsDefined

-        #endif

+        _7Z_DECODER_CRYPRO_VARS

         );

     RINOK(result);

     if (dataVector.Size() == 0)

@@ -1242,35 +1635,45 @@
       ThrowIncorrect();

   }

 

+  db.IsArc = true;

+

   db.HeadersSize = HeadersSize;

 

   return ReadHeader(

     EXTERNAL_CODECS_LOC_VARS

     db

-    #ifndef _NO_CRYPTO

-    , getTextPassword, passwordIsDefined

-    #endif

+    _7Z_DECODER_CRYPRO_VARS

     );

 }

 

 HRESULT CInArchive::ReadDatabase(

     DECL_EXTERNAL_CODECS_LOC_VARS

-    CArchiveDatabaseEx &db

-    #ifndef _NO_CRYPTO

-    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-    #endif

+    CDbEx &db

+    _7Z_DECODER_CRYPRO_VARS_DECL

     )

 {

   try

   {

-    return ReadDatabase2(

+    HRESULT res = ReadDatabase2(

       EXTERNAL_CODECS_LOC_VARS db

-      #ifndef _NO_CRYPTO

-      , getTextPassword, passwordIsDefined

-      #endif

+      _7Z_DECODER_CRYPRO_VARS

       );

+    if (ThereIsHeaderError)

+      db.ThereIsHeaderError = true;

+    if (res == E_NOTIMPL)

+      ThrowUnsupported();

+    return res;

   }

-  catch(CInArchiveException &) { return S_FALSE; }

+  catch(CUnsupportedFeatureException &)

+  {

+    db.UnsupportedFeatureError = true;

+    return S_FALSE;

+  }

+  catch(CInArchiveException &)

+  {

+    db.ThereIsHeaderError = true;

+    return S_FALSE;

+  }

 }

 

 }}

diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
old mode 100755
new mode 100644
index b82a020..d78eca2
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -5,6 +5,8 @@
 

 #include "../../../Common/MyCom.h"

 

+#include "../../../Windows/PropVariant.h"

+

 #include "../../IPassword.h"

 #include "../../IStream.h"

 

@@ -15,7 +17,148 @@
  

 namespace NArchive {

 namespace N7z {

+

+/*

+  We don't need to init isEncrypted and passwordIsDefined

+  We must upgrade them only */

+

+#ifdef _NO_CRYPTO

+#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

+#endif

+

+struct CParsedMethods

+{

+  Byte Lzma2Prop;

+  UInt32 LzmaDic;

+  CRecordVector<UInt64> IDs;

+

+  CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}

+};

+

+struct CFolders

+{

+  CNum NumPackStreams;

+  CNum NumFolders;

+

+  CObjArray<UInt64> PackPositions; // NumPackStreams + 1

+  // CUInt32DefVector PackCRCs; // we don't use PackCRCs now

+

+  CUInt32DefVector FolderCRCs;              // NumFolders

+  CObjArray<CNum> NumUnpackStreamsVector;  // NumFolders

+

+  CObjArray<UInt64> CoderUnpackSizes;      // including unpack sizes of bind coders

+  CObjArray<CNum> FoToCoderUnpackSizes;    // NumFolders + 1

+  CObjArray<CNum> FoStartPackStreamIndex;  // NumFolders + 1

+  CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders

   

+  CObjArray<size_t> FoCodersDataOffset;    // NumFolders + 1

+  CByteBuffer CodersData;

+

+  CParsedMethods ParsedMethods;

+

+  void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;

+  

+  unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const

+  {

+    return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];

+  }

+

+  UInt64 GetFolderUnpackSize(unsigned folderIndex) const

+  {

+    return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];

+  }

+

+  UInt64 GetStreamPackSize(unsigned index) const

+  {

+    return PackPositions[index + 1] - PackPositions[index];

+  }

+

+  void Clear()

+  {

+    NumPackStreams = 0;

+    PackPositions.Free();

+    // PackCRCs.Clear();

+

+    NumFolders = 0;

+    FolderCRCs.Clear();

+    NumUnpackStreamsVector.Free();

+    CoderUnpackSizes.Free();

+    FoToCoderUnpackSizes.Free();

+    FoStartPackStreamIndex.Free();

+    FoToMainUnpackSizeIndex.Free();

+    FoCodersDataOffset.Free();

+    CodersData.Free();

+  }

+};

+

+struct CDatabase: public CFolders

+{

+  CRecordVector<CFileItem> Files;

+

+  CUInt64DefVector CTime;

+  CUInt64DefVector ATime;

+  CUInt64DefVector MTime;

+  CUInt64DefVector StartPos;

+  CRecordVector<bool> IsAnti;

+  /*

+  CRecordVector<bool> IsAux;

+  CByteBuffer SecureBuf;

+  CRecordVector<UInt32> SecureIDs;

+  */

+

+  CByteBuffer NamesBuf;

+  CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols

+

+  /*

+  void ClearSecure()

+  {

+    SecureBuf.Free();

+    SecureIDs.Clear();

+  }

+  */

+

+  void Clear()

+  {

+    CFolders::Clear();

+    // ClearSecure();

+

+    NamesBuf.Free();

+    NameOffsets.Free();

+    

+    Files.Clear();

+    CTime.Clear();

+    ATime.Clear();

+    MTime.Clear();

+    StartPos.Clear();

+    IsAnti.Clear();

+    // IsAux.Clear();

+  }

+

+  bool IsSolid() const

+  {

+    for (CNum i = 0; i < NumFolders; i++)

+      if (NumUnpackStreamsVector[i] > 1)

+        return true;

+    return false;

+  }

+  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

+  {

+    if (!NameOffsets || !NamesBuf)

+      return NULL;

+    return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);

+  };

+

+  void GetPath(unsigned index, UString &path) const;

+  HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();

+};

+

 struct CInArchiveInfo

 {

   CArchiveVersion Version;

@@ -24,29 +167,73 @@
   UInt64 DataStartPosition;

   UInt64 DataStartPosition2;

   CRecordVector<UInt64> FileInfoPopIDs;

+  

   void Clear()

   {

+    StartPosition = 0;

+    StartPositionAfterHeader = 0;

+    DataStartPosition = 0;

+    DataStartPosition2 = 0;

     FileInfoPopIDs.Clear();

   }

 };

 

-struct CArchiveDatabaseEx: public CArchiveDatabase

+struct CDbEx: public CDatabase

 {

-  CInArchiveInfo ArchiveInfo;

-  CRecordVector<UInt64> PackStreamStartPositions;

-  CRecordVector<CNum> FolderStartPackStreamIndex;

+  CInArchiveInfo ArcInfo;

   CRecordVector<CNum> FolderStartFileIndex;

   CRecordVector<CNum> FileIndexToFolderIndexMap;

 

   UInt64 HeadersSize;

   UInt64 PhySize;

 

+  /*

+  CRecordVector<size_t> SecureOffsets;

+  bool IsTree;

+  bool ThereAreAltStreams;

+  */

+

+  bool IsArc;

+  bool PhySizeWasConfirmed;

+

+  bool ThereIsHeaderError;

+  bool UnexpectedEnd;

+  // bool UnsupportedVersion;

+

+  bool StartHeaderWasRecovered;

+  bool UnsupportedFeatureWarning;

+  bool UnsupportedFeatureError;

+

+  /*

+  void ClearSecureEx()

+  {

+    ClearSecure();

+    SecureOffsets.Clear();

+  }

+  */

+

   void Clear()

   {

-    CArchiveDatabase::Clear();

-    ArchiveInfo.Clear();

-    PackStreamStartPositions.Clear();

-    FolderStartPackStreamIndex.Clear();

+    IsArc = false;

+    PhySizeWasConfirmed = false;

+

+    ThereIsHeaderError = false;

+    UnexpectedEnd = false;

+    // UnsupportedVersion = false;

+

+    StartHeaderWasRecovered = false;

+    UnsupportedFeatureError = false;

+    UnsupportedFeatureWarning = false;

+

+    /*

+    IsTree = false;

+    ThereAreAltStreams = false;

+    */

+

+    CDatabase::Clear();

+    

+    // SecureOffsets.Clear();

+    ArcInfo.Clear();

     FolderStartFileIndex.Clear();

     FileIndexToFolderIndexMap.Clear();

 

@@ -54,36 +241,25 @@
     PhySize = 0;

   }

 

-  void FillFolderStartPackStream();

-  void FillStartPos();

-  void FillFolderStartFileIndex();

-

-  void Fill()

+  void FillLinks();

+  

+  UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const

   {

-    FillFolderStartPackStream();

-    FillStartPos();

-    FillFolderStartFileIndex();

+    return ArcInfo.DataStartPosition +

+        PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];

   }

   

-  UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const

+  UInt64 GetFolderFullPackSize(unsigned folderIndex) const

   {

-    return ArchiveInfo.DataStartPosition +

-        PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];

+    return

+      PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -

+      PackPositions[FoStartPackStreamIndex[folderIndex]];

   }

   

-  UInt64 GetFolderFullPackSize(int folderIndex) const

+  UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const

   {

-    CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];

-    const CFolder &folder = Folders[folderIndex];

-    UInt64 size = 0;

-    for (int i = 0; i < folder.PackStreams.Size(); i++)

-      size += PackSizes[packStreamIndex + i];

-    return size;

-  }

-  

-  UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const

-  {

-    return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];

+    unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;

+    return PackPositions[i + 1] - PackPositions[i];

   }

 

   UInt64 GetFilePackSize(CNum fileIndex) const

@@ -96,12 +272,17 @@
   }

 };

 

-class CInByte2

+const unsigned kNumBufLevelsMax = 4;

+

+struct CInByte2

 {

   const Byte *_buffer;

-  size_t _size;

 public:

+  size_t _size;

   size_t _pos;

+  

+  size_t GetRem() const { return _size - _pos; }

+  const Byte *GetPtr() const { return _buffer + _pos; }

   void Init(const Byte *buffer, size_t size)

   {

     _buffer = buffer;

@@ -110,13 +291,17 @@
   }

   Byte ReadByte();

   void ReadBytes(Byte *data, size_t size);

+  void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }

   void SkipData(UInt64 size);

+

   void SkipData();

+  void SkipRem() { _pos = _size; }

   UInt64 ReadNumber();

   CNum ReadNum();

   UInt32 ReadUInt32();

   UInt64 ReadUInt64();

-  void ReadString(UString &s);

+

+  void ParseFolder(CFolder &folder);

 };

 

 class CStreamSwitch;

@@ -129,27 +314,30 @@
 

   CMyComPtr<IInStream> _stream;

 

-  CObjectVector<CInByte2> _inByteVector;

+  unsigned _numInByteBufs;

+  CInByte2 _inByteVector[kNumBufLevelsMax];

+

   CInByte2 *_inByteBack;

+  bool ThereIsHeaderError;

  

   UInt64 _arhiveBeginStreamPosition;

+  UInt64 _fileEndPosition;

 

   Byte _header[kHeaderSize];

 

   UInt64 HeadersSize;

 

-  void AddByteStream(const Byte *buffer, size_t size)

-  {

-    _inByteVector.Add(CInByte2());

-    _inByteBack = &_inByteVector.Back();

-    _inByteBack->Init(buffer, size);

-  }

+  void AddByteStream(const Byte *buffer, size_t size);

   

-  void DeleteByteStream()

+  void DeleteByteStream(bool needUpdatePos)

   {

-    _inByteVector.DeleteBack();

-    if (!_inByteVector.IsEmpty())

-      _inByteBack = &_inByteVector.Back();

+    _numInByteBufs--;

+    if (_numInByteBufs > 0)

+    {

+      _inByteBack = &_inByteVector[_numInByteBufs - 1];

+      if (needUpdatePos)

+        _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;

+    }

   }

 

 private:

@@ -164,79 +352,58 @@
   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }

   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }

   void SkipData() { _inByteBack->SkipData(); }

-  void WaitAttribute(UInt64 attribute);

+  void WaitId(UInt64 id);

 

   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);

-  void GetNextFolderItem(CFolder &itemInfo);

-  void ReadHashDigests(int numItems,

-      CBoolVector &digestsDefined, CRecordVector<UInt32> &digests);

+  void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);

   

-  void ReadPackInfo(

-      UInt64 &dataOffset,

-      CRecordVector<UInt64> &packSizes,

-      CBoolVector &packCRCsDefined,

-      CRecordVector<UInt32> &packCRCs);

+  void ReadPackInfo(CFolders &f);

   

   void ReadUnpackInfo(

       const CObjectVector<CByteBuffer> *dataVector,

-      CObjectVector<CFolder> &folders);

+      CFolders &folders);

   

   void ReadSubStreamsInfo(

-      const CObjectVector<CFolder> &folders,

-      CRecordVector<CNum> &numUnpackStreamsInFolders,

+      CFolders &folders,

       CRecordVector<UInt64> &unpackSizes,

-      CBoolVector &digestsDefined,

-      CRecordVector<UInt32> &digests);

+      CUInt32DefVector &digests);

 

   void ReadStreamsInfo(

       const CObjectVector<CByteBuffer> *dataVector,

       UInt64 &dataOffset,

-      CRecordVector<UInt64> &packSizes,

-      CBoolVector &packCRCsDefined,

-      CRecordVector<UInt32> &packCRCs,

-      CObjectVector<CFolder> &folders,

-      CRecordVector<CNum> &numUnpackStreamsInFolders,

+      CFolders &folders,

       CRecordVector<UInt64> &unpackSizes,

-      CBoolVector &digestsDefined,

-      CRecordVector<UInt32> &digests);

+      CUInt32DefVector &digests);

 

-

-  void ReadBoolVector(int numItems, CBoolVector &v);

-  void ReadBoolVector2(int numItems, CBoolVector &v);

+  void ReadBoolVector(unsigned numItems, CBoolVector &v);

+  void ReadBoolVector2(unsigned numItems, CBoolVector &v);

   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,

-      CUInt64DefVector &v, int numFiles);

+      CUInt64DefVector &v, unsigned numItems);

   HRESULT ReadAndDecodePackedStreams(

       DECL_EXTERNAL_CODECS_LOC_VARS

       UInt64 baseOffset, UInt64 &dataOffset,

       CObjectVector<CByteBuffer> &dataVector

-      #ifndef _NO_CRYPTO

-      , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-      #endif

+      _7Z_DECODER_CRYPRO_VARS_DECL

       );

   HRESULT ReadHeader(

       DECL_EXTERNAL_CODECS_LOC_VARS

-      CArchiveDatabaseEx &db

-      #ifndef _NO_CRYPTO

-      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-      #endif

+      CDbEx &db

+      _7Z_DECODER_CRYPRO_VARS_DECL

       );

   HRESULT ReadDatabase2(

       DECL_EXTERNAL_CODECS_LOC_VARS

-      CArchiveDatabaseEx &db

-      #ifndef _NO_CRYPTO

-      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-      #endif

+      CDbEx &db

+      _7Z_DECODER_CRYPRO_VARS_DECL

       );

 public:

+  CInArchive(): _numInByteBufs(0) { }

   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive

   void Close();

 

   HRESULT ReadDatabase(

       DECL_EXTERNAL_CODECS_LOC_VARS

-      CArchiveDatabaseEx &db

-      #ifndef _NO_CRYPTO

-      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

-      #endif

+      CDbEx &db

+      _7Z_DECODER_CRYPRO_VARS_DECL

       );

 };

   

diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
old mode 100755
new mode 100644
index 3b01a8d..90e6869
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -3,7 +3,7 @@
 #ifndef __7Z_ITEM_H

 #define __7Z_ITEM_H

 

-#include "../../../Common/Buffer.h"

+#include "../../../Common/MyBuffer.h"

 #include "../../../Common/MyString.h"

 

 #include "../../Common/MethodId.h"

@@ -25,6 +25,7 @@
   CByteBuffer Props;

   CNum NumInStreams;

   CNum NumOutStreams;

+  

   bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

 };

 

@@ -36,55 +37,48 @@
 

 struct CFolder

 {

-  CObjectVector<CCoderInfo> Coders;

-  CRecordVector<CBindPair> BindPairs;

-  CRecordVector<CNum> PackStreams;

-  CRecordVector<UInt64> UnpackSizes;

-  UInt32 UnpackCRC;

-  bool UnpackCRCDefined;

-

-  CFolder(): UnpackCRCDefined(false) {}

-

-  UInt64 GetUnpackSize() const // test it

-  {

-    if (UnpackSizes.IsEmpty())

-      return 0;

-    for (int i = UnpackSizes.Size() - 1; i >= 0; i--)

-      if (FindBindPairForOutStream(i) < 0)

-        return UnpackSizes[i];

-    throw 1;

-  }

+  CObjArray2<CCoderInfo> Coders;

+  CObjArray2<CBindPair> BindPairs;

+  CObjArray2<CNum> PackStreams;

 

   CNum GetNumOutStreams() const

   {

     CNum result = 0;

-    for (int i = 0; i < Coders.Size(); i++)

+    FOR_VECTOR(i, Coders)

       result += Coders[i].NumOutStreams;

     return result;

   }

 

   int FindBindPairForInStream(CNum inStreamIndex) const

   {

-    for(int i = 0; i < BindPairs.Size(); i++)

+    FOR_VECTOR(i, BindPairs)

       if (BindPairs[i].InIndex == inStreamIndex)

         return i;

     return -1;

   }

   int FindBindPairForOutStream(CNum outStreamIndex) const

   {

-    for(int i = 0; i < BindPairs.Size(); i++)

+    FOR_VECTOR(i, BindPairs)

       if (BindPairs[i].OutIndex == outStreamIndex)

         return i;

     return -1;

   }

   int FindPackStreamArrayIndex(CNum inStreamIndex) const

   {

-    for(int i = 0; i < PackStreams.Size(); i++)

+    FOR_VECTOR(i, PackStreams)

       if (PackStreams[i] == inStreamIndex)

         return i;

     return -1;

   }

 

+  int GetIndexOfMainOutStream() const

+  {

+    for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)

+      if (FindBindPairForOutStream(i) < 0)

+        return i;

+    throw 1;

+  }

+

   bool IsEncrypted() const

   {

     for (int i = Coders.Size() - 1; i >= 0; i--)

@@ -93,50 +87,66 @@
     return false;

   }

 

-  bool CheckStructure() const;

+  bool CheckStructure(unsigned numUnpackSizes) const;

+};

+

+struct CUInt32DefVector

+{

+  CBoolVector Defs;

+  CRecordVector<UInt32> Vals;

+

+  void ClearAndSetSize(unsigned newSize)

+  {

+    Defs.ClearAndSetSize(newSize);

+    Vals.ClearAndSetSize(newSize);

+  }

+

+  void Clear()

+  {

+    Defs.Clear();

+    Vals.Clear();

+  }

+

+  void ReserveDown()

+  {

+    Defs.ReserveDown();

+    Vals.ReserveDown();

+  }

+

+  bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }

 };

 

 struct CUInt64DefVector

 {

-  CRecordVector<UInt64> Values;

-  CRecordVector<bool> Defined;

+  CBoolVector Defs;

+  CRecordVector<UInt64> Vals;

   

   void Clear()

   {

-    Values.Clear();

-    Defined.Clear();

+    Defs.Clear();

+    Vals.Clear();

   }

   

   void ReserveDown()

   {

-    Values.ReserveDown();

-    Values.ReserveDown();

+    Defs.ReserveDown();

+    Vals.ReserveDown();

   }

 

-  bool GetItem(int index, UInt64 &value) const

+  bool GetItem(unsigned index, UInt64 &value) const

   {

-    if (index < Defined.Size() && Defined[index])

+    if (index < Defs.Size() && Defs[index])

     {

-      value = Values[index];

+      value = Vals[index];

       return true;

     }

     value = 0;

     return false;

   }

   

-  void SetItem(int index, bool defined, UInt64 value)

-  {

-    while (index >= Defined.Size())

-      Defined.Add(false);

-    Defined[index] = defined;

-    if (!defined)

-      return;

-    while (index >= Values.Size())

-      Values.Add(0);

-    Values[index] = value;

-  }

+  void SetItem(unsigned index, bool defined, UInt64 value);

 

-  bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; }

+  bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }

 };

 

 struct CFileItem

@@ -144,8 +154,10 @@
   UInt64 Size;

   UInt32 Attrib;

   UInt32 Crc;

-  UString Name;

-

+  /*

+  int Parent;

+  bool IsAltStream;

+  */

   bool HasStream; // Test it !!! it means that there is

                   // stream in some folder. It can be empty stream

   bool IsDir;

@@ -153,6 +165,10 @@
   bool AttribDefined;

 

   CFileItem():

+    /*

+    Parent(-1),

+    IsAltStream(false),

+    */

     HasStream(true),

     IsDir(false),

     CrcDefined(false),

@@ -165,104 +181,6 @@
   }

 };

 

-struct CFileItem2

-{

-  UInt64 CTime;

-  UInt64 ATime;

-  UInt64 MTime;

-  UInt64 StartPos;

-  bool CTimeDefined;

-  bool ATimeDefined;

-  bool MTimeDefined;

-  bool StartPosDefined;

-  bool IsAnti;

-};

-

-struct CArchiveDatabase

-{

-  CRecordVector<UInt64> PackSizes;

-  CRecordVector<bool> PackCRCsDefined;

-  CRecordVector<UInt32> PackCRCs;

-  CObjectVector<CFolder> Folders;

-  CRecordVector<CNum> NumUnpackStreamsVector;

-  CObjectVector<CFileItem> Files;

-

-  CUInt64DefVector CTime;

-  CUInt64DefVector ATime;

-  CUInt64DefVector MTime;

-  CUInt64DefVector StartPos;

-  CRecordVector<bool> IsAnti;

-

-  void Clear()

-  {

-    PackSizes.Clear();

-    PackCRCsDefined.Clear();

-    PackCRCs.Clear();

-    Folders.Clear();

-    NumUnpackStreamsVector.Clear();

-    Files.Clear();

-    CTime.Clear();

-    ATime.Clear();

-    MTime.Clear();

-    StartPos.Clear();

-    IsAnti.Clear();

-  }

-

-  void ReserveDown()

-  {

-    PackSizes.ReserveDown();

-    PackCRCsDefined.ReserveDown();

-    PackCRCs.ReserveDown();

-    Folders.ReserveDown();

-    NumUnpackStreamsVector.ReserveDown();

-    Files.ReserveDown();

-    CTime.ReserveDown();

-    ATime.ReserveDown();

-    MTime.ReserveDown();

-    StartPos.ReserveDown();

-    IsAnti.ReserveDown();

-  }

-

-  bool IsEmpty() const

-  {

-    return (PackSizes.IsEmpty() &&

-      PackCRCsDefined.IsEmpty() &&

-      PackCRCs.IsEmpty() &&

-      Folders.IsEmpty() &&

-      NumUnpackStreamsVector.IsEmpty() &&

-      Files.IsEmpty());

-  }

-

-  bool CheckNumFiles() const

-  {

-    int size = Files.Size();

-    return (

-      CTime.CheckSize(size) &&

-      ATime.CheckSize(size) &&

-      MTime.CheckSize(size) &&

-      StartPos.CheckSize(size) &&

-      (size == IsAnti.Size() || IsAnti.Size() == 0));

-  }

-

-  bool IsSolid() const

-  {

-    for (int i = 0; i < NumUnpackStreamsVector.Size(); i++)

-      if (NumUnpackStreamsVector[i] > 1)

-        return true;

-    return false;

-  }

-  bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); }

-  void SetItemAnti(int index, bool isAnti)

-  {

-    while (index >= IsAnti.Size())

-      IsAnti.Add(false);

-    IsAnti[index] = isAnti;

-  }

-

-  void GetFile(int index, CFileItem &file, CFileItem2 &file2) const;

-  void AddFile(const CFileItem &file, const CFileItem2 &file2);

-};

-

 }}

 

 #endif

diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
old mode 100755
new mode 100644
index b34a2c9..cf776ce
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -10,35 +10,15 @@
 

 #include "7zOut.h"

 

-static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)

-{

-  while (size > 0)

-  {

-    UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);

-    UInt32 processedSize;

-    RINOK(stream->Write(data, curSize, &processedSize));

-    if (processedSize == 0)

-      return E_FAIL;

-    data = (const void *)((const Byte *)data + processedSize);

-    size -= processedSize;

-  }

-  return S_OK;

-}

-

 namespace NArchive {

 namespace N7z {

 

-HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)

-{

-  return ::WriteBytes(SeqStream, data, size);

-}

-

 HRESULT COutArchive::WriteSignature()

 {

   Byte buf[8];

   memcpy(buf, kSignature, kSignatureSize);

   buf[kSignatureSize] = kMajorVersion;

-  buf[kSignatureSize + 1] = 3;

+  buf[kSignatureSize + 1] = 4;

   return WriteDirect(buf, 8);

 }

 

@@ -145,7 +125,9 @@
   if (_endMarker)

     return S_OK;

   #endif

-  return Stream->Seek(24, STREAM_SEEK_CUR, NULL);

+  Byte buf[24];

+  memset(buf, 0, 24);

+  return WriteDirect(buf, 24);

 }

 

 UInt64 COutArchive::GetPos() const

@@ -271,19 +253,19 @@
 void COutArchive::WriteFolder(const CFolder &folder)

 {

   WriteNumber(folder.Coders.Size());

-  int i;

+  unsigned i;

   for (i = 0; i < folder.Coders.Size(); i++)

   {

     const CCoderInfo &coder = folder.Coders[i];

     {

-      size_t propsSize = coder.Props.GetCapacity();

+      size_t propsSize = coder.Props.Size();

       

       UInt64 id = coder.MethodID;

       int idSize;

       for (idSize = 1; idSize < sizeof(id); idSize++)

         if ((id >> (8 * idSize)) == 0)

           break;

-      BYTE longID[15];

+      Byte longID[15];

       for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)

         longID[t] = (Byte)(id & 0xFF);

       Byte b;

@@ -321,7 +303,7 @@
 {

   Byte b = 0;

   Byte mask = 0x80;

-  for (int i = 0; i < boolVector.Size(); i++)

+  FOR_VECTOR (i, boolVector)

   {

     if (boolVector[i])

       b |= mask;

@@ -337,37 +319,42 @@
     WriteByte(b);

 }

 

+static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }

 

-void COutArchive::WriteHashDigests(

-    const CRecordVector<bool> &digestsDefined,

-    const CRecordVector<UInt32> &digests)

+void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)

 {

-  int numDefined = 0;

-  int i;

-  for (i = 0; i < digestsDefined.Size(); i++)

-    if (digestsDefined[i])

+  WriteByte(id);

+  WriteNumber(Bv_GetSizeInBytes(boolVector));

+  WriteBoolVector(boolVector);

+}

+

+void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)

+{

+  unsigned numDefined = 0;

+  unsigned i;

+  for (i = 0; i < digests.Defs.Size(); i++)

+    if (digests.Defs[i])

       numDefined++;

   if (numDefined == 0)

     return;

 

   WriteByte(NID::kCRC);

-  if (numDefined == digestsDefined.Size())

+  if (numDefined == digests.Defs.Size())

     WriteByte(1);

   else

   {

     WriteByte(0);

-    WriteBoolVector(digestsDefined);

+    WriteBoolVector(digests.Defs);

   }

-  for (i = 0; i < digests.Size(); i++)

-    if (digestsDefined[i])

-      WriteUInt32(digests[i]);

+  for (i = 0; i < digests.Defs.Size(); i++)

+    if (digests.Defs[i])

+      WriteUInt32(digests.Vals[i]);

 }

 

 void COutArchive::WritePackInfo(

     UInt64 dataOffset,

     const CRecordVector<UInt64> &packSizes,

-    const CRecordVector<bool> &packCRCsDefined,

-    const CRecordVector<UInt32> &packCRCs)

+    const CUInt32DefVector &packCRCs)

 {

   if (packSizes.IsEmpty())

     return;

@@ -375,15 +362,15 @@
   WriteNumber(dataOffset);

   WriteNumber(packSizes.Size());

   WriteByte(NID::kSize);

-  for (int i = 0; i < packSizes.Size(); i++)

+  FOR_VECTOR (i, packSizes)

     WriteNumber(packSizes[i]);

 

-  WriteHashDigests(packCRCsDefined, packCRCs);

+  WriteHashDigests(packCRCs);

   

   WriteByte(NID::kEnd);

 }

 

-void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)

+void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)

 {

   if (folders.IsEmpty())

     return;

@@ -394,44 +381,29 @@
   WriteNumber(folders.Size());

   {

     WriteByte(0);

-    for (int i = 0; i < folders.Size(); i++)

+    FOR_VECTOR (i, folders)

       WriteFolder(folders[i]);

   }

   

   WriteByte(NID::kCodersUnpackSize);

-  int i;

-  for (i = 0; i < folders.Size(); i++)

-  {

-    const CFolder &folder = folders[i];

-    for (int j = 0; j < folder.UnpackSizes.Size(); j++)

-      WriteNumber(folder.UnpackSizes[j]);

-  }

-

-  CRecordVector<bool> unpackCRCsDefined;

-  CRecordVector<UInt32> unpackCRCs;

-  for (i = 0; i < folders.Size(); i++)

-  {

-    const CFolder &folder = folders[i];

-    unpackCRCsDefined.Add(folder.UnpackCRCDefined);

-    unpackCRCs.Add(folder.UnpackCRC);

-  }

-  WriteHashDigests(unpackCRCsDefined, unpackCRCs);

-

+  FOR_VECTOR (i, outFolders.CoderUnpackSizes)

+    WriteNumber(outFolders.CoderUnpackSizes[i]);

+  

+  WriteHashDigests(outFolders.FolderUnpackCRCs);

+  

   WriteByte(NID::kEnd);

 }

 

-void COutArchive::WriteSubStreamsInfo(

-    const CObjectVector<CFolder> &folders,

-    const CRecordVector<CNum> &numUnpackStreamsInFolders,

+void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,

+    const COutFolders &outFolders,

     const CRecordVector<UInt64> &unpackSizes,

-    const CRecordVector<bool> &digestsDefined,

-    const CRecordVector<UInt32> &digests)

+    const CUInt32DefVector &digests)

 {

+  const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;

   WriteByte(NID::kSubStreamsInfo);

 

-  int i;

+  unsigned i;

   for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

-  {

     if (numUnpackStreamsInFolders[i] != 1)

     {

       WriteByte(NID::kNumUnpackStream);

@@ -439,54 +411,50 @@
         WriteNumber(numUnpackStreamsInFolders[i]);

       break;

     }

-  }

  

-

-  bool needFlag = true;

-  CNum index = 0;

   for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

-    for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)

+    if (numUnpackStreamsInFolders[i] > 1)

     {

-      if (j + 1 != numUnpackStreamsInFolders[i])

+      WriteByte(NID::kSize);

+      CNum index = 0;

+      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

       {

-        if (needFlag)

-          WriteByte(NID::kSize);

-        needFlag = false;

-        WriteNumber(unpackSizes[index]);

+        CNum num = numUnpackStreamsInFolders[i];

+        for (CNum j = 0; j < num; j++)

+        {

+          if (j + 1 != num)

+            WriteNumber(unpackSizes[index]);

+          index++;

+        }

       }

-      index++;

+      break;

     }

 

-  CRecordVector<bool> digestsDefined2;

-  CRecordVector<UInt32> digests2;

+  CUInt32DefVector digests2;

 

-  int digestIndex = 0;

+  unsigned digestIndex = 0;

   for (i = 0; i < folders.Size(); i++)

   {

-    int numSubStreams = (int)numUnpackStreamsInFolders[i];

-    if (numSubStreams == 1 && folders[i].UnpackCRCDefined)

+    unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];

+    if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))

       digestIndex++;

     else

-      for (int j = 0; j < numSubStreams; j++, digestIndex++)

+      for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)

       {

-        digestsDefined2.Add(digestsDefined[digestIndex]);

-        digests2.Add(digests[digestIndex]);

+        digests2.Defs.Add(digests.Defs[digestIndex]);

+        digests2.Vals.Add(digests.Vals[digestIndex]);

       }

   }

-  WriteHashDigests(digestsDefined2, digests2);

+  WriteHashDigests(digests2);

   WriteByte(NID::kEnd);

 }

 

-void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)

-{

-  return;

-}

-

-/*

-7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.

+// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.

 

 void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)

 {

+  if (!_useAlign)

+    return;

   pos += (unsigned)GetPos();

   pos &= (alignSize - 1);

   if (pos == 0)

@@ -500,11 +468,8 @@
   for (unsigned i = 0; i < skip; i++)

     WriteByte(0);

 }

-*/

 

-static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }

-

-void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize)

+void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize)

 {

   const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);

   const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;

@@ -524,48 +489,53 @@
 

 void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)

 {

-  int numDefined = 0;

+  unsigned numDefined = 0;

 

-  int i;

-  for (i = 0; i < v.Defined.Size(); i++)

-    if (v.Defined[i])

+  unsigned i;

+  for (i = 0; i < v.Defs.Size(); i++)

+    if (v.Defs[i])

       numDefined++;

 

   if (numDefined == 0)

     return;

 

-  WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);

+  WriteAlignedBoolHeader(v.Defs, numDefined, type, 8);

   

-  for (i = 0; i < v.Defined.Size(); i++)

-    if (v.Defined[i])

-      WriteUInt64(v.Values[i]);

+  for (i = 0; i < v.Defs.Size(); i++)

+    if (v.Defs[i])

+      WriteUInt64(v.Vals[i]);

 }

 

 HRESULT COutArchive::EncodeStream(

     DECL_EXTERNAL_CODECS_LOC_VARS

     CEncoder &encoder, const CByteBuffer &data,

-    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)

+    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)

 {

   CBufInStream *streamSpec = new CBufInStream;

   CMyComPtr<ISequentialInStream> stream = streamSpec;

-  streamSpec->Init(data, data.GetCapacity());

-  CFolder folderItem;

-  folderItem.UnpackCRCDefined = true;

-  folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());

-  UInt64 dataSize64 = data.GetCapacity();

+  streamSpec->Init(data, data.Size());

+  outFolders.FolderUnpackCRCs.Defs.Add(true);

+  outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));

+  // outFolders.NumUnpackStreamsVector.Add(1);

+  UInt64 dataSize64 = data.Size();

+  UInt64 unpackSize;

   RINOK(encoder.Encode(

       EXTERNAL_CODECS_LOC_VARS

-      stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))

-  folders.Add(folderItem);

+      stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))

   return S_OK;

 }

 

 void COutArchive::WriteHeader(

-    const CArchiveDatabase &db,

-    const CHeaderOptions &headerOptions,

+    const CArchiveDatabaseOut &db,

+    // const CHeaderOptions &headerOptions,

     UInt64 &headerOffset)

 {

-  int i;

+  /*

+  bool thereIsSecure = (db.SecureBuf.Size() != 0);

+  */

+  _useAlign = true;

+

+  unsigned i;

   

   UInt64 packedSize = 0;

   for (i = 0; i < db.PackSizes.Size(); i++)

@@ -580,31 +550,22 @@
   if (db.Folders.Size() > 0)

   {

     WriteByte(NID::kMainStreamsInfo);

-    WritePackInfo(0, db.PackSizes,

-        db.PackCRCsDefined,

-        db.PackCRCs);

-

-    WriteUnpackInfo(db.Folders);

+    WritePackInfo(0, db.PackSizes, db.PackCRCs);

+    WriteUnpackInfo(db.Folders, (const COutFolders &)db);

 

     CRecordVector<UInt64> unpackSizes;

-    CRecordVector<bool> digestsDefined;

-    CRecordVector<UInt32> digests;

+    CUInt32DefVector digests;

     for (i = 0; i < db.Files.Size(); i++)

     {

       const CFileItem &file = db.Files[i];

       if (!file.HasStream)

         continue;

       unpackSizes.Add(file.Size);

-      digestsDefined.Add(file.CrcDefined);

-      digests.Add(file.Crc);

+      digests.Defs.Add(file.CrcDefined);

+      digests.Vals.Add(file.Crc);

     }

 

-    WriteSubStreamsInfo(

-        db.Folders,

-        db.NumUnpackStreamsVector,

-        unpackSizes,

-        digestsDefined,

-        digests);

+    WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);

     WriteByte(NID::kEnd);

   }

 

@@ -618,85 +579,75 @@
   WriteNumber(db.Files.Size());

 

   {

-  /* ---------- Empty Streams ---------- */

-  CBoolVector emptyStreamVector;

-  emptyStreamVector.Reserve(db.Files.Size());

-  int numEmptyStreams = 0;

-  for (i = 0; i < db.Files.Size(); i++)

-    if (db.Files[i].HasStream)

-      emptyStreamVector.Add(false);

-    else

-    {

-      emptyStreamVector.Add(true);

-      numEmptyStreams++;

-    }

-  if (numEmptyStreams > 0)

-  {

-    WriteByte(NID::kEmptyStream);

-    WriteNumber(Bv_GetSizeInBytes(emptyStreamVector));

-    WriteBoolVector(emptyStreamVector);

-

-    CBoolVector emptyFileVector, antiVector;

-    emptyFileVector.Reserve(numEmptyStreams);

-    antiVector.Reserve(numEmptyStreams);

-    CNum numEmptyFiles = 0, numAntiItems = 0;

+    /* ---------- Empty Streams ---------- */

+    CBoolVector emptyStreamVector;

+    emptyStreamVector.ClearAndSetSize(db.Files.Size());

+    unsigned numEmptyStreams = 0;

     for (i = 0; i < db.Files.Size(); i++)

-    {

-      const CFileItem &file = db.Files[i];

-      if (!file.HasStream)

+      if (db.Files[i].HasStream)

+        emptyStreamVector[i] = false;

+      else

       {

-        emptyFileVector.Add(!file.IsDir);

-        if (!file.IsDir)

-          numEmptyFiles++;

-        bool isAnti = db.IsItemAnti(i);

-        antiVector.Add(isAnti);

-        if (isAnti)

-          numAntiItems++;

+        emptyStreamVector[i] = true;

+        numEmptyStreams++;

       }

-    }

-

-    if (numEmptyFiles > 0)

+    if (numEmptyStreams != 0)

     {

-      WriteByte(NID::kEmptyFile);

-      WriteNumber(Bv_GetSizeInBytes(emptyFileVector));

-      WriteBoolVector(emptyFileVector);

+      WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);

+      

+      CBoolVector emptyFileVector, antiVector;

+      emptyFileVector.ClearAndSetSize(numEmptyStreams);

+      antiVector.ClearAndSetSize(numEmptyStreams);

+      bool thereAreEmptyFiles = false, thereAreAntiItems = false;

+      unsigned cur = 0;

+      for (i = 0; i < db.Files.Size(); i++)

+      {

+        const CFileItem &file = db.Files[i];

+        if (file.HasStream)

+          continue;

+        emptyFileVector[cur] = !file.IsDir;

+        if (!file.IsDir)

+          thereAreEmptyFiles = true;

+        bool isAnti = db.IsItemAnti(i);

+        antiVector[cur] = isAnti;

+        if (isAnti)

+          thereAreAntiItems = true;

+        cur++;

+      }

+      

+      if (thereAreEmptyFiles)

+        WritePropBoolVector(NID::kEmptyFile, emptyFileVector);

+      if (thereAreAntiItems)

+        WritePropBoolVector(NID::kAnti, antiVector);

     }

-

-    if (numAntiItems > 0)

-    {

-      WriteByte(NID::kAnti);

-      WriteNumber(Bv_GetSizeInBytes(antiVector));

-      WriteBoolVector(antiVector);

-    }

-  }

   }

 

 

   {

     /* ---------- Names ---------- */

     

-    int numDefined = 0;

+    unsigned numDefined = 0;

     size_t namesDataSize = 0;

-    for (int i = 0; i < db.Files.Size(); i++)

+    FOR_VECTOR (i, db.Files)

     {

-      const UString &name = db.Files[i].Name;

+      const UString &name = db.Names[i];

       if (!name.IsEmpty())

         numDefined++;

-      namesDataSize += (name.Length() + 1) * 2;

+      namesDataSize += (name.Len() + 1) * 2;

     }

     

     if (numDefined > 0)

     {

       namesDataSize++;

-      SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);

+      SkipAlign(2 + GetBigNumberSize(namesDataSize), 16);

 

       WriteByte(NID::kName);

       WriteNumber(namesDataSize);

       WriteByte(0);

-      for (int i = 0; i < db.Files.Size(); i++)

+      FOR_VECTOR (i, db.Files)

       {

-        const UString &name = db.Files[i].Name;

-        for (int t = 0; t <= name.Length(); t++)

+        const UString &name = db.Names[i];

+        for (unsigned t = 0; t <= name.Len(); t++)

         {

           wchar_t c = name[t];

           WriteByte((Byte)c);

@@ -706,26 +657,26 @@
     }

   }

 

-  if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);

-  if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);

-  if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);

+  /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);

+  /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);

+  /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);

   WriteUInt64DefVector(db.StartPos, NID::kStartPos);

   

   {

     /* ---------- Write Attrib ---------- */

     CBoolVector boolVector;

-    boolVector.Reserve(db.Files.Size());

-    int numDefined = 0;

+    boolVector.ClearAndSetSize(db.Files.Size());

+    unsigned numDefined = 0;

     for (i = 0; i < db.Files.Size(); i++)

     {

       bool defined = db.Files[i].AttribDefined;

-      boolVector.Add(defined);

+      boolVector[i] = defined;

       if (defined)

         numDefined++;

     }

-    if (numDefined > 0)

+    if (numDefined != 0)

     {

-      WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);

+      WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);

       for (i = 0; i < db.Files.Size(); i++)

       {

         const CFileItem &file = db.Files[i];

@@ -735,13 +686,95 @@
     }

   }

 

+  /*

+  {

+    // ---------- Write IsAux ----------

+    unsigned numAux = 0;

+    const CBoolVector &isAux = db.IsAux;

+    for (i = 0; i < isAux.Size(); i++)

+      if (isAux[i])

+        numAux++;

+    if (numAux > 0)

+    {

+      const unsigned bvSize = Bv_GetSizeInBytes(isAux);

+      WriteByte(NID::kIsAux);

+      WriteNumber(bvSize);

+      WriteBoolVector(isAux);

+    }

+  }

+

+  {

+    // ---------- Write Parent ----------

+    CBoolVector boolVector;

+    boolVector.Reserve(db.Files.Size());

+    unsigned numIsDir = 0;

+    unsigned numParentLinks = 0;

+    for (i = 0; i < db.Files.Size(); i++)

+    {

+      const CFileItem &file = db.Files[i];

+      bool defined = !file.IsAltStream;

+      boolVector.Add(defined);

+      if (defined)

+        numIsDir++;

+      if (file.Parent >= 0)

+        numParentLinks++;

+    }

+    if (numParentLinks > 0)

+    {

+      // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4);

+      const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);

+      const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;

+      SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4);

+      

+      WriteByte(NID::kParent);

+      WriteNumber(dataSize);

+      if (numIsDir == boolVector.Size())

+        WriteByte(1);

+      else

+      {

+        WriteByte(0);

+        WriteBoolVector(boolVector);

+      }

+      for (i = 0; i < db.Files.Size(); i++)

+      {

+        const CFileItem &file = db.Files[i];

+        // if (file.Parent >= 0)

+          WriteUInt32(file.Parent);

+      }

+    }

+  }

+

+  if (thereIsSecure)

+  {

+    UInt64 secureDataSize = 1 + 4 +

+       db.SecureBuf.Size() +

+       db.SecureSizes.Size() * 4;

+    // secureDataSize += db.SecureIDs.Size() * 4;

+    for (i = 0; i < db.SecureIDs.Size(); i++)

+      secureDataSize += GetBigNumberSize(db.SecureIDs[i]);

+    SkipAlign(2 + GetBigNumberSize(secureDataSize), 4);

+    WriteByte(NID::kNtSecure);

+    WriteNumber(secureDataSize);

+    WriteByte(0);

+    WriteUInt32(db.SecureSizes.Size());

+    for (i = 0; i < db.SecureSizes.Size(); i++)

+      WriteUInt32(db.SecureSizes[i]);

+    WriteBytes(db.SecureBuf, db.SecureBuf.Size());

+    for (i = 0; i < db.SecureIDs.Size(); i++)

+    {

+      WriteNumber(db.SecureIDs[i]);

+      // WriteUInt32(db.SecureIDs[i]);

+    }

+  }

+  */

+

   WriteByte(NID::kEnd); // for files

   WriteByte(NID::kEnd); // for headers

 }

 

 HRESULT COutArchive::WriteDatabase(

     DECL_EXTERNAL_CODECS_LOC_VARS

-    const CArchiveDatabase &db,

+    const CArchiveDatabaseOut &db,

     const CCompressionMethodMode *options,

     const CHeaderOptions &headerOptions)

 {

@@ -773,17 +806,16 @@
     _countMode = encodeHeaders;

     _writeToStream = true;

     _countSize = 0;

-    WriteHeader(db, headerOptions, headerOffset);

+    WriteHeader(db, /* headerOptions, */ headerOffset);

 

     if (encodeHeaders)

     {

-      CByteBuffer buf;

-      buf.SetCapacity(_countSize);

+      CByteBuffer buf(_countSize);

       _outByte2.Init((Byte *)buf, _countSize);

       

       _countMode = false;

       _writeToStream = false;

-      WriteHeader(db, headerOptions, headerOffset);

+      WriteHeader(db, /* headerOptions, */ headerOffset);

       

       if (_countSize != _outByte2.GetPos())

         return E_FAIL;

@@ -794,10 +826,12 @@
       CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);

       CRecordVector<UInt64> packSizes;

       CObjectVector<CFolder> folders;

+      COutFolders outFolders;

+

       RINOK(EncodeStream(

           EXTERNAL_CODECS_LOC_VARS

           encoder, buf,

-          packSizes, folders));

+          packSizes, folders, outFolders));

 

       _writeToStream = true;

       

@@ -805,11 +839,10 @@
         throw 1;

 

       WriteID(NID::kEncodedHeader);

-      WritePackInfo(headerOffset, packSizes,

-        CRecordVector<bool>(), CRecordVector<UInt32>());

-      WriteUnpackInfo(folders);

+      WritePackInfo(headerOffset, packSizes, CUInt32DefVector());

+      WriteUnpackInfo(folders, outFolders);

       WriteByte(NID::kEnd);

-      for (int i = 0; i < packSizes.Size(); i++)

+      FOR_VECTOR (i, packSizes)

         headerOffset += packSizes[i];

     }

     RINOK(_outByte.Flush());

@@ -842,24 +875,28 @@
   }

 }

 

-void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const

+void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)

 {

-  file = Files[index];

-  file2.CTimeDefined = CTime.GetItem(index, file2.CTime);

-  file2.ATimeDefined = ATime.GetItem(index, file2.ATime);

-  file2.MTimeDefined = MTime.GetItem(index, file2.MTime);

-  file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);

-  file2.IsAnti = IsItemAnti(index);

+  while (index >= Defs.Size())

+    Defs.Add(false);

+  Defs[index] = defined;

+  if (!defined)

+    return;

+  while (index >= Vals.Size())

+    Vals.Add(0);

+  Vals[index] = value;

 }

 

-void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)

+void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)

 {

-  int index = Files.Size();

+  unsigned index = Files.Size();

   CTime.SetItem(index, file2.CTimeDefined, file2.CTime);

   ATime.SetItem(index, file2.ATimeDefined, file2.ATime);

   MTime.SetItem(index, file2.MTimeDefined, file2.MTime);

   StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);

-  SetItemAnti(index, file2.IsAnti);

+  SetItem_Anti(index, file2.IsAnti);

+  // SetItem_Aux(index, file2.IsAux);

+  Names.Add(name);

   Files.Add(file);

 }

 

diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
old mode 100755
new mode 100644
index bdd465c..07dbd63
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -9,6 +9,7 @@
 #include "7zItem.h"

 

 #include "../../Common/OutBuffer.h"

+#include "../../Common/StreamUtils.h"

 

 namespace NArchive {

 namespace N7z {

@@ -45,27 +46,191 @@
 struct CHeaderOptions

 {

   bool CompressMainHeader;

+  /*

   bool WriteCTime;

   bool WriteATime;

   bool WriteMTime;

+  */

 

   CHeaderOptions():

-      CompressMainHeader(true),

-      WriteCTime(false),

-      WriteATime(false),

-      WriteMTime(true)

+      CompressMainHeader(true)

+      /*

+      , WriteCTime(false)

+      , WriteATime(false)

+      , WriteMTime(true)

+      */

       {}

 };

 

+

+struct CFileItem2

+{

+  UInt64 CTime;

+  UInt64 ATime;

+  UInt64 MTime;

+  UInt64 StartPos;

+  bool CTimeDefined;

+  bool ATimeDefined;

+  bool MTimeDefined;

+  bool StartPosDefined;

+  bool IsAnti;

+  // bool IsAux;

+

+  void Init()

+  {

+    CTimeDefined = false;

+    ATimeDefined = false;

+    MTimeDefined = false;

+    StartPosDefined = false;

+    IsAnti = false;

+    // IsAux = false;

+  }

+};

+

+struct COutFolders

+{

+  CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.

+

+  CRecordVector<CNum> NumUnpackStreamsVector;

+  CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders

+

+  void OutFoldersClear()

+  {

+    FolderUnpackCRCs.Clear();

+    NumUnpackStreamsVector.Clear();

+    CoderUnpackSizes.Clear();

+  }

+

+  void OutFoldersReserveDown()

+  {

+    FolderUnpackCRCs.ReserveDown();

+    NumUnpackStreamsVector.ReserveDown();

+    CoderUnpackSizes.ReserveDown();

+  }

+};

+

+struct CArchiveDatabaseOut: public COutFolders

+{

+  CRecordVector<UInt64> PackSizes;

+  CUInt32DefVector PackCRCs;

+  CObjectVector<CFolder> Folders;

+

+  CRecordVector<CFileItem> Files;

+  UStringVector Names;

+  CUInt64DefVector CTime;

+  CUInt64DefVector ATime;

+  CUInt64DefVector MTime;

+  CUInt64DefVector StartPos;

+  CRecordVector<bool> IsAnti;

+

+  /*

+  CRecordVector<bool> IsAux;

+

+  CByteBuffer SecureBuf;

+  CRecordVector<UInt32> SecureSizes;

+  CRecordVector<UInt32> SecureIDs;

+

+  void ClearSecure()

+  {

+    SecureBuf.Free();

+    SecureSizes.Clear();

+    SecureIDs.Clear();

+  }

+  */

+

+  void Clear()

+  {

+    OutFoldersClear();

+

+    PackSizes.Clear();

+    PackCRCs.Clear();

+    Folders.Clear();

+  

+    Files.Clear();

+    Names.Clear();

+    CTime.Clear();

+    ATime.Clear();

+    MTime.Clear();

+    StartPos.Clear();

+    IsAnti.Clear();

+

+    /*

+    IsAux.Clear();

+    ClearSecure();

+    */

+  }

+

+  void ReserveDown()

+  {

+    OutFoldersReserveDown();

+

+    PackSizes.ReserveDown();

+    PackCRCs.ReserveDown();

+    Folders.ReserveDown();

+    

+    Files.ReserveDown();

+    Names.ReserveDown();

+    CTime.ReserveDown();

+    ATime.ReserveDown();

+    MTime.ReserveDown();

+    StartPos.ReserveDown();

+    IsAnti.ReserveDown();

+

+    /*

+    IsAux.ReserveDown();

+    */

+  }

+

+  bool IsEmpty() const

+  {

+    return (

+      PackSizes.IsEmpty() &&

+      NumUnpackStreamsVector.IsEmpty() &&

+      Folders.IsEmpty() &&

+      Files.IsEmpty());

+  }

+

+  bool CheckNumFiles() const

+  {

+    unsigned size = Files.Size();

+    return (

+      CTime.CheckSize(size) &&

+      ATime.CheckSize(size) &&

+      MTime.CheckSize(size) &&

+      StartPos.CheckSize(size) &&

+      (size == IsAnti.Size() || IsAnti.Size() == 0));

+  }

+

+  bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }

+  // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }

+

+  void SetItem_Anti(unsigned index, bool isAnti)

+  {

+    while (index >= IsAnti.Size())

+      IsAnti.Add(false);

+    IsAnti[index] = isAnti;

+  }

+  /*

+  void SetItem_Aux(unsigned index, bool isAux)

+  {

+    while (index >= IsAux.Size())

+      IsAux.Add(false);

+    IsAux[index] = isAux;

+  }

+  */

+

+  void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);

+};

+

 class COutArchive

 {

   UInt64 _prefixHeaderPos;

 

-  HRESULT WriteDirect(const void *data, UInt32 size);

+  HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }

   

   UInt64 GetPos() const;

   void WriteBytes(const void *data, size_t size);

-  void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); }

+  void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }

   void WriteByte(Byte b);

   void WriteUInt32(UInt32 value);

   void WriteUInt64(UInt64 value);

@@ -75,36 +240,36 @@
   void WriteFolder(const CFolder &folder);

   HRESULT WriteFileHeader(const CFileItem &itemInfo);

   void WriteBoolVector(const CBoolVector &boolVector);

-  void WriteHashDigests(

-      const CRecordVector<bool> &digestsDefined,

-      const CRecordVector<UInt32> &hashDigests);

+  void WritePropBoolVector(Byte id, const CBoolVector &boolVector);

+

+  void WriteHashDigests(const CUInt32DefVector &digests);

 

   void WritePackInfo(

       UInt64 dataOffset,

       const CRecordVector<UInt64> &packSizes,

-      const CRecordVector<bool> &packCRCsDefined,

-      const CRecordVector<UInt32> &packCRCs);

+      const CUInt32DefVector &packCRCs);

 

-  void WriteUnpackInfo(const CObjectVector<CFolder> &folders);

+  void WriteUnpackInfo(

+      const CObjectVector<CFolder> &folders,

+      const COutFolders &outFolders);

 

   void WriteSubStreamsInfo(

       const CObjectVector<CFolder> &folders,

-      const CRecordVector<CNum> &numUnpackStreamsInFolders,

+      const COutFolders &outFolders,

       const CRecordVector<UInt64> &unpackSizes,

-      const CRecordVector<bool> &digestsDefined,

-      const CRecordVector<UInt32> &hashDigests);

+      const CUInt32DefVector &digests);

 

   void SkipAlign(unsigned pos, unsigned alignSize);

-  void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize);

+  void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize);

   void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);

 

   HRESULT EncodeStream(

       DECL_EXTERNAL_CODECS_LOC_VARS

       CEncoder &encoder, const CByteBuffer &data,

-      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);

+      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);

   void WriteHeader(

-      const CArchiveDatabase &db,

-      const CHeaderOptions &headerOptions,

+      const CArchiveDatabaseOut &db,

+      // const CHeaderOptions &headerOptions,

       UInt64 &headerOffset);

   

   bool _countMode;

@@ -118,6 +283,8 @@
   bool _endMarker;

   #endif

 

+  bool _useAlign;

+

   HRESULT WriteSignature();

   #ifdef _7Z_VOL

   HRESULT WriteFinishSignature();

@@ -136,7 +303,7 @@
   HRESULT SkipPrefixArchiveHeader();

   HRESULT WriteDatabase(

       DECL_EXTERNAL_CODECS_LOC_VARS

-      const CArchiveDatabase &db,

+      const CArchiveDatabaseOut &db,

       const CCompressionMethodMode *options,

       const CHeaderOptions &headerOptions);

 

diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
old mode 100755
new mode 100644
index 432da23..345c61b
--- a/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -17,7 +17,7 @@
   STATPROPSTG StatPROPSTG;

 };

 

-CPropMap kPropMap[] =

+static const CPropMap kPropMap[] =

 {

   { NID::kName, { NULL, kpidPath, VT_BSTR } },

   { NID::kSize, { NULL, kpidSize, VT_UI8 } },

@@ -34,11 +34,12 @@
   { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },

   { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },

   { NID::kATime, { NULL, kpidATime, VT_FILETIME } },

-  { NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },

+  { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },

   { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },

 

   { NID::kCRC, { NULL, kpidCRC, VT_UI4 } },

   

+//  { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } },

   { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }

 

   #ifndef _SFX

@@ -49,11 +50,9 @@
   #endif

 };

 

-static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);

-

 static int FindPropInMap(UInt64 filePropID)

 {

-  for (int i = 0; i < kPropMapSize; i++)

+  for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)

     if (kPropMap[i].FilePropID == filePropID)

       return i;

   return -1;

@@ -62,7 +61,7 @@
 static void CopyOneItem(CRecordVector<UInt64> &src,

     CRecordVector<UInt64> &dest, UInt32 item)

 {

-  for (int i = 0; i < src.Size(); i++)

+  FOR_VECTOR (i, src)

     if (src[i] == item)

     {

       dest.Add(item);

@@ -73,7 +72,7 @@
 

 static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)

 {

-  for (int i = 0; i < src.Size(); i++)

+  FOR_VECTOR (i, src)

     if (src[i] == item)

     {

       src.Delete(i);

@@ -83,7 +82,7 @@
 

 static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)

 {

-  for (int i = 0; i < dest.Size(); i++)

+  FOR_VECTOR (i, dest)

     if (dest[i] == item)

     {

       dest.Delete(i);

@@ -92,6 +91,8 @@
   dest.Insert(0, item);

 }

 

+#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);

+

 void CHandler::FillPopIDs()

 {

   _fileInfoPopIDs.Clear();

@@ -103,21 +104,26 @@
   const CArchiveDatabaseEx &_db = volume.Database;

   #endif

 

-  CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs;

+  CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;

 

   RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);

   RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);

+  /*

+  RemoveOneItem(fileInfoPopIDs, NID::kParent);

+  RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);

+  */

 

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);

-  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);

+  COPY_ONE_ITEM(kName);

+  COPY_ONE_ITEM(kAnti);

+  COPY_ONE_ITEM(kSize);

+  COPY_ONE_ITEM(kPackInfo);

+  COPY_ONE_ITEM(kCTime);

+  COPY_ONE_ITEM(kMTime);

+  COPY_ONE_ITEM(kATime);

+  COPY_ONE_ITEM(kWinAttrib);

+  COPY_ONE_ITEM(kCRC);

+  COPY_ONE_ITEM(kComment);

+

   _fileInfoPopIDs += fileInfoPopIDs;

  

   #ifndef _SFX

@@ -141,9 +147,9 @@
   #endif

 }

 

-STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)

+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)

 {

-  *numProperties = _fileInfoPopIDs.Size();

+  *numProps = _fileInfoPopIDs.Size();

   return S_OK;

 }

 

diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
old mode 100755
new mode 100644
index ac3d133..ae4e890
--- a/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -5,14 +5,21 @@
 #include "../../Common/RegisterArc.h"

 

 #include "7zHandler.h"

-static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; }

-#ifndef EXTRACT_ONLY

-static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }

-#else

-#define CreateArcOut 0

-#endif

+

+namespace NArchive {

+namespace N7z {

+

+IMP_CreateArcIn

+IMP_CreateArcOut

 

 static CArcInfo g_ArcInfo =

-  { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };

+  { "7z", "7z", 0, 7,

+  6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},

+  0,

+  NArcInfoFlags::kFindSignature,

+  REF_CreateArc_Pair };

 

-REGISTER_ARC(7z)

+REGISTER_ARC_DEC_SIG(7z)

+// REGISTER_ARC(7z)

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp
old mode 100755
new mode 100644
index 58f2ec4..e9671a8
--- a/CPP/7zip/Archive/7z/7zSpecStream.cpp
+++ b/CPP/7zip/Archive/7z/7zSpecStream.cpp
@@ -9,16 +9,14 @@
   UInt32 realProcessedSize;

   HRESULT result = _stream->Read(data, size, &realProcessedSize);

   _size += realProcessedSize;

-  if (processedSize != 0)

+  if (processedSize)

     *processedSize = realProcessedSize;

   return result;

 }

 

-STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(

-    UInt64 subStream, UInt64 *value)

+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)

 {

-  if (_getSubStreamSize == NULL)

+  if (!_getSubStreamSize)

     return E_NOTIMPL;

-  return  _getSubStreamSize->GetSubStreamSize(subStream, value);

+  return _getSubStreamSize->GetSubStreamSize(subStream, value);

 }

-

diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
old mode 100755
new mode 100644
index 4b4db06..87f3e0d
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -4,10 +4,11 @@
 

 #include "../../../../C/CpuArch.h"

 

-#include "../../Common/LimitedStreams.h"

-#include "../../Common/ProgressUtils.h"

+#include "../../../Common/Wildcard.h"

 

 #include "../../Common/CreateCoder.h"

+#include "../../Common/LimitedStreams.h"

+#include "../../Common/ProgressUtils.h"

 

 #include "../../Compress/CopyCoder.h"

 

@@ -24,15 +25,6 @@
 namespace NArchive {

 namespace N7z {

 

-static const UInt64 k_LZMA = 0x030101;

-static const UInt64 k_BCJ  = 0x03030103;

-static const UInt64 k_BCJ2 = 0x0303011B;

-

-static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";

-static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;

-static const UInt32 kAlgorithmForBCJ2_LZMA = 1;

-static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;

-

 #ifdef MY_CPU_X86_OR_AMD64

 #define USE_86_FILTER

 #endif

@@ -67,19 +59,20 @@
   int slashPos = GetReverseSlashPos(Name);

   int dotPos = Name.ReverseFind(L'.');

   if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))

-    return Name.Length();

+    return Name.Len();

   return dotPos + 1;

 }

 

 UString CUpdateItem::GetExtension() const

 {

-  return Name.Mid(GetExtensionPos());

+  return Name.Ptr(GetExtensionPos());

 }

 

 #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

 

 #define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))

 

+/*

 static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)

 {

   size_t c1 = a1.GetCapacity();

@@ -119,11 +112,12 @@
     RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));

   return 0;

 }

+*/

 

 /*

 static int CompareFiles(const CFileItem &f1, const CFileItem &f2)

 {

-  return MyStringCompareNoCase(f1.Name, f2.Name);

+  return CompareFileNames(f1.Name, f2.Name);

 }

 */

 

@@ -134,15 +128,19 @@
   CNum NumCopyFiles;

 };

 

-static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param)

+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)

 {

   RINOZ_COMP(p1->Group, p2->Group);

   int i1 = p1->FolderIndex;

   int i2 = p2->FolderIndex;

-  const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;

+  /*

+  // 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]));

+  */

   return MyCompare(i1, i2);

   /*

   RINOZ_COMP(

@@ -156,25 +154,31 @@
   */

 }

 

-////////////////////////////////////////////////////////////

+/*

+  we sort empty files and dirs in such order:

+  - Dir.NonAnti   (name sorted)

+  - File.NonAnti  (name sorted)

+  - File.Anti     (name sorted)

+  - Dir.Anti (reverse name sorted)

+*/

 

 static int CompareEmptyItems(const int *p1, const int *p2, void *param)

 {

   const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;

   const CUpdateItem &u1 = updateItems[*p1];

   const CUpdateItem &u2 = updateItems[*p2];

-  if (u1.IsDir != u2.IsDir)

-    return (u1.IsDir) ? 1 : -1;

-  if (u1.IsDir)

-  {

-    if (u1.IsAnti != u2.IsAnti)

-      return (u1.IsAnti ? 1 : -1);

-    int n = MyStringCompareNoCase(u1.Name, u2.Name);

-    return -n;

-  }

+  // NonAnti < Anti

   if (u1.IsAnti != u2.IsAnti)

     return (u1.IsAnti ? 1 : -1);

-  return MyStringCompareNoCase(u1.Name, u2.Name);

+  if (u1.IsDir != u2.IsDir)

+  {

+    // Dir.NonAnti < File < Dir.Anti

+    if (u1.IsDir)

+      return (u1.IsAnti ? 1 : -1);

+    return (u2.IsAnti ? -1 : 1);

+  }

+  int n = CompareFileNames(u1.Name, u2.Name);

+  return (u1.IsDir && u1.IsAnti) ? -n : n;

 }

 

 static const char *g_Exts =

@@ -207,7 +211,7 @@
   " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "

   " pdb pch idb ncb opt";

 

-int GetExtIndex(const char *ext)

+static int GetExtIndex(const char *ext)

 {

   int extIndex = 1;

   const char *p = g_Exts;

@@ -246,7 +250,9 @@
   UInt32 Index;

   UInt32 ExtensionPos;

   UInt32 NamePos;

-  int ExtensionIndex;

+  unsigned ExtensionIndex;

+  

+  CRefItem() {};

   CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):

     UpdateItem(&ui),

     Index(index),

@@ -257,64 +263,134 @@
     if (sortByType)

     {

       int slashPos = GetReverseSlashPos(ui.Name);

-      NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);

+      NamePos = slashPos + 1;

       int dotPos = ui.Name.ReverseFind(L'.');

-      if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))

-        ExtensionPos = ui.Name.Length();

+      if (dotPos < 0 || dotPos < slashPos)

+        ExtensionPos = ui.Name.Len();

       else

       {

         ExtensionPos = dotPos + 1;

-        UString us = ui.Name.Mid(ExtensionPos);

-        if (!us.IsEmpty())

+        if (ExtensionPos != ui.Name.Len())

         {

-          us.MakeLower();

-          int i;

           AString s;

-          for (i = 0; i < us.Length(); i++)

+          for (unsigned pos = ExtensionPos;; pos++)

           {

-            wchar_t c = us[i];

+            wchar_t c = ui.Name[pos];

             if (c >= 0x80)

               break;

-            s += (char)c;

+            if (c == 0)

+            {

+              ExtensionIndex = GetExtIndex(s);

+              break;

+            }

+            s += (char)MyCharLower_Ascii((char)c);

           }

-          if (i == us.Length())

-            ExtensionIndex = GetExtIndex(s);

-          else

-            ExtensionIndex = 0;

         }

       }

     }

   }

 };

 

+struct CSortParam

+{

+  // const CObjectVector<CTreeFolder> *TreeFolders;

+  bool SortByType;

+};

+

+/*

+  we sort files in such order:

+  - Dir.NonAnti   (name sorted)

+  - alt streams

+  - Dirs

+  - Dir.Anti (reverse name sorted)

+*/

+

+

 static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)

 {

   const CRefItem &a1 = *p1;

   const CRefItem &a2 = *p2;

   const CUpdateItem &u1 = *a1.UpdateItem;

   const CUpdateItem &u2 = *a2.UpdateItem;

-  int n;

+

+  /*

+  if (u1.IsAltStream != u2.IsAltStream)

+    return u1.IsAltStream ? 1 : -1;

+  */

+  

+  // Actually there are no dirs that time. They were stored in other steps

+  // So that code is unused?

   if (u1.IsDir != u2.IsDir)

-    return (u1.IsDir) ? 1 : -1;

+    return u1.IsDir ? 1 : -1;

   if (u1.IsDir)

   {

     if (u1.IsAnti != u2.IsAnti)

       return (u1.IsAnti ? 1 : -1);

-    n = MyStringCompareNoCase(u1.Name, u2.Name);

+    int n = CompareFileNames(u1.Name, u2.Name);

     return -n;

   }

-  bool sortByType = *(bool *)param;

+  

+  // bool sortByType = *(bool *)param;

+  const CSortParam *sortParam = (const CSortParam *)param;

+  bool sortByType = sortParam->SortByType;

   if (sortByType)

   {

     RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);

-    RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));

-    RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));

+    RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos)));

+    RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos)));

     if (!u1.MTimeDefined && u2.MTimeDefined) return 1;

     if (u1.MTimeDefined && !u2.MTimeDefined) return -1;

     if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);

     RINOZ_COMP(u1.Size, u2.Size);

   }

-  return MyStringCompareNoCase(u1.Name, u2.Name);

+  /*

+  int par1 = a1.UpdateItem->ParentFolderIndex;

+  int par2 = a2.UpdateItem->ParentFolderIndex;

+  const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1];

+  const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2];

+

+  int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd;

+  int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd;

+  if (b1 < b2)

+  {

+    if (e1 <= b2)

+      return -1;

+    // p2 in p1

+    int par = par2;

+    for (;;)

+    {

+      const CTreeFolder &tf = (*sortParam->TreeFolders)[par];

+      par = tf.Parent;

+      if (par == par1)

+      {

+        RINOZ(CompareFileNames(u1.Name, tf.Name));

+        break;

+      }

+    }

+  }

+  else if (b2 < b1)

+  {

+    if (e2 <= b1)

+      return 1;

+    // p1 in p2

+    int par = par1;

+    for (;;)

+    {

+      const CTreeFolder &tf = (*sortParam->TreeFolders)[par];

+      par = tf.Parent;

+      if (par == par2)

+      {

+        RINOZ(CompareFileNames(tf.Name, u2.Name));

+        break;

+      }

+    }

+  }

+  */

+  // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex);

+  RINOK(CompareFileNames(u1.Name, u2.Name));

+  RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient);

+  RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive);

+  return 0;

 }

 

 struct CSolidGroup

@@ -322,112 +398,95 @@
   CRecordVector<UInt32> Indices;

 };

 

-static wchar_t *g_ExeExts[] =

+static const wchar_t *g_ExeExts[] =

 {

-  L"dll",

-  L"exe",

-  L"ocx",

-  L"sfx",

-  L"sys"

+    L"dll"

+  , L"exe"

+  , L"ocx"

+  , L"sfx"

+  , L"sys"

 };

 

-static bool IsExeExt(const UString &ext)

+static bool IsExeExt(const wchar_t *ext)

 {

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

-    if (ext.CompareNoCase(g_ExeExts[i]) == 0)

+  for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)

+    if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)

       return true;

   return false;

 }

 

-#ifdef USE_86_FILTER

 

-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)

+static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)

 {

-  methodResult.Id = methodID;

-  methodResult.NumInStreams = numInStreams;

-  methodResult.NumOutStreams = 1;

+  m.Id = methodID;

+  m.NumInStreams = numInStreams;

+  m.NumOutStreams = 1;

 }

 

-static void MakeExeMethod(const CCompressionMethodMode &method,

-    bool bcj2Filter, CCompressionMethodMode &exeMethod)

+static void AddBcj2Methods(CCompressionMethodMode &mode)

 {

-  exeMethod = method;

+  CMethodFull m;

+  GetMethodFull(k_LZMA, 1, m);

+  

+  m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);

+  m.AddProp32(NCoderPropID::kNumFastBytes, 128);

+  m.AddProp32(NCoderPropID::kNumThreads, 1);

+  m.AddProp32(NCoderPropID::kLitPosBits, 2);

+  m.AddProp32(NCoderPropID::kLitContextBits, 0);

+  // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");

+

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

+}

+

+static void MakeExeMethod(CCompressionMethodMode &mode,

+    bool useFilters, bool addFilter, bool bcj2Filter)

+{

+  if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)

+    return;

+  if (mode.Methods.Size() == 2)

+  {

+    if (mode.Methods[0].Id == k_BCJ2)

+      AddBcj2Methods(mode);

+    return;

+  }

+  if (!addFilter)

+    return;

+  bcj2Filter = bcj2Filter;

+  #ifdef USE_86_FILTER

   if (bcj2Filter)

   {

-    CMethodFull methodFull;

-    GetMethodFull(k_BCJ2, 4, methodFull);

-    exeMethod.Methods.Insert(0, methodFull);

-    GetMethodFull(k_LZMA, 1, methodFull);

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kAlgorithm;

-      prop.Value = kAlgorithmForBCJ2_LZMA;

-      methodFull.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kMatchFinder;

-      prop.Value = kMatchFinderForBCJ2_LZMA;

-      methodFull.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kDictionarySize;

-      prop.Value = kDictionaryForBCJ2_LZMA;

-      methodFull.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kNumFastBytes;

-      prop.Value = kNumFastBytesForBCJ2_LZMA;

-      methodFull.Props.Add(prop);

-    }

-    {

-      CProp prop;

-      prop.Id = NCoderPropID::kNumThreads;

-      prop.Value = (UInt32)1;

-      methodFull.Props.Add(prop);

-    }

-

-    exeMethod.Methods.Add(methodFull);

-    exeMethod.Methods.Add(methodFull);

-    CBind bind;

-

-    bind.OutCoder = 0;

-    bind.InStream = 0;

-

-    bind.InCoder = 1;

-    bind.OutStream = 0;

-    exeMethod.Binds.Add(bind);

-

-    bind.InCoder = 2;

-    bind.OutStream = 1;

-    exeMethod.Binds.Add(bind);

-

-    bind.InCoder = 3;

-    bind.OutStream = 2;

-    exeMethod.Binds.Add(bind);

+    CMethodFull m;

+    GetMethodFull(k_BCJ2, 4, m);

+    mode.Methods.Insert(0, m);

+    AddBcj2Methods(mode);

   }

   else

   {

-    CMethodFull methodFull;

-    GetMethodFull(k_BCJ, 1, methodFull);

-    exeMethod.Methods.Insert(0, methodFull);

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

-    exeMethod.Binds.Add(bind);

+    mode.Binds.Add(bind);

   }

+  #endif

 }

 

-#endif

 

 static void FromUpdateItemToFileItem(const CUpdateItem &ui,

     CFileItem &file, CFileItem2 &file2)

 {

-  file.Name = NItemName::MakeLegalName(ui.Name);

   if (ui.AttribDefined)

     file.SetAttrib(ui.Attrib);

   

@@ -435,11 +494,13 @@
   file2.ATime = ui.ATime;  file2.ATimeDefined = ui.ATimeDefined;

   file2.MTime = ui.MTime;  file2.MTimeDefined = ui.MTimeDefined;

   file2.IsAnti = ui.IsAnti;

+  // file2.IsAux = false;

   file2.StartPosDefined = false;

 

   file.Size = ui.Size;

   file.IsDir = ui.IsDir;

   file.HasStream = ui.HasStream();

+  // file.IsAltStream = ui.IsAltStream;

 }

 

 class CFolderOutStream2:

@@ -448,11 +509,11 @@
 {

   COutStreamWithCRC *_crcStreamSpec;

   CMyComPtr<ISequentialOutStream> _crcStream;

-  const CArchiveDatabaseEx *_db;

+  const CDbEx *_db;

   const CBoolVector *_extractStatuses;

   CMyComPtr<ISequentialOutStream> _outStream;

   UInt32 _startIndex;

-  int _currentIndex;

+  unsigned _currentIndex;

   bool _fileIsOpen;

   UInt64 _rem;

 

@@ -469,7 +530,7 @@
     _crcStream = _crcStreamSpec;

   }

 

-  HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex,

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

@@ -477,7 +538,7 @@
   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

-HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex,

+HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,

     const CBoolVector *extractStatuses, ISequentialOutStream *outStream)

 {

   _db = db;

@@ -576,13 +637,13 @@
   CMyComPtr<ISequentialOutStream> Fos;

 

   UInt64 StartPos;

-  const UInt64 *PackSizes;

-  const CFolder *Folder;

+  const CFolders *Folders;

+  int FolderIndex;

   #ifndef _NO_CRYPTO

-  CMyComPtr<ICryptoGetTextPassword> GetTextPassword;

+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;

   #endif

 

-  DECL_EXTERNAL_CODECS_VARS

+  DECL_EXTERNAL_CODECS_LOC_VARS2;

   CDecoder Decoder;

 

   #ifndef _7ZIP_ST

@@ -601,6 +662,7 @@
     Fos = FosSpec;

     Result = E_FAIL;

   }

+  ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }

   virtual void Execute();

 };

 

@@ -609,21 +671,20 @@
   try

   {

     #ifndef _NO_CRYPTO

-    bool passwordIsDefined;

+      bool isEncrypted = false;

+      bool passwordIsDefined = false;

     #endif

+    

     Result = Decoder.Decode(

-      EXTERNAL_CODECS_VARS

+      EXTERNAL_CODECS_LOC_VARS

       InStream,

       StartPos,

-      PackSizes,

-      *Folder,

+      *Folders, FolderIndex,

       Fos,

       NULL

-      #ifndef _NO_CRYPTO

-      , GetTextPassword, passwordIsDefined

-      #endif

+      _7Z_DECODER_CRYPRO_VARS

       #ifndef _7ZIP_ST

-      , MtMode, NumThreads

+        , MtMode, NumThreads

       #endif

       );

   }

@@ -638,7 +699,7 @@
 

 bool static Is86FilteredFolder(const CFolder &f)

 {

-  for (int i = 0; i < f.Coders.Size(); i++)

+  FOR_VECTOR(i, f.Coders)

   {

     CMethodId m = f.Coders[i].MethodID;

     if (m == k_BCJ || m == k_BCJ2)

@@ -669,20 +730,31 @@
 

 static const int kNumGroupsMax = 4;

 

-#ifdef USE_86_FILTER

 static bool Is86Group(int group) { return (group & 1) != 0; }

-#endif

 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)

+{

+  file = inDb.Files[index];

+  file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);

+  file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);

+  file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);

+  file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);

+  file2.IsAnti = inDb.IsItemAnti(index);

+  // file2.IsAux = inDb.IsItemAux(index);

+}

+

 HRESULT Update(

     DECL_EXTERNAL_CODECS_LOC_VARS

     IInStream *inStream,

-    const CArchiveDatabaseEx *db,

+    const CDbEx *db,

     const CObjectVector<CUpdateItem> &updateItems,

+    // const CObjectVector<CTreeFolder> &treeFolders,

+    // const CUniqBlocks &secureBlocks,

     COutArchive &archive,

-    CArchiveDatabase &newDatabase,

+    CArchiveDatabaseOut &newDatabase,

     ISequentialOutStream *seqOutStream,

     IArchiveUpdateCallback *updateCallback,

     const CUpdateOptions &options

@@ -694,6 +766,9 @@
   UInt64 numSolidFiles = options.NumSolidFiles;

   if (numSolidFiles == 0)

     numSolidFiles = 1;

+

+  // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();

+

   /*

   CMyComPtr<IOutStream> outStream;

   RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));

@@ -701,23 +776,23 @@
     return E_NOTIMPL;

   */

 

-  UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0;

+  UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0;

   if (startBlockSize > 0 && !options.RemoveSfxBlock)

   {

     RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));

   }

 

-  CRecordVector<int> fileIndexToUpdateIndexMap;

+  CIntArr fileIndexToUpdateIndexMap;

   CRecordVector<CFolderRepack> folderRefs;

   UInt64 complexity = 0;

   UInt64 inSizeForReduce2 = 0;

   bool needEncryptedRepack = false;

   if (db != 0)

   {

-    fileIndexToUpdateIndexMap.Reserve(db->Files.Size());

-    int i;

+    fileIndexToUpdateIndexMap.Alloc(db->Files.Size());

+    unsigned i;

     for (i = 0; i < db->Files.Size(); i++)

-      fileIndexToUpdateIndexMap.Add(-1);

+      fileIndexToUpdateIndexMap[i] = -1;

 

     for (i = 0; i < updateItems.Size(); i++)

     {

@@ -726,7 +801,7 @@
         fileIndexToUpdateIndexMap[index] = i;

     }

 

-    for (i = 0; i < db->Folders.Size(); i++)

+    for (i = 0; i < (int)db->NumFolders; i++)

     {

       CNum indexInFolder = 0;

       CNum numCopyItems = 0;

@@ -753,7 +828,8 @@
       CFolderRepack rep;

       rep.FolderIndex = i;

       rep.NumCopyFiles = numCopyItems;

-      const CFolder &f = db->Folders[i];

+      CFolder f;

+      db->ParseFolderInfo(i, f);

       bool isEncrypted = f.IsEncrypted();

       rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));

       folderRefs.Add(rep);

@@ -772,7 +848,7 @@
   }

 

   UInt64 inSizeForReduce = 0;

-  int i;

+  unsigned i;

   for (i = 0; i < updateItems.Size(); i++)

   {

     const CUpdateItem &ui = updateItems[i];

@@ -789,32 +865,30 @@
   if (inSizeForReduce2 > inSizeForReduce)

     inSizeForReduce = inSizeForReduce2;

 

-  const UInt32 kMinReduceSize = (1 << 16);

-  if (inSizeForReduce < kMinReduceSize)

-    inSizeForReduce = kMinReduceSize;

-

   RINOK(updateCallback->SetTotal(complexity));

 

   CLocalProgress *lps = new CLocalProgress;

   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(updateCallback, true);

 

+  CStreamBinder sb;

+  RINOK(sb.CreateEvents());

+

   CThreadDecoder threadDecoder;

   if (!folderRefs.IsEmpty())

   {

     #ifdef EXTERNAL_CODECS

-    threadDecoder._codecsInfo = codecsInfo;

-    threadDecoder._externalCodecs = *externalCodecs;

+    threadDecoder.__externalCodecs = __externalCodecs;

     #endif

     RINOK(threadDecoder.Create());

   }

 

   CObjectVector<CSolidGroup> groups;

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

-    groups.Add(CSolidGroup());

+    groups.AddNew();

 

   {

-    // ---------- Split files to 2 groups ----------

+    // ---------- Split files to groups ----------

 

     bool useFilters = options.UseFilters;

     const CCompressionMethodMode &method = *options.Method;

@@ -830,7 +904,7 @@
       {

         int dotPos = ui.Name.ReverseFind(L'.');

         if (dotPos >= 0)

-          filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1));

+          filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));

       }

       groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);

     }

@@ -842,7 +916,7 @@
   if (needEncryptedRepack)

   {

     getPasswordSpec = new CCryptoGetTextPassword;

-    threadDecoder.GetTextPassword = getPasswordSpec;

+    threadDecoder.getTextPassword = getPasswordSpec;

 

     if (options.Method->PasswordIsDefined)

       getPasswordSpec->Password = options.Method->Password;

@@ -852,31 +926,119 @@
         return E_NOTIMPL;

       CMyComBSTR password;

       RINOK(getDecoderPassword->CryptoGetTextPassword(&password));

-      getPasswordSpec->Password = password;

+      if ((BSTR)password)

+        getPasswordSpec->Password = password;

     }

   }

 

   #endif

 

+  

   // ---------- Compress ----------

 

   RINOK(archive.Create(seqOutStream, false));

   RINOK(archive.SkipPrefixArchiveHeader());

 

-  int folderRefIndex = 0;

+  /*

+  CIntVector treeFolderToArcIndex;

+  treeFolderToArcIndex.Reserve(treeFolders.Size());

+  for (i = 0; i < treeFolders.Size(); i++)

+    treeFolderToArcIndex.Add(-1);

+  // ---------- Write Tree (only AUX dirs) ----------

+  for (i = 1; i < treeFolders.Size(); i++)

+  {

+    const CTreeFolder &treeFolder = treeFolders[i];

+    CFileItem file;

+    CFileItem2 file2;

+    file2.Init();

+    int secureID = 0;

+    if (treeFolder.UpdateItemIndex < 0)

+    {

+      // we can store virtual dir item wuthout attrib, but we want all items have attrib.

+      file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY);

+      file2.IsAux = true;

+    }

+    else

+    {

+      const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex];

+      // if item is not dir, then it's parent for alt streams.

+      // we will write such items later

+      if (!ui.IsDir)

+        continue;

+      secureID = ui.SecureIndex;

+      if (ui.NewProps)

+        FromUpdateItemToFileItem(ui, file, file2);

+      else

+        GetFile(*db, ui.IndexInArchive, file, file2);

+    }

+    file.Size = 0;

+    file.HasStream = false;

+    file.IsDir = true;

+    file.Parent = treeFolder.Parent;

+    

+    treeFolderToArcIndex[i] = newDatabase.Files.Size();

+    newDatabase.AddFile(file, file2, treeFolder.Name);

+    

+    if (totalSecureDataSize != 0)

+      newDatabase.SecureIDs.Add(secureID);

+  }

+  */

+

+  {

+    /* ---------- Write non-AUX dirs and Empty files ---------- */

+    CRecordVector<int> emptyRefs;

+    for (i = 0; i < updateItems.Size(); i++)

+    {

+      const CUpdateItem &ui = updateItems[i];

+      if (ui.NewData)

+      {

+        if (ui.HasStream())

+          continue;

+      }

+      else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)

+        continue;

+      /*

+      if (ui.TreeFolderIndex >= 0)

+        continue;

+      */

+      emptyRefs.Add(i);

+    }

+    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);

+    for (i = 0; i < emptyRefs.Size(); i++)

+    {

+      const CUpdateItem &ui = updateItems[emptyRefs[i]];

+      CFileItem file;

+      CFileItem2 file2;

+      UString name;

+      if (ui.NewProps)

+      {

+        FromUpdateItemToFileItem(ui, file, file2);

+        name = ui.Name;

+      }

+      else

+      {

+        GetFile(*db, ui.IndexInArchive, file, file2);

+        db->GetPath(ui.IndexInArchive, name);

+      }

+      

+      /*

+      if (totalSecureDataSize != 0)

+        newDatabase.SecureIDs.Add(ui.SecureIndex);

+      file.Parent = ui.ParentFolderIndex;

+      */

+      newDatabase.AddFile(file, file2, name);

+    }

+  }

+

+  unsigned folderRefIndex = 0;

   lps->ProgressOffset = 0;

 

   for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)

   {

     const CSolidGroup &group = groups[groupIndex];

 

-    CCompressionMethodMode method;

-    #ifdef USE_86_FILTER

-    if (Is86Group(groupIndex))

-      MakeExeMethod(*options.Method, options.MaxFilter, method);

-    else

-    #endif

-      method = *options.Method;

+    CCompressionMethodMode method = *options.Method;

+    MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);

 

     if (IsEncryptedGroup(groupIndex))

     {

@@ -911,23 +1073,23 @@
           db->GetFolderStreamPos(folderIndex, 0), packSize, progress));

         lps->ProgressOffset += packSize;

         

-        const CFolder &folder = db->Folders[folderIndex];

-        CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];

-        for (int j = 0; j < folder.PackStreams.Size(); j++)

+        CFolder &folder = newDatabase.Folders.AddNew();

+        db->ParseFolderInfo(folderIndex, folder);

+        CNum startIndex = db->FoStartPackStreamIndex[folderIndex];

+        for (unsigned j = 0; j < folder.PackStreams.Size(); j++)

         {

-          newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);

+          newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));

           // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);

           // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);

         }

-        newDatabase.Folders.Add(folder);

+

+        UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];

+        UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];

+        for (; indexStart < indexEnd; indexStart++)

+          newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);

       }

       else

       {

-        CStreamBinder sb;

-        RINOK(sb.CreateEvents());

-        CMyComPtr<ISequentialOutStream> sbOutStream;

-        CMyComPtr<ISequentialInStream> sbInStream;

-        sb.CreateStreams(&sbInStream, &sbOutStream);

         CBoolVector extractStatuses;

         

         CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

@@ -946,32 +1108,38 @@
           extractStatuses.Add(needExtract);

         }

 

-        RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));

-        sbOutStream.Release();

-        

-        threadDecoder.InStream = inStream;

-        threadDecoder.Folder = &db->Folders[folderIndex];

-        threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);

-        threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];

-        

-        threadDecoder.Start();

-        

-        int startPackIndex = newDatabase.PackSizes.Size();

-        CFolder newFolder;

-        RINOK(encoder.Encode(

-          EXTERNAL_CODECS_LOC_VARS

-          sbInStream, NULL, &inSizeForReduce, newFolder,

-          archive.SeqStream, newDatabase.PackSizes, progress));

-        

-        threadDecoder.WaitFinish();

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

 

         for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

           lps->OutSize += newDatabase.PackSizes[startPackIndex];

-        lps->InSize += newFolder.GetUnpackSize();

-        

-        newDatabase.Folders.Add(newFolder);

+        lps->InSize += curUnpackSize;

       }

       

       newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);

@@ -983,7 +1151,9 @@
       {

         CFileItem file;

         CFileItem2 file2;

-        db->GetFile(fi, file, file2);

+        GetFile(*db, fi, file, file2);

+        UString name;

+        db->GetPath(fi, name);

         if (file.HasStream)

         {

           indexInFolder++;

@@ -1002,30 +1172,40 @@
               uf.CrcDefined = file.CrcDefined;

               uf.HasStream = file.HasStream;

               file = uf;

+              name = ui.Name;

             }

-            newDatabase.AddFile(file, file2);

+            /*

+            file.Parent = ui.ParentFolderIndex;

+            if (ui.TreeFolderIndex >= 0)

+              treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();

+            if (totalSecureDataSize != 0)

+              newDatabase.SecureIDs.Add(ui.SecureIndex);

+            */

+            newDatabase.AddFile(file, file2, name);

           }

         }

       }

     }

 

-    int numFiles = group.Indices.Size();

+    unsigned numFiles = group.Indices.Size();

     if (numFiles == 0)

       continue;

     CRecordVector<CRefItem> refItems;

-    refItems.Reserve(numFiles);

+    refItems.ClearAndSetSize(numFiles);

     bool sortByType = (numSolidFiles > 1);

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

-      refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));

-    refItems.Sort(CompareUpdateItems, (void *)&sortByType);

+      refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);

+    CSortParam sortParam;

+    // sortParam.TreeFolders = &treeFolders;

+    sortParam.SortByType = sortByType;

+    refItems.Sort(CompareUpdateItems, (void *)&sortParam);

     

-    CRecordVector<UInt32> indices;

-    indices.Reserve(numFiles);

+    CObjArray<UInt32> indices(numFiles);

 

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

     {

       UInt32 index = refItems[i].Index;

-      indices.Add(index);

+      indices[i] = index;

       /*

       const CUpdateItem &ui = updateItems[index];

       CFileItem file;

@@ -1057,7 +1237,7 @@
           if (numSubFiles == 0)

             prevExtension = ext;

           else

-            if (ext.CompareNoCase(prevExtension) != 0)

+            if (!ext.IsEqualToNoCase(prevExtension))

               break;

         }

       }

@@ -1068,34 +1248,39 @@
       CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);

       inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);

       

-      CFolder folderItem;

-

-      int startPackIndex = newDatabase.PackSizes.Size();

+      unsigned startPackIndex = newDatabase.PackSizes.Size();

+      UInt64 curFolderUnpackSize;

       RINOK(encoder.Encode(

           EXTERNAL_CODECS_LOC_VARS

-          solidInStream, NULL, &inSizeForReduce, folderItem,

+          solidInStream, NULL, &inSizeForReduce,

+          newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,

           archive.SeqStream, newDatabase.PackSizes, progress));

 

       for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

         lps->OutSize += newDatabase.PackSizes[startPackIndex];

 

-      lps->InSize += folderItem.GetUnpackSize();

+      lps->InSize += curFolderUnpackSize;

       // for ()

       // newDatabase.PackCRCsDefined.Add(false);

       // newDatabase.PackCRCs.Add(0);

       

-      newDatabase.Folders.Add(folderItem);

-      

       CNum numUnpackStreams = 0;

       for (int subIndex = 0; subIndex < numSubFiles; subIndex++)

       {

         const CUpdateItem &ui = updateItems[indices[i + subIndex]];

         CFileItem file;

         CFileItem2 file2;

+        UString name;

         if (ui.NewProps)

+        {

           FromUpdateItemToFileItem(ui, file, file2);

+          name = ui.Name;

+        }

         else

-          db->GetFile(ui.IndexInArchive, file, file2);

+        {

+          GetFile(*db, ui.IndexInArchive, file, file2);

+          db->GetPath(ui.IndexInArchive, name);

+        }

         if (file2.IsAnti || file.IsDir)

           return E_FAIL;

         

@@ -1122,7 +1307,14 @@
           file.CrcDefined = false;

           file.HasStream = false;

         }

-        newDatabase.AddFile(file, file2);

+        /*

+        file.Parent = ui.ParentFolderIndex;

+        if (ui.TreeFolderIndex >= 0)

+          treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();

+        if (totalSecureDataSize != 0)

+          newDatabase.SecureIDs.Add(ui.SecureIndex);

+        */

+        newDatabase.AddFile(file, file2, name);

       }

       // numUnpackStreams = 0 is very bad case for locked files

       // v3.13 doesn't understand it.

@@ -1134,42 +1326,36 @@
   if (folderRefIndex != folderRefs.Size())

     return E_FAIL;

 

+  RINOK(lps->SetCur());

+

   /*

   folderRefs.ClearAndFree();

   fileIndexToUpdateIndexMap.ClearAndFree();

   groups.ClearAndFree();

   */

 

+  /*

+  for (i = 0; i < newDatabase.Files.Size(); i++)

   {

-    // ---------- Write Folders & Empty Files ----------

-    

-    CRecordVector<int> emptyRefs;

-    for (i = 0; i < updateItems.Size(); i++)

+    CFileItem &file = newDatabase.Files[i];

+    file.Parent = treeFolderToArcIndex[file.Parent];

+  }

+

+  if (totalSecureDataSize != 0)

+  {

+    newDatabase.SecureBuf.SetCapacity(totalSecureDataSize);

+    size_t pos = 0;

+    newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size());

+    for (i = 0; i < secureBlocks.Sorted.Size(); i++)

     {

-      const CUpdateItem &ui = updateItems[i];

-      if (ui.NewData)

-      {

-        if (ui.HasStream())

-          continue;

-      }

-      else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)

-        continue;

-      emptyRefs.Add(i);

-    }

-    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);

-    for (i = 0; i < emptyRefs.Size(); i++)

-    {

-      const CUpdateItem &ui = updateItems[emptyRefs[i]];

-      CFileItem file;

-      CFileItem2 file2;

-      if (ui.NewProps)

-        FromUpdateItemToFileItem(ui, file, file2);

-      else

-        db->GetFile(ui.IndexInArchive, file, file2);

-      newDatabase.AddFile(file, file2);

+      const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];

+      size_t size = buf.GetCapacity();

+      memcpy(newDatabase.SecureBuf + pos, buf, size);

+      newDatabase.SecureSizes.Add((UInt32)size);

+      pos += size;

     }

   }

-    

+  */

   newDatabase.ReserveDown();

   return S_OK;

 }

diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
old mode 100755
new mode 100644
index f3dc885..070bc30
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -3,15 +3,31 @@
 #ifndef __7Z_UPDATE_H

 #define __7Z_UPDATE_H

 

+#include "../IArchive.h"

+

+// #include "../../Common/UniqBlocks.h"

+

 #include "7zCompressionMode.h"

 #include "7zIn.h"

 #include "7zOut.h"

 

-#include "../IArchive.h"

-

 namespace NArchive {

 namespace N7z {

 

+/*

+struct CTreeFolder

+{

+  UString Name;

+  int Parent;

+  CIntVector SubFolders;

+  int UpdateItemIndex;

+  int SortIndex;

+  int SortIndexEnd;

+

+  CTreeFolder(): UpdateItemIndex(-1) {}

+};

+*/

+

 struct CUpdateItem

 {

   int IndexInArchive;

@@ -23,6 +39,15 @@
 

   UInt64 Size;

   UString Name;

+  /*

+  bool IsAltStream;

+  int ParentFolderIndex;

+  int TreeFolderIndex;

+  */

+

+  // that code is not used in 9.26

+  // int ParentSortIndex;

+  // int ParentSortIndexEnd;

 

   UInt32 Attrib;

   

@@ -37,15 +62,20 @@
   bool ATimeDefined;

   bool MTimeDefined;

 

+  // int SecureIndex; // 0 means (no_security)

+

   bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }

 

   CUpdateItem():

+      // ParentSortIndex(-1),

+      // IsAltStream(false),

       IsAnti(false),

       IsDir(false),

       AttribDefined(false),

       CTimeDefined(false),

       ATimeDefined(false),

       MTimeDefined(false)

+      // SecureIndex(0)

       {}

   void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };

 

@@ -72,10 +102,12 @@
 HRESULT Update(

     DECL_EXTERNAL_CODECS_LOC_VARS

     IInStream *inStream,

-    const CArchiveDatabaseEx *db,

+    const CDbEx *db,

     const CObjectVector<CUpdateItem> &updateItems,

+    // const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root

+    // const CUniqBlocks &secureBlocks,

     COutArchive &archive,

-    CArchiveDatabase &newDatabase,

+    CArchiveDatabaseOut &newDatabase,

     ISequentialOutStream *seqOutStream,

     IArchiveUpdateCallback *updateCallback,

     const CUpdateOptions &options

diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/Archive/7z/StdAfx.h
+++ b/CPP/7zip/Archive/7z/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
old mode 100755
new mode 100644
index 190fbd8..09bd9b9
--- a/CPP/7zip/Archive/Archive2.def
+++ b/CPP/7zip/Archive/Archive2.def
@@ -3,7 +3,9 @@
   GetHandlerProperty PRIVATE

   GetNumberOfFormats PRIVATE

   GetHandlerProperty2 PRIVATE

-  CreateObject PRIVATE

   GetNumberOfMethods PRIVATE

   GetMethodProperty PRIVATE

+  GetHashers 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
old mode 100755
new mode 100644
index 5d6cf92..1295331
--- a/CPP/7zip/Archive/ArchiveExports.cpp
+++ b/CPP/7zip/Archive/ArchiveExports.cpp
@@ -2,24 +2,28 @@
 

 #include "StdAfx.h"

 

+#include "../../../C/7zVersion.h"

+

 #include "../../Common/ComTry.h"

 

 #include "../../Windows/PropVariant.h"

 

 #include "../Common/RegisterArc.h"

 

-static const unsigned int kNumArcsMax = 48;

-static unsigned int g_NumArcs = 0;

-static unsigned int g_DefaultArcIndex = 0;

+static const unsigned kNumArcsMax = 64;

+static unsigned g_NumArcs = 0;

+static unsigned g_DefaultArcIndex = 0;

 static const CArcInfo *g_Arcs[kNumArcsMax];

-void RegisterArc(const CArcInfo *arcInfo)

+

+void RegisterArc(const CArcInfo *arcInfo) throw()

 {

   if (g_NumArcs < kNumArcsMax)

   {

-    const wchar_t *p = arcInfo->Name;

+    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_Arcs[g_NumArcs] = arcInfo;

+    g_NumArcs++;

   }

 }

 

@@ -28,7 +32,7 @@
 

 #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])

 

-static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)

+static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)

 {

   if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)

     value->vt = VT_BSTR;

@@ -86,37 +90,38 @@
 STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)

 {

   COM_TRY_BEGIN

+  NWindows::NCOM::PropVariant_Clear(value);

   if (formatIndex >= g_NumArcs)

     return E_INVALIDARG;

   const CArcInfo &arc = *g_Arcs[formatIndex];

   NWindows::NCOM::CPropVariant prop;

-  switch(propID)

+  switch (propID)

   {

-    case NArchive::kName:

-      prop = arc.Name;

-      break;

-    case NArchive::kClassID:

+    case NArchive::NHandlerPropID::kName: prop = arc.Name; break;

+    case NArchive::NHandlerPropID::kClassID:

     {

       GUID clsId = CLSID_CArchiveHandler;

       CLS_ARC_ID_ITEM(clsId) = arc.ClassId;

       return SetPropGUID(clsId, value);

     }

-    case NArchive::kExtension:

-      if (arc.Ext != 0)

-        prop = arc.Ext;

+    case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;

+    case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;

+    case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;

+    case NArchive::NHandlerPropID::kKeepName:   prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;

+    case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;

+    case NArchive::NHandlerPropID::kNtSecure:   prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;

+    case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;

+    case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;

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

       break;

-    case NArchive::kAddExtension:

-      if (arc.AddExt != 0)

-        prop = arc.AddExt;

+    case NArchive::NHandlerPropID::kMultiSignature:

+      if (arc.IsMultiSignature())

+        return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);

       break;

-    case NArchive::kUpdate:

-      prop = (bool)(arc.CreateOutArchive != 0);

-      break;

-    case NArchive::kKeepName:

-      prop = arc.KeepName;

-      break;

-    case NArchive::kStartSignature:

-      return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);

   }

   prop.Detach(value);

   return S_OK;

@@ -133,3 +138,12 @@
   *numFormats = g_NumArcs;

   return S_OK;

 }

+

+STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)

+{

+  *isArc = NULL;

+  if (formatIndex >= g_NumArcs)

+    return E_INVALIDARG;

+  *isArc = g_Arcs[formatIndex]->IsArc;

+  return S_OK;

+}

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
old mode 100755
new mode 100644
index 417e8a7..ed82d98
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -11,16 +11,23 @@
 {

   srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);

 

-  UInt32  j;

+  UInt32 j;

+  _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams);

+  DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams);

+

   for (j = 0; j < NumSrcInStreams; j++)

   {

-    _srcInToDestOutMap.Add(0);

-    DestOutToSrcInMap.Add(0);

+    _srcInToDestOutMap[j] = 0;

+    DestOutToSrcInMap[j] = 0;

   }

+

+  _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams);

+  _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams);

+

   for (j = 0; j < _numSrcOutStreams; j++)

   {

-    _srcOutToDestInMap.Add(0);

-    _destInToSrcOutMap.Add(0);

+    _srcOutToDestInMap[j] = 0;

+    _destInToSrcOutMap[j] = 0;

   }

 

   UInt32 destInOffset = 0;

@@ -53,66 +60,57 @@
 

 void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)

 {

-  destBindInfo.Coders.Clear();

-  destBindInfo.BindPairs.Clear();

-  destBindInfo.InStreams.Clear();

-  destBindInfo.OutStreams.Clear();

+  destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size());

+  destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size());

+  destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size());

+  destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size());

 

-  int i;

-  for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)

+  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.Add(destCoderInfo);

+    destBindInfo.Coders.AddInReserved(destCoderInfo);

   }

-  for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)

+  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.Add(destBindPair);

+    destBindInfo.BindPairs.AddInReserved(destBindPair);

   }

   for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)

-    destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);

+    destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);

   for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)

-    destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);

+    destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);

 }

 

-CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):

-    NumInStreams(numInStreams),

-    NumOutStreams(numOutStreams)

-{

-  InSizes.Reserve(NumInStreams);

-  InSizePointers.Reserve(NumInStreams);

-  OutSizes.Reserve(NumOutStreams);

-  OutSizePointers.Reserve(NumOutStreams);

-}

-

-static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

+void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

     CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)

 {

-  sizes.Clear();

-  sizePointers.Clear();

+  sizes.ClearAndSetSize(numItems);

+  sizePointers.ClearAndSetSize(numItems);

   for(UInt32 i = 0; i < numItems; i++)

   {

-    if (srcSizes == 0 || srcSizes[i] == NULL)

+    if (!srcSizes || !srcSizes[i])

     {

-      sizes.Add(0);

-      sizePointers.Add(NULL);

+      sizes[i] = 0;

+      sizePointers[i] = NULL;

     }

     else

     {

-      sizes.Add(*srcSizes[i]);

-      sizePointers.Add(&sizes.Back());

+      sizes[i] = *(srcSizes[i]);

+      sizePointers[i] = &sizes[i];

     }

   }

 }

 

-void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,

-      const UInt64 **outSizes)

+void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)

 {

   SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

   SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
old mode 100755
new mode 100644
index b1893b2..7618bb2
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -3,9 +3,9 @@
 #ifndef __CODER_MIXER2_H

 #define __CODER_MIXER2_H

 

-#include "../../../Common/MyVector.h"

-#include "../../../Common/Types.h"

 #include "../../../Common/MyCom.h"

+#include "../../../Common/MyVector.h"

+

 #include "../../ICoder.h"

 

 namespace NCoderMixer {

@@ -52,7 +52,7 @@
   {

     numInStreams = 0;

     numOutStreams = 0;

-    for (int i = 0; i < Coders.Size(); i++)

+    FOR_VECTOR (i, Coders)

     {

       const CCoderStreamsInfo &coderStreamsInfo = Coders[i];

       numInStreams += coderStreamsInfo.NumInStreams;

@@ -62,14 +62,14 @@
 

   int FindBinderForInStream(UInt32 inStream) const

   {

-    for (int i = 0; i < BindPairs.Size(); i++)

+    FOR_VECTOR (i, BindPairs)

       if (BindPairs[i].InIndex == inStream)

         return i;

     return -1;

   }

   int FindBinderForOutStream(UInt32 outStream) const

   {

-    for (int i = 0; i < BindPairs.Size(); i++)

+    FOR_VECTOR (i, BindPairs)

       if (BindPairs[i].OutIndex == outStream)

         return i;

     return -1;

@@ -139,6 +139,9 @@
   void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);

 };

 

+void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);

+

 struct CCoderInfo2

 {

   CMyComPtr<ICompressCoder> Coder;

@@ -151,7 +154,9 @@
   CRecordVector<const UInt64 *> InSizePointers;

   CRecordVector<const UInt64 *> OutSizePointers;

 

-  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);

+  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):

+      NumInStreams(numInStreams),

+      NumOutStreams(numOutStreams) {}

   void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

 

   HRESULT QueryInterface(REFGUID iid, void** pp) const

@@ -170,5 +175,5 @@
 };

 

 }

-#endif

 

+#endif

diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
old mode 100755
new mode 100644
index 3047b13..1e9c13e
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -9,30 +9,28 @@
 CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):

     CCoderInfo2(numInStreams, numOutStreams)

 {

-  InStreams.Reserve(NumInStreams);

-  InStreamPointers.Reserve(NumInStreams);

-  OutStreams.Reserve(NumOutStreams);

-  OutStreamPointers.Reserve(NumOutStreams);

+  InStreams.ClearAndReserve(NumInStreams);

+  OutStreams.ClearAndReserve(NumOutStreams);

 }

 

 void CCoder2::Execute() { Code(NULL); }

 

 void CCoder2::Code(ICompressProgressInfo *progress)

 {

-  InStreamPointers.Clear();

-  OutStreamPointers.Clear();

+  InStreamPointers.ClearAndReserve(NumInStreams);

+  OutStreamPointers.ClearAndReserve(NumOutStreams);

   UInt32 i;

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

   {

-    if (InSizePointers[i] != NULL)

+    if (InSizePointers[i])

       InSizePointers[i] = &InSizes[i];

-    InStreamPointers.Add((ISequentialInStream *)InStreams[i]);

+    InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);

   }

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

   {

-    if (OutSizePointers[i] != NULL)

+    if (OutSizePointers[i])

       OutSizePointers[i] = &OutSizes[i];

-    OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);

+    OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);

   }

   if (Coder)

     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],

@@ -41,7 +39,7 @@
     Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,

       &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);

   {

-    int i;

+    unsigned i;

     for (i = 0; i < InStreams.Size(); i++)

       InStreams[i].Release();

     for (i = 0; i < OutStreams.Size(); i++)

@@ -49,32 +47,13 @@
   }

 }

 

-static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

-    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)

-{

-  sizes.Clear();

-  sizePointers.Clear();

-  for (UInt32 i = 0; i < numItems; i++)

-  {

-    if (srcSizes == 0 || srcSizes[i] == NULL)

-    {

-      sizes.Add(0);

-      sizePointers.Add(NULL);

-    }

-    else

-    {

-      sizes.Add(*srcSizes[i]);

-      sizePointers.Add(&sizes.Back());

-    }

-  }

-}

-

-

+/*

 void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)

 {

   SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

   SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

 }

+*/

 

 //////////////////////////////////////

 // CCoderMixer2MT

@@ -83,10 +62,9 @@
 {

   _bindInfo = bindInfo;

   _streamBinders.Clear();

-  for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)

+  FOR_VECTOR (i, _bindInfo.BindPairs)

   {

-    _streamBinders.Add(CStreamBinder());

-    RINOK(_streamBinders.Back().CreateEvents());

+    RINOK(_streamBinders.AddNew().CreateEvents());

   }

   return S_OK;

 }

@@ -113,7 +91,7 @@
 

 void CCoderMixer2MT::ReInit()

 {

-  for (int i = 0; i < _streamBinders.Size(); i++)

+  FOR_VECTOR (i, _streamBinders)

     _streamBinders[i].ReInit();

 }

 

@@ -124,7 +102,7 @@
   if (_coders.Size() != _bindInfo.Coders.Size())

     throw 0;

   */

-  int i;

+  unsigned i;

   for (i = 0; i < _coders.Size(); i++)

   {

     CCoder2 &coderInfo = _coders[i];

@@ -179,7 +157,7 @@
 

 HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)

 {

-  for (int i = 0; i < _coders.Size(); i++)

+  FOR_VECTOR (i, _coders)

     if (_coders[i].Result == code)

       return code;

   return S_OK;

@@ -199,7 +177,7 @@
 

   Init(inStreams, outStreams);

 

-  int i;

+  unsigned i;

   for (i = 0; i < _coders.Size(); i++)

     if (i != _progressCoderIndex)

     {

@@ -214,7 +192,7 @@
 

   for (i = 0; i < _coders.Size(); i++)

     if (i != _progressCoderIndex)

-      _coders[i].WaitFinish();

+      _coders[i].WaitExecuteFinish();

 

   RINOK(ReturnIfError(E_ABORT));

   RINOK(ReturnIfError(E_OUTOFMEMORY));

diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
old mode 100755
new mode 100644
index acecc39..78d0c19
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -12,14 +12,17 @@
 

 struct CCoder2: public CCoderInfo2, public CVirtThread

 {

-  HRESULT Result;

-  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;

-  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;

   CRecordVector<ISequentialInStream*> InStreamPointers;

   CRecordVector<ISequentialOutStream*> OutStreamPointers;

 

+public:

+  HRESULT Result;

+  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;

+  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;

+

   CCoder2(UInt32 numInStreams, UInt32 numOutStreams);

-  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

+  ~CCoder2() { CVirtThread::WaitThreadFinish(); }

+  // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

   virtual void Execute();

   void Code(ICompressProgressInfo *progress);

 };

@@ -47,7 +50,7 @@
 {

   CBindInfo _bindInfo;

   CObjectVector<CStreamBinder> _streamBinders;

-  int _progressCoderIndex;

+  unsigned _progressCoderIndex;

 

   void AddCoderCommon();

   HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);

@@ -67,7 +70,7 @@
   HRESULT SetBindInfo(const CBindInfo &bindInfo);

   void AddCoder(ICompressCoder *coder);

   void AddCoder2(ICompressCoder2 *coder);

-  void SetProgressCoderIndex(int coderIndex) {  _progressCoderIndex = coderIndex; }

+  void SetProgressCoderIndex(unsigned coderIndex) {  _progressCoderIndex = coderIndex; }

 

   void ReInit();

   void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)

diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
old mode 100755
new mode 100644
index 237e01e..c7d45e7
--- a/CPP/7zip/Archive/Common/DummyOutStream.cpp
+++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp
@@ -4,19 +4,14 @@
 

 #include "DummyOutStream.h"

 

-STDMETHODIMP CDummyOutStream::Write(const void *data,  UInt32 size, UInt32 *processedSize)

+STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  UInt32 realProcessedSize;

-  HRESULT result;

-  if(!_stream)

-  {

-    realProcessedSize = size;

-    result = S_OK;

-  }

-  else

-    result = _stream->Write(data, size, &realProcessedSize);

+  UInt32 realProcessedSize = size;

+  HRESULT res = S_OK;

+  if (_stream)

+    res = _stream->Write(data, size, &realProcessedSize);

   _size += realProcessedSize;

-  if(processedSize != NULL)

+  if (processedSize)

     *processedSize = realProcessedSize;

-  return result;

+  return res;

 }

diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h
old mode 100755
new mode 100644
index c993bb3..30e84c5
--- a/CPP/7zip/Archive/Common/DummyOutStream.h
+++ b/CPP/7zip/Archive/Common/DummyOutStream.h
@@ -1,10 +1,11 @@
 // DummyOutStream.h

 

-#ifndef __DUMMYOUTSTREAM_H

-#define __DUMMYOUTSTREAM_H

+#ifndef __DUMMY_OUT_STREAM_H

+#define __DUMMY_OUT_STREAM_H

+

+#include "../../../Common/MyCom.h"

 

 #include "../../IStream.h"

-#include "Common/MyCom.h"

 

 class CDummyOutStream:

   public ISequentialOutStream,

diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
old mode 100755
new mode 100644
index c2254a7..2c920bc
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -2,16 +2,10 @@
 

 #include "StdAfx.h"

 

-#include "../../../Common/StringToInt.h"

-

-#include "../../../Windows/PropVariant.h"

-

 #ifndef _7ZIP_ST

 #include "../../../Windows/System.h"

 #endif

 

-#include "../../ICoder.h"

-

 #include "../Common/ParseProperties.h"

 

 #include "HandlerOut.h"

@@ -20,602 +14,126 @@
 

 namespace NArchive {

 

-static const wchar_t *kCopyMethod = L"Copy";

-static const wchar_t *kLZMAMethodName = L"LZMA";

-static const wchar_t *kLZMA2MethodName = L"LZMA2";

-static const wchar_t *kBZip2MethodName = L"BZip2";

-static const wchar_t *kPpmdMethodName = L"PPMd";

-static const wchar_t *kDeflateMethodName = L"Deflate";

-static const wchar_t *kDeflate64MethodName = L"Deflate64";

-

-static const wchar_t *kLzmaMatchFinderX1 = L"HC4";

-static const wchar_t *kLzmaMatchFinderX5 = L"BT4";

-

-static const UInt32 kLzmaAlgoX1 = 0;

-static const UInt32 kLzmaAlgoX5 = 1;

-

-static const UInt32 kLzmaDicSizeX1 = 1 << 16;

-static const UInt32 kLzmaDicSizeX3 = 1 << 20;

-static const UInt32 kLzmaDicSizeX5 = 1 << 24;

-static const UInt32 kLzmaDicSizeX7 = 1 << 25;

-static const UInt32 kLzmaDicSizeX9 = 1 << 26;

-

-static const UInt32 kLzmaFastBytesX1 = 32;

-static const UInt32 kLzmaFastBytesX7 = 64;

-

-static const UInt32 kPpmdMemSizeX1 = (1 << 22);

-static const UInt32 kPpmdMemSizeX5 = (1 << 24);

-static const UInt32 kPpmdMemSizeX7 = (1 << 26);

-static const UInt32 kPpmdMemSizeX9 = (192 << 20);

-

-static const UInt32 kPpmdOrderX1 = 4;

-static const UInt32 kPpmdOrderX5 = 6;

-static const UInt32 kPpmdOrderX7 = 16;

-static const UInt32 kPpmdOrderX9 = 32;

-

-static const UInt32 kDeflateAlgoX1 = 0;

-static const UInt32 kDeflateAlgoX5 = 1;

-

-static const UInt32 kDeflateFastBytesX1 = 32;

-static const UInt32 kDeflateFastBytesX7 = 64;

-static const UInt32 kDeflateFastBytesX9 = 128;

-

-static const UInt32 kDeflatePassesX1 = 1;

-static const UInt32 kDeflatePassesX7 = 3;

-static const UInt32 kDeflatePassesX9 = 10;

-

-static const UInt32 kBZip2NumPassesX1 = 1;

-static const UInt32 kBZip2NumPassesX7 = 2;

-static const UInt32 kBZip2NumPassesX9 = 7;

-

-static const UInt32 kBZip2DicSizeX1 = 100000;

-static const UInt32 kBZip2DicSizeX3 = 500000;

-static const UInt32 kBZip2DicSizeX5 = 900000;

-

-static const wchar_t *kDefaultMethodName = kLZMAMethodName;

-

-static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";

-static const UInt32 kDictionaryForHeaders = 1 << 20;

-static const UInt32 kNumFastBytesForHeaders = 273;

-static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;

-

-static bool AreEqual(const UString &methodName, const wchar_t *s)

-  { return (methodName.CompareNoCase(s) == 0); }

-

-bool COneMethodInfo::IsLzma() const

+static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)

 {

-  return

-    AreEqual(MethodName, kLZMAMethodName) ||

-    AreEqual(MethodName, kLZMA2MethodName);

+  if (m.FindProp(propID) < 0)

+    m.AddProp32(propID, value);

 }

 

-static inline bool IsBZip2Method(const UString &methodName)

-  { return AreEqual(methodName, kBZip2MethodName); }

-

-static inline bool IsPpmdMethod(const UString &methodName)

-  { return AreEqual(methodName, kPpmdMethodName); }

-

-static inline bool IsDeflateMethod(const UString &methodName)

-{

-  return

-    AreEqual(methodName, kDeflateMethodName) ||

-    AreEqual(methodName, kDeflate64MethodName);

-}

-

-struct CNameToPropID

-{

-  PROPID PropID;

-  VARTYPE VarType;

-  const wchar_t *Name;

-};

-

-static CNameToPropID g_NameToPropID[] =

-{

-  { NCoderPropID::kBlockSize, VT_UI4, L"C" },

-  { NCoderPropID::kDictionarySize, VT_UI4, L"D" },

-  { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },

-

-  { NCoderPropID::kOrder, VT_UI4, L"O" },

-  { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },

-  { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },

-  { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },

-  { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },

-

-  { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },

-  { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },

-  { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },

-  { NCoderPropID::kAlgorithm, VT_UI4, L"a" },

-  { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },

-  { NCoderPropID::kNumThreads, VT_UI4, L"mt" },

-  { NCoderPropID::kDefaultProp, VT_UI4, L"" }

-};

-

-static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)

-{

-  if (varType == srcProp.vt)

-  {

-    destProp = srcProp;

-    return true;

-  }

-  if (varType == VT_UI1)

-  {

-    if (srcProp.vt == VT_UI4)

-    {

-      UInt32 value = srcProp.ulVal;

-      if (value > 0xFF)

-        return false;

-      destProp = (Byte)value;

-      return true;

-    }

-  }

-  else if (varType == VT_BOOL)

-  {

-    bool res;

-    if (SetBoolProperty(res, srcProp) != S_OK)

-      return false;

-    destProp = res;

-    return true;

-  }

-  return false;

-}

-    

-static int FindPropIdExact(const UString &name)

-{

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

-    if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)

-      return i;

-  return -1;

-}

-

-static int FindPropIdStart(const UString &name)

-{

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

-  {

-    UString t = g_NameToPropID[i].Name;

-    if (t.CompareNoCase(name.Left(t.Length())) == 0)

-      return i;

-  }

-  return -1;

-}

-

-static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)

-{

-  for (int j = 0; j < m.Props.Size(); j++)

-    if (m.Props[j].Id == propID)

-      return;

-  CProp prop;

-  prop.Id = propID;

-  prop.Value = value;

-  m.Props.Add(prop);

-}

-

-void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo

+void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo

     #ifndef _7ZIP_ST

     , UInt32 numThreads

     #endif

     )

 {

   UInt32 level = _level;

-  if (oneMethodInfo.MethodName.IsEmpty())

-    oneMethodInfo.MethodName = kDefaultMethodName;

-  

-  if (oneMethodInfo.IsLzma())

-  {

-    UInt32 dicSize =

-      (level >= 9 ? kLzmaDicSizeX9 :

-      (level >= 7 ? kLzmaDicSizeX7 :

-      (level >= 5 ? kLzmaDicSizeX5 :

-      (level >= 3 ? kLzmaDicSizeX3 :

-                    kLzmaDicSizeX1))));

-    

-    UInt32 algo =

-      (level >= 5 ? kLzmaAlgoX5 :

-                    kLzmaAlgoX1);

-    

-    UInt32 fastBytes =

-      (level >= 7 ? kLzmaFastBytesX7 :

-                    kLzmaFastBytesX1);

-    

-    const wchar_t *matchFinder =

-      (level >= 5 ? kLzmaMatchFinderX5 :

-                    kLzmaMatchFinderX1);

-    

-    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);

-    #ifndef _7ZIP_ST

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

-    #endif

-  }

-  else if (IsDeflateMethod(oneMethodInfo.MethodName))

-  {

-    UInt32 fastBytes =

-      (level >= 9 ? kDeflateFastBytesX9 :

-      (level >= 7 ? kDeflateFastBytesX7 :

-                    kDeflateFastBytesX1));

-    

-    UInt32 numPasses =

-      (level >= 9 ? kDeflatePassesX9 :

-      (level >= 7 ? kDeflatePassesX7 :

-                    kDeflatePassesX1));

-    

-    UInt32 algo =

-      (level >= 5 ? kDeflateAlgoX5 :

-                    kDeflateAlgoX1);

-    

-    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);

-  }

-  else if (IsBZip2Method(oneMethodInfo.MethodName))

-  {

-    UInt32 numPasses =

-      (level >= 9 ? kBZip2NumPassesX9 :

-      (level >= 7 ? kBZip2NumPassesX7 :

-                    kBZip2NumPassesX1));

-    

-    UInt32 dicSize =

-      (level >= 5 ? kBZip2DicSizeX5 :

-      (level >= 3 ? kBZip2DicSizeX3 :

-                    kBZip2DicSizeX1));

-    

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);

-    #ifndef _7ZIP_ST

-    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

-    #endif

-  }

-  else if (IsPpmdMethod(oneMethodInfo.MethodName))

-  {

-    UInt32 useMemSize =

-      (level >= 9 ? kPpmdMemSizeX9 :

-      (level >= 7 ? kPpmdMemSizeX7 :

-      (level >= 5 ? kPpmdMemSizeX5 :

-                    kPpmdMemSizeX1)));

-    

-    UInt32 order =

-      (level >= 9 ? kPpmdOrderX9 :

-      (level >= 7 ? kPpmdOrderX7 :

-      (level >= 5 ? kPpmdOrderX5 :

-                    kPpmdOrderX1)));

-    

-    SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);

-    SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);

-  }

-}

-

-static void SplitParams(const UString &srcString, UStringVector &subStrings)

-{

-  subStrings.Clear();

-  UString name;

-  int len = srcString.Length();

-  if (len == 0)

-    return;

-  for (int i = 0; i < len; i++)

-  {

-    wchar_t c = srcString[i];

-    if (c == L':')

-    {

-      subStrings.Add(name);

-      name.Empty();

-    }

-    else

-      name += c;

-  }

-  subStrings.Add(name);

-}

-

-static void SplitParam(const UString &param, UString &name, UString &value)

-{

-  int eqPos = param.Find(L'=');

-  if (eqPos >= 0)

-  {

-    name = param.Left(eqPos);

-    value = param.Mid(eqPos + 1);

-    return;

-  }

-  for(int i = 0; i < param.Length(); i++)

-  {

-    wchar_t c = param[i];

-    if (c >= L'0' && c <= L'9')

-    {

-      name = param.Left(i);

-      value = param.Mid(i);

-      return;

-    }

-  }

-  name = param;

-}

-

-HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)

-{

-  CProp prop;

-  int index = FindPropIdExact(name);

-  if (index < 0)

-    return E_INVALIDARG;

-  const CNameToPropID &nameToPropID = g_NameToPropID[index];

-  prop.Id = nameToPropID.PropID;

-

-  if (prop.Id == NCoderPropID::kBlockSize ||

-      prop.Id == NCoderPropID::kDictionarySize ||

-      prop.Id == NCoderPropID::kUsedMemorySize)

-  {

-    UInt32 dicSize;

-    RINOK(ParsePropDictionaryValue(value, dicSize));

-    prop.Value = dicSize;

-  }

-  else

-  {

-    NCOM::CPropVariant propValue;

-    

-    if (nameToPropID.VarType == VT_BSTR)

-      propValue = value;

-    else if (nameToPropID.VarType == VT_BOOL)

-    {

-      bool res;

-      if (!StringToBool(value, res))

-        return E_INVALIDARG;

-      propValue = res;

-    }

-    else

-    {

-      UInt32 number;

-      if (ParseStringToUInt32(value, number) == value.Length())

-        propValue = number;

-      else

-        propValue = value;

-    }

-    

-    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))

-      return E_INVALIDARG;

-  }

-  oneMethodInfo.Props.Add(prop);

-  return S_OK;

-}

-

-HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)

-{

-  UStringVector params;

-  SplitParams(srcString, params);

-  if (params.Size() > 0)

-    oneMethodInfo.MethodName = params[0];

-  for (int i = 1; i < params.Size(); i++)

-  {

-    const UString &param = params[i];

-    UString name, value;

-    SplitParam(param, name, value);

-    RINOK(SetParam(oneMethodInfo, name, value));

-  }

-  return S_OK;

-}

-

-HRESULT COutHandler::SetSolidSettings(const UString &s)

-{

-  UString s2 = s;

-  s2.MakeUpper();

-  for (int i = 0; i < s2.Length();)

-  {

-    const wchar_t *start = ((const wchar_t *)s2) + i;

-    const wchar_t *end;

-    UInt64 v = ConvertStringToUInt64(start, &end);

-    if (start == end)

-    {

-      if (s2[i++] != 'E')

-        return E_INVALIDARG;

-      _solidExtension = true;

-      continue;

-    }

-    i += (int)(end - start);

-    if (i == s2.Length())

-      return E_INVALIDARG;

-    wchar_t c = s2[i++];

-    switch(c)

-    {

-      case 'F':

-        if (v < 1)

-          v = 1;

-        _numSolidFiles = v;

-        break;

-      case 'B':

-        _numSolidBytes = v;

-        _numSolidBytesDefined = true;

-        break;

-      case 'K':

-        _numSolidBytes = (v << 10);

-        _numSolidBytesDefined = true;

-        break;

-      case 'M':

-        _numSolidBytes = (v << 20);

-        _numSolidBytesDefined = true;

-        break;

-      case 'G':

-        _numSolidBytes = (v << 30);

-        _numSolidBytesDefined = true;

-        break;

-      default:

-        return E_INVALIDARG;

-    }

-  }

-  return S_OK;

-}

-

-HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)

-{

-  bool isSolid;

-  switch(value.vt)

-  {

-    case VT_EMPTY:

-      isSolid = true;

-      break;

-    case VT_BOOL:

-      isSolid = (value.boolVal != VARIANT_FALSE);

-      break;

-    case VT_BSTR:

-      if (StringToBool(value.bstrVal, isSolid))

-        break;

-      return SetSolidSettings(value.bstrVal);

-    default:

-      return E_INVALIDARG;

-  }

-  if (isSolid)

-    InitSolid();

-  else

-    _numSolidFiles = 1;

-  return S_OK;

-}

-

-void COutHandler::Init()

-{

-  _removeSfxBlock = false;

-  _compressHeaders = true;

-  _encryptHeadersSpecified = false;

-  _encryptHeaders = false;

-  

-  WriteCTime = false;

-  WriteATime = false;

-  WriteMTime = true;

-  

+  if (level != (UInt32)(Int32)-1)

+    SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);

   #ifndef _7ZIP_ST

-  _numThreads = NSystem::GetNumberOfProcessors();

+  SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

+  #endif

+}

+

+void CMultiMethodProps::Init()

+{

+  #ifndef _7ZIP_ST

+  _numProcessors = _numThreads = NSystem::GetNumberOfProcessors();

   #endif

   

-  _level = 5;

+  _level = (UInt32)(Int32)-1;

   _autoFilter = true;

-  _volumeMode = false;

   _crcSize = 4;

-  InitSolid();

+  _filterMethod.Clear();

+  _methods.Clear();

 }

 

-void COutHandler::BeforeSetProperty()

-{

-  Init();

-  #ifndef _7ZIP_ST

-  numProcessors = NSystem::GetNumberOfProcessors();

-  #endif

-

-  mainDicSize = 0xFFFFFFFF;

-  mainDicMethodIndex = 0xFFFFFFFF;

-  minNumber = 0;

-  _crcSize = 4;

-}

-

-HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)

+HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)

 {

   UString name = nameSpec;

-  name.MakeUpper();

+  name.MakeLower_Ascii();

   if (name.IsEmpty())

     return E_INVALIDARG;

   

-  if (name[0] == 'X')

+  if (name[0] == 'x')

   {

     name.Delete(0);

     _level = 9;

-    return ParsePropValue(name, value, _level);

+    return ParsePropToUInt32(name, value, _level);

   }

   

-  if (name[0] == L'S')

+  if (name == L"crc")

   {

-    name.Delete(0);

-    if (name.IsEmpty())

-      return SetSolidSettings(value);

-    if (value.vt != VT_EMPTY)

-      return E_INVALIDARG;

-    return SetSolidSettings(name);

-  }

-  

-  if (name == L"CRC")

-  {

-    _crcSize = 4;

     name.Delete(0, 3);

-    return ParsePropValue(name, value, _crcSize);

+    _crcSize = 4;

+    return ParsePropToUInt32(name, value, _crcSize);

   }

   

   UInt32 number;

   int index = ParseStringToUInt32(name, number);

-  UString realName = name.Mid(index);

+  UString realName = name.Ptr(index);

   if (index == 0)

   {

-    if(name.Left(2).CompareNoCase(L"MT") == 0)

+    if (name.IsPrefixedBy(L"mt"))

     {

       #ifndef _7ZIP_ST

-      RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));

+      RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));

       #endif

       return S_OK;

     }

-    if (name.CompareNoCase(L"RSFX") == 0)  return SetBoolProperty(_removeSfxBlock, value);

-    if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);

-    if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);

-    if (name.CompareNoCase(L"HCF") == 0)

+    if (name.IsEqualTo("f"))

     {

-      bool compressHeadersFull = true;

-      RINOK(SetBoolProperty(compressHeadersFull, value));

-      if (!compressHeadersFull)

+      HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);

+      if (res == S_OK)

+        return res;

+      if (value.vt != VT_BSTR)

         return E_INVALIDARG;

-      return S_OK;

+      return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);

     }

-    if (name.CompareNoCase(L"HE") == 0)

-    {

-      RINOK(SetBoolProperty(_encryptHeaders, value));

-      _encryptHeadersSpecified = true;

-      return S_OK;

-    }

-    if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);

-    if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);

-    if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);

-    if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);

     number = 0;

   }

-  if (number > 10000)

+  if (number > 64)

     return E_FAIL;

-  if (number < minNumber)

-    return E_INVALIDARG;

-  number -= minNumber;

-  for(int j = _methods.Size(); j <= (int)number; j++)

-  {

-    COneMethodInfo oneMethodInfo;

-    _methods.Add(oneMethodInfo);

-  }

-  

-  COneMethodInfo &oneMethodInfo = _methods[number];

-  

-  if (realName.Length() == 0)

-  {

-    if (value.vt != VT_BSTR)

-      return E_INVALIDARG;

-    

-    RINOK(SetParams(oneMethodInfo, value.bstrVal));

-  }

-  else

-  {

-    int index = FindPropIdStart(realName);

-    if (index < 0)

-      return E_INVALIDARG;

-    const CNameToPropID &nameToPropID = g_NameToPropID[index];

-    CProp prop;

-    prop.Id = nameToPropID.PropID;

+  for (int j = _methods.Size(); j <= (int)number; j++)

+    _methods.Add(COneMethodInfo());

+  return _methods[number].ParseMethodFromPROPVARIANT(realName, value);

+}

 

-    if (prop.Id == NCoderPropID::kBlockSize ||

-        prop.Id == NCoderPropID::kDictionarySize ||

-        prop.Id == NCoderPropID::kUsedMemorySize)

+void CSingleMethodProps::Init()

+{

+  Clear();

+  #ifndef _7ZIP_ST

+  _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();

+  AddNumThreadsProp(_numThreads);

+  #endif

+  _level = (UInt32)(Int32)-1;

+}

+

+HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

+{

+  Init();

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    UString name = names[i];

+    name.MakeLower_Ascii();

+    if (name.IsEmpty())

+      return E_INVALIDARG;

+    const PROPVARIANT &value = values[i];

+    if (name[0] == L'x')

     {

-      UInt32 dicSize;

-      RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));

-      prop.Value = dicSize;

-      if (number <= mainDicMethodIndex)

-        mainDicSize = dicSize;

+      UInt32 a = 9;

+      RINOK(ParsePropToUInt32(name.Ptr(1), value, a));

+      _level = a;

+      AddLevelProp(a);

+    }

+    else if (name.IsPrefixedBy(L"mt"))

+    {

+      #ifndef _7ZIP_ST

+      RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));

+      AddNumThreadsProp(_numThreads);

+      #endif

     }

     else

-    {

-      int index = FindPropIdExact(realName);

-      if (index < 0)

-        return E_INVALIDARG;

-      const CNameToPropID &nameToPropID = g_NameToPropID[index];

-      prop.Id = nameToPropID.PropID;

-      if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))

-        return E_INVALIDARG;

-    }

-    oneMethodInfo.Props.Add(prop);

+      return ParseMethodFromPROPVARIANT(names[i], value);

   }

   return S_OK;

 }

diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
old mode 100755
new mode 100644
index c4ccf37..8fc3d26
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -3,83 +3,61 @@
 #ifndef __HANDLER_OUT_H

 #define __HANDLER_OUT_H

 

-#include "../../../Common/MyString.h"

 #include "../../Common/MethodProps.h"

 

 namespace NArchive {

 

-struct COneMethodInfo

+class CMultiMethodProps

 {

-  CObjectVector<CProp> Props;

-  UString MethodName;

-

-  bool IsLzma() const;

-};

-

-class COutHandler

-{

+  UInt32 _level;

 public:

-  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);

-  

-  HRESULT SetSolidSettings(const UString &s);

-  HRESULT SetSolidSettings(const PROPVARIANT &value);

-

   #ifndef _7ZIP_ST

   UInt32 _numThreads;

+  UInt32 _numProcessors;

   #endif

 

   UInt32 _crcSize;

-

   CObjectVector<COneMethodInfo> _methods;

-  bool _removeSfxBlock;

-  

-  UInt64 _numSolidFiles;

-  UInt64 _numSolidBytes;

-  bool _numSolidBytesDefined;

-  bool _solidExtension;

-

-  bool _compressHeaders;

-  bool _encryptHeadersSpecified;

-  bool _encryptHeaders;

-

-  bool WriteCTime;

-  bool WriteATime;

-  bool WriteMTime;

-

+  COneMethodInfo _filterMethod;

   bool _autoFilter;

-  UInt32 _level;

 

-  bool _volumeMode;

-

-  HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);

-  HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);

-

-  void SetCompressionMethod2(COneMethodInfo &oneMethodInfo

+  void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo

       #ifndef _7ZIP_ST

       , UInt32 numThreads

       #endif

       );

 

-  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }

-  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }

-  void InitSolid()

+  unsigned GetNumEmptyMethods() const

   {

-    InitSolidFiles();

-    InitSolidSize();

-    _solidExtension = false;

-    _numSolidBytesDefined = false;

+    unsigned i;

+    for (i = 0; i < _methods.Size(); i++)

+      if (!_methods[i].IsEmpty())

+        break;

+    return i;

   }

 

+  int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }

+

   void Init();

 

-  COutHandler() { Init(); }

+  CMultiMethodProps() { Init(); }

+  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);

+};

 

-  void BeforeSetProperty();

+class CSingleMethodProps: public COneMethodInfo

+{

+  UInt32 _level;

+  

+public:

+  #ifndef _7ZIP_ST

+  UInt32 _numThreads;

+  UInt32 _numProcessors;

+  #endif

 

-  UInt32 minNumber;

-  UInt32 numProcessors;

-  UInt32 mainDicSize;

-  UInt32 mainDicMethodIndex;

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

 };

 

 }

diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
old mode 100755
new mode 100644
index 6338d0a..cddc083
--- a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
@@ -6,29 +6,33 @@
 

 STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  UInt32 realProcessedSize;

-  HRESULT result = _stream->Read(data, size, &realProcessedSize);

-  _size += realProcessedSize;

-  if (size > 0 && realProcessedSize == 0)

+  UInt32 realProcessed = 0;

+  HRESULT result = S_OK;

+  if (_stream)

+    result = _stream->Read(data, size, &realProcessed);

+  _size += realProcessed;

+  if (size != 0 && realProcessed == 0)

     _wasFinished = true;

-  _crc = CrcUpdate(_crc, data, realProcessedSize);

-  if(processedSize != NULL)

-    *processedSize = realProcessedSize;

+  _crc = CrcUpdate(_crc, data, realProcessed);

+  if (processedSize)

+    *processedSize = realProcessed;

   return result;

 }

 

 STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  UInt32 realProcessedSize;

-  HRESULT result = _stream->Read(data, size, &realProcessedSize);

+  UInt32 realProcessed = 0;

+  HRESULT result = S_OK;

+  if (_stream)

+    result = _stream->Read(data, size, &realProcessed);

+  _size += realProcessed;

   /*

-  if (size > 0 && realProcessedSize == 0)

+  if (size != 0 && realProcessed == 0)

     _wasFinished = true;

   */

-  _size += realProcessedSize;

-  _crc = CrcUpdate(_crc, data, realProcessedSize);

-  if(processedSize != NULL)

-    *processedSize = realProcessedSize;

+  _crc = CrcUpdate(_crc, data, realProcessed);

+  if (processedSize)

+    *processedSize = realProcessed;

   return result;

 }

 

diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
old mode 100755
new mode 100644
index 287ddce..1608949
--- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -2,8 +2,6 @@
 

 #include "StdAfx.h"

 

-#include "../../../../C/Types.h"

-

 #include "ItemNameUtils.h"

 

 namespace NArchive {

@@ -12,6 +10,21 @@
 static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;

 static const wchar_t kDirDelimiter = L'/';

 

+void ReplaceToOsPathSeparator(wchar_t *s)

+{

+  #ifdef _WIN32

+  for (;;)

+  {

+    wchar_t c = *s;

+    if (c == 0)

+      break;

+    if (c == kDirDelimiter)

+      *s = kOSDirDelimiter;

+    s++;

+  }

+  #endif

+}

+

 UString MakeLegalName(const UString &name)

 {

   UString zipName = name;

@@ -31,20 +44,34 @@
   if (name.IsEmpty())

     return UString();

   UString newName = GetOSName(name);

-  if (newName[newName.Length() - 1] == kOSDirDelimiter)

-    newName.Delete(newName.Length() - 1);

+  if (newName.Back() == kOSDirDelimiter)

+    newName.DeleteBack();

   return newName;

 }

 

-bool HasTailSlash(const AString &name, UINT codePage)

+void ConvertToOSName2(UString &name)

+{

+  if (!name.IsEmpty())

+  {

+    name.Replace(kDirDelimiter, kOSDirDelimiter);

+    if (name.Back() == kOSDirDelimiter)

+      name.DeleteBack();

+  }

+}

+

+bool HasTailSlash(const AString &name, UINT

+  #if defined(_WIN32) && !defined(UNDER_CE)

+    codePage

+  #endif

+  )

 {

   if (name.IsEmpty())

     return false;

   LPCSTR prev =

   #if defined(_WIN32) && !defined(UNDER_CE)

-    CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);

+    CharPrevExA((WORD)codePage, name, &name[name.Len()], 0);

   #else

-    (LPCSTR)(name) + (name.Length() - 1);

+    (LPCSTR)(name) + (name.Len() - 1);

   #endif

   return (*prev == '/');

 }

diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
old mode 100755
new mode 100644
index 8b91d1c..8ee2d0f
--- a/CPP/7zip/Archive/Common/ItemNameUtils.h
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -1,16 +1,19 @@
 // Archive/Common/ItemNameUtils.h

 

-#ifndef __ARCHIVE_ITEMNAMEUTILS_H

-#define __ARCHIVE_ITEMNAMEUTILS_H

+#ifndef __ARCHIVE_ITEM_NAME_UTILS_H

+#define __ARCHIVE_ITEM_NAME_UTILS_H

 

 #include "../../../Common/MyString.h"

 

 namespace NArchive {

 namespace NItemName {

 

+  void ReplaceToOsPathSeparator(wchar_t *s);

+

   UString MakeLegalName(const UString &name);

   UString GetOSName(const UString &name);

   UString GetOSName2(const UString &name);

+  void ConvertToOSName2(UString &name);

   bool HasTailSlash(const AString &name, UINT codePage);

 

   #ifdef _WIN32

diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
old mode 100755
new mode 100644
index 83b3da1..3613ab2
--- a/CPP/7zip/Archive/Common/MultiStream.cpp
+++ b/CPP/7zip/Archive/Common/MultiStream.cpp
@@ -11,10 +11,10 @@
   if (size == 0)

     return S_OK;

   if (_pos >= _totalLength)

-    return (_pos == _totalLength) ? S_OK : E_FAIL;

+    return S_OK;

 

   {

-    int left = 0, mid = _streamIndex, right = Streams.Size();

+    unsigned left = 0, mid = _streamIndex, right = Streams.Size();

     for (;;)

     {

       CSubStreamInfo &m = Streams[mid];

@@ -51,15 +51,18 @@
   

 STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET: _pos = offset; break;

-    case STREAM_SEEK_CUR: _pos = _pos + offset; break;

-    case STREAM_SEEK_END: _pos = _totalLength + offset; break;

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _pos; break;

+    case STREAM_SEEK_END: offset += _totalLength; break;

     default: return STG_E_INVALIDFUNCTION;

   }

-  if (newPosition != 0)

-    *newPosition = _pos;

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _pos = offset;

+  if (newPosition)

+    *newPosition = offset;

   return S_OK;

 }

 

@@ -69,7 +72,7 @@
   public ISequentialOutStream,

   public CMyUnknownImp

 {

-  int _volIndex;

+  unsigned _volIndex;

   UInt64 _volSize;

   UInt64 _curPos;

   CMyComPtr<ISequentialOutStream> _volumeStream;

@@ -169,22 +172,20 @@
 

 STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  if(seekOrigin >= 3)

-    return STG_E_INVALIDFUNCTION;

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET:

-      _absPos = offset;

-      break;

-    case STREAM_SEEK_CUR:

-      _absPos += offset;

-      break;

-    case STREAM_SEEK_END:

-      _absPos = _length + offset;

-      break;

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _absPos; break;

+    case STREAM_SEEK_END: offset += _length; break;

+    default: return STG_E_INVALIDFUNCTION;

   }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _absPos = offset;

   _offsetPos = _absPos;

   _streamIndex = 0;

+  if (newPosition)

+    *newPosition = offset;

   return S_OK;

 }

 */

diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
old mode 100755
new mode 100644
index 74ec6ad..39e041d
--- a/CPP/7zip/Archive/Common/MultiStream.h
+++ b/CPP/7zip/Archive/Common/MultiStream.h
@@ -14,21 +14,26 @@
 {

   UInt64 _pos;

   UInt64 _totalLength;

-  int _streamIndex;

+  unsigned _streamIndex;

+

 public:

+

   struct CSubStreamInfo

   {

     CMyComPtr<IInStream> Stream;

     UInt64 Size;

     UInt64 GlobalOffset;

     UInt64 LocalPos;

+

+    CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {}

   };

+  

   CObjectVector<CSubStreamInfo> Streams;

   

   HRESULT Init()

   {

     UInt64 total = 0;

-    for (int i = 0; i < Streams.Size(); i++)

+    FOR_VECTOR (i, Streams)

     {

       CSubStreamInfo &s = Streams[i];

       s.GlobalOffset = total;

@@ -52,7 +57,7 @@
   public IOutStream,

   public CMyUnknownImp

 {

-  int _streamIndex; // required stream

+  unsigned _streamIndex; // required stream

   UInt64 _offsetPos; // offset from start of _streamIndex index

   UInt64 _absPos;

   UInt64 _length;

diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
old mode 100755
new mode 100644
index d9eb646..0cc9a85
--- a/CPP/7zip/Archive/Common/OutStreamWithCRC.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
@@ -28,6 +28,7 @@
     _calculate = calculate;

     _crc = CRC_INIT_VAL;

   }

+  void EnableCalc(bool calculate) { _calculate = calculate; }

   void InitCRC() { _crc = CRC_INIT_VAL; }

   UInt64 GetSize() const { return _size; }

   UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }

diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
old mode 100755
new mode 100644
index 5550a23..0fe89b3
--- a/CPP/7zip/Archive/Common/ParseProperties.cpp
+++ b/CPP/7zip/Archive/Common/ParseProperties.cpp
@@ -1,177 +1,3 @@
 // ParseProperties.cpp

 

 #include "StdAfx.h"

-

-#include "ParseProperties.h"

-

-#include "Common/StringToInt.h"

-#include "Common/MyCom.h"

-

-HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)

-{

-  if (prop.vt == VT_UI4)

-  {

-    if (!name.IsEmpty())

-      return E_INVALIDARG;

-    resValue = prop.ulVal;

-  }

-  else if (prop.vt == VT_EMPTY)

-  {

-    if(!name.IsEmpty())

-    {

-      const wchar_t *start = name;

-      const wchar_t *end;

-      UInt64 v = ConvertStringToUInt64(start, &end);

-      if (end - start != name.Length())

-        return E_INVALIDARG;

-      resValue = (UInt32)v;

-    }

-  }

-  else

-    return E_INVALIDARG;

-  return S_OK;

-}

-

-static const int kLogarithmicSizeLimit = 32;

-static const wchar_t kByteSymbol = L'B';

-static const wchar_t kKiloByteSymbol = L'K';

-static const wchar_t kMegaByteSymbol = L'M';

-

-HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)

-{

-  UString srcString = srcStringSpec;

-  srcString.MakeUpper();

-

-  const wchar_t *start = srcString;

-  const wchar_t *end;

-  UInt64 number = ConvertStringToUInt64(start, &end);

-  int numDigits = (int)(end - start);

-  if (numDigits == 0 || srcString.Length() > numDigits + 1)

-    return E_INVALIDARG;

-  if (srcString.Length() == numDigits)

-  {

-    if (number >= kLogarithmicSizeLimit)

-      return E_INVALIDARG;

-    dicSize = (UInt32)1 << (int)number;

-    return S_OK;

-  }

-  switch (srcString[numDigits])

-  {

-    case kByteSymbol:

-      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))

-        return E_INVALIDARG;

-      dicSize = (UInt32)number;

-      break;

-    case kKiloByteSymbol:

-      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))

-        return E_INVALIDARG;

-      dicSize = (UInt32)(number << 10);

-      break;

-    case kMegaByteSymbol:

-      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))

-        return E_INVALIDARG;

-      dicSize = (UInt32)(number << 20);

-      break;

-    default:

-      return E_INVALIDARG;

-  }

-  return S_OK;

-}

-

-HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)

-{

-  if (name.IsEmpty())

-  {

-    if (prop.vt == VT_UI4)

-    {

-      UInt32 logDicSize = prop.ulVal;

-      if (logDicSize >= 32)

-        return E_INVALIDARG;

-      resValue = (UInt32)1 << logDicSize;

-      return S_OK;

-    }

-    if (prop.vt == VT_BSTR)

-      return ParsePropDictionaryValue(prop.bstrVal, resValue);

-    return E_INVALIDARG;

-  }

-  return ParsePropDictionaryValue(name, resValue);

-}

-

-bool StringToBool(const UString &s, bool &res)

-{

-  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)

-  {

-    res = true;

-    return true;

-  }

-  if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)

-  {

-    res = false;

-    return true;

-  }

-  return false;

-}

-

-HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)

-{

-  switch(value.vt)

-  {

-    case VT_EMPTY:

-      dest = true;

-      return S_OK;

-    case VT_BOOL:

-      dest = (value.boolVal != VARIANT_FALSE);

-      return S_OK;

-    /*

-    case VT_UI4:

-      dest = (value.ulVal != 0);

-      break;

-    */

-    case VT_BSTR:

-      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;

-  }

-  return E_INVALIDARG;

-}

-

-int ParseStringToUInt32(const UString &srcString, UInt32 &number)

-{

-  const wchar_t *start = srcString;

-  const wchar_t *end;

-  UInt64 number64 = ConvertStringToUInt64(start, &end);

-  if (number64 > 0xFFFFFFFF)

-  {

-    number = 0;

-    return 0;

-  }

-  number = (UInt32)number64;

-  return (int)(end - start);

-}

-

-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)

-{

-  if (name.IsEmpty())

-  {

-    switch(prop.vt)

-    {

-      case VT_UI4:

-        numThreads = prop.ulVal;

-        break;

-      default:

-      {

-        bool val;

-        RINOK(SetBoolProperty(val, prop));

-        numThreads = (val ? defaultNumThreads : 1);

-        break;

-      }

-    }

-  }

-  else

-  {

-    UInt32 number;

-    int index = ParseStringToUInt32(name, number);

-    if (index != name.Length())

-      return E_INVALIDARG;

-    numThreads = number;

-  }

-  return S_OK;

-}

diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
old mode 100755
new mode 100644
index c64fc1e..f4367a7
--- a/CPP/7zip/Archive/Common/ParseProperties.h
+++ b/CPP/7zip/Archive/Common/ParseProperties.h
@@ -1,18 +1,6 @@
 // ParseProperties.h

 

-#ifndef __PARSEPROPERTIES_H

-#define __PARSEPROPERTIES_H

-

-#include "Common/MyString.h"

-#include "Common/Types.h"

-

-HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);

-HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);

-HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);

-

-bool StringToBool(const UString &s, bool &res);

-HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);

-int ParseStringToUInt32(const UString &srcString, UInt32 &number);

-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);

+#ifndef __PARSE_PROPERTIES_H

+#define __PARSE_PROPERTIES_H

 

 #endif

diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/Archive/Common/StdAfx.h
+++ b/CPP/7zip/Archive/Common/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
old mode 100755
new mode 100644
index a45b5c9..4267d46
--- a/CPP/7zip/Archive/DllExports2.cpp
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -1,10 +1,10 @@
-// DLLExports.cpp

+// DLLExports2.cpp

 

 #include "StdAfx.h"

 

 #include "../../Common/MyInitGuid.h"

 

-#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+#if defined(_7ZIP_LARGE_PAGES)

 #include "../../../C/Alloc.h"

 #endif

 

@@ -45,30 +45,38 @@
 static const UInt16 kDecodeId = 0x2790;

 

 DEFINE_GUID(CLSID_CCodec,

-0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

+0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);

 

 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 CreateObject(const GUID *clsid, const GUID *iid, void **outObject)

 {

   // COM_TRY_BEGIN

   *outObject = 0;

-  if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)

-  {

+  if (*iid == IID_ICompressCoder ||

+      *iid == IID_ICompressCoder2 ||

+      *iid == IID_ICompressFilter)

     return CreateCoder(clsid, iid, outObject);

-  }

-  else

-  {

-    return CreateArchiver(clsid, iid, outObject);

-  }

+  if (*iid == IID_IHasher)

+    return CreateHasher(clsid, (IHasher **)outObject);

+  return CreateArchiver(clsid, iid, outObject);

   // COM_TRY_END

 }

 

 STDAPI SetLargePageMode()

 {

-  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+  #if defined(_7ZIP_LARGE_PAGES)

   SetLargePageSize();

   #endif

   return S_OK;

 }

+

+extern bool g_CaseSensitive;

+

+STDAPI SetCaseSensitive(Int32 caseSensitive)

+{

+  g_CaseSensitive = (caseSensitive != 0);

+  return S_OK;

+}

diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
old mode 100755
new mode 100644
index e4101cc..5e831c9
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -20,20 +20,43 @@
   };

 }

 

+namespace NArcInfoFlags

+{

+  const UInt32 kKeepName        = 1 << 0;  // keep name of file in archive name

+  const UInt32 kAltStreams      = 1 << 1;  // the handler supports alt streams

+  const UInt32 kNtSecure        = 1 << 2;  // the handler supports NT security

+  const UInt32 kFindSignature   = 1 << 3;  // the handler can find start of archive

+  const UInt32 kMultiSignature  = 1 << 4;  // there are several signatures

+  const UInt32 kUseGlobalOffset = 1 << 5;  // the seek position of stream must be set as global offset

+  const UInt32 kStartOpen       = 1 << 6;  // call handler for each start position

+  const UInt32 kPureStartOpen   = 1 << 7;  // call handler only for start of file

+  const UInt32 kBackwardOpen    = 1 << 8;  // archive can be open backward

+  const UInt32 kPreArc          = 1 << 9;  // such archive can be stored before real archive (like SFX stub)

+  const UInt32 kSymLinks        = 1 << 10; // the handler supports symbolic links

+  const UInt32 kHardLinks       = 1 << 11; // the handler supports hard links

+}

+

 namespace NArchive

 {

-  enum

+  namespace NHandlerPropID

   {

-    kName = 0,

-    kClassID,

-    kExtension,

-    kAddExtension,

-    kUpdate,

-    kKeepName,

-    kStartSignature,

-    kFinishSignature,

-    kAssociate

-  };

+    enum

+    {

+      kName = 0,        // VT_BSTR

+      kClassID,         // binary GUID in VT_BSTR

+      kExtension,       // VT_BSTR

+      kAddExtension,    // VT_BSTR

+      kUpdate,          // VT_BOOL

+      kKeepName,        // VT_BOOL

+      kSignature,       // binary in VT_BSTR

+      kMultiSignature,  // binary in VT_BSTR

+      kSignatureOffset, // VT_UI4

+      kAltStreams,      // VT_BOOL

+      kNtSecure,        // VT_BOOL

+      kFlags            // VT_UI4

+      // kVersion          // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR)

+    };

+  }

 

   namespace NExtract

   {

@@ -46,25 +69,32 @@
         kSkip

       };

     }

+  

     namespace NOperationResult

     {

       enum

       {

         kOK = 0,

-        kUnSupportedMethod,

+        kUnsupportedMethod,

         kDataError,

-        kCRCError

+        kCRCError,

+        kUnavailable,

+        kUnexpectedEnd,

+        kDataAfterEnd,

+        kIsNotArc,

+        kHeadersError

       };

     }

   }

+  

   namespace NUpdate

   {

     namespace NOperationResult

     {

       enum

       {

-        kOK = 0,

-        kError

+        kOK = 0

+        , // kError

       };

     }

   }

@@ -79,10 +109,16 @@
   INTERFACE_IArchiveOpenCallback(PURE);

 };

 

+/*

+IArchiveExtractCallback::GetStream

+  Result:

+      (*inStream == NULL) - for directories

+      (*inStream == NULL) - if link (hard link or symbolic link) was created

+*/

 

 #define INTERFACE_IArchiveExtractCallback(x) \

   INTERFACE_IProgress(x) \

-  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \

+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \

   STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \

   STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

 

@@ -115,41 +151,184 @@
 

 

 /*

+IInArchive::Open

+    stream

+      if (kUseGlobalOffset), stream current position can be non 0.

+      if (!kUseGlobalOffset), stream current position is 0.

+    if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream

+    if (*maxCheckStartPosition == 0), the handler must check only current position as archive start

+

 IInArchive::Extract:

   indices must be sorted

-  numItems = 0xFFFFFFFF means "all files"

+  numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files"

   testMode != 0 means "test files without writing to outStream"

+

+IInArchive::GetArchiveProperty:

+  kpidOffset  - start offset of archive.

+      VT_EMPTY : means offset = 0.

+      VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed

+  kpidPhySize - size of archive. VT_EMPTY means unknown size.

+    kpidPhySize is allowed to be larger than file size. In that case it must show

+    supposed size.

+

+  kpidIsDeleted:

+  kpidIsAltStream:

+  kpidIsAux:

+  kpidINode:

+    must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty.

+

+

+Notes:

+  Don't call IInArchive functions for same IInArchive object from different threads simultaneously.

+  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

+  #define MY_NO_THROW_DECL_ONLY

+#endif

+

 #define INTERFACE_IInArchive(x) \

-  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \

-  STDMETHOD(Close)() x; \

-  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \

-  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \

-  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \

-  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \

-  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \

-  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \

-  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \

-  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;

+  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \

+  STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \

+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \

+  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \

+  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \

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

 

 ARCHIVE_INTERFACE(IInArchive, 0x60)

 {

   INTERFACE_IInArchive(PURE)

 };

 

+namespace NParentType

+{

+  enum

+  {

+    kDir = 0,

+    kAltStream

+  };

+};

+

+namespace NPropDataType

+{

+  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_Utf16 = kMask_Utf | 1;

+  // const UInt32 kMask_Utf32 = kMask_Utf | 2;

+

+  const UInt32 kNotDefined = 0;

+  const UInt32 kRaw = 1;

+  const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;

+};

+

+// UTF string (pointer to wchar_t) with zero end and little-endian.

+#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1))

+

+/*

+GetRawProp:

+  Result:

+    S_OK - even if property is not set

+*/

+

+#define INTERFACE_IArchiveGetRawProps(x) \

+  STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \

+  STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \

+  STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \

+  STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x;

+

+ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70)

+{

+  INTERFACE_IArchiveGetRawProps(PURE)

+};

+

+#define INTERFACE_IArchiveGetRootProps(x) \

+  STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \

+  STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \

+ 

+ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71)

+{

+  INTERFACE_IArchiveGetRootProps(PURE)

+};

+

 ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)

 {

   STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;

 };

 

+/*

+  OpenForSize

+  Result:

+    S_FALSE - is not archive

+    ? - DATA error

+*/

+    

+/*

+const UInt32 kOpenFlags_RealPhySize = 1 << 0;

+const UInt32 kOpenFlags_NoSeek = 1 << 1;

+// const UInt32 kOpenFlags_BeforeExtract = 1 << 2;

+*/

+

+/*

+Flags:

+   0 - opens archive with IInStream, if IInStream interface is supported

+     - if phySize is not available, it doesn't try to make full parse to get phySize

+   kOpenFlags_NoSeek -  ArcOpen2 function doesn't use IInStream interface, even if it's available

+   kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file

+   

+  if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified,

+  the handler can return S_OK, but it doesn't check even Signature.

+  So next Extract can be called for that sequential stream.

+*/

+

+/*

+ARCHIVE_INTERFACE(IArchiveOpen2, 0x62)

+{

+  STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE;

+};

+*/

+

+// ---------- UPDATE ----------

+

+/*

+GetUpdateItemInfo outs:

+*newData  *newProps

+   0        0      - Copy data and properties from archive

+   0        1      - Copy data from archive, request new properties

+   1        0      - that combination is unused now

+   1        1      - Request new data and new properties. It can be used even for folders

+

+  indexInArchive = -1 if there is no item in archive, or if it doesn't matter.

+

+

+GetStream out:

+  Result:

+    S_OK:

+      (*inStream == NULL) - only for directories

+                          - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file

+      (*inStream != NULL) - for any file, even for empty file or anti-file

+    S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason)

+      (*inStream == NULL)

+

+The order of calling for hard links:

+  - GetStream()

+  - GetProperty(kpidHardLink)

+

+*/

+

 #define INTERFACE_IArchiveUpdateCallback(x) \

   INTERFACE_IProgress(x); \

-  STDMETHOD(GetUpdateItemInfo)(UInt32 index,  \

-      Int32 *newData, /*1 - new data, 0 - old data */ \

-      Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \

-      UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \

-      )  x; \

+  STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \

   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \

   STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \

   STDMETHOD(SetOperationResult)(Int32 operationResult) x; \

@@ -169,6 +348,27 @@
   INTERFACE_IArchiveUpdateCallback2(PURE);

 };

 

+/*

+UpdateItems()

+-------------

+

+  outStream: output stream. (the handler) MUST support the case when

+    Seek position in outStream is not ZERO.

+    but the caller calls with empty outStream and seek position is ZERO??

+ 

+  archives with stub:

+

+  If archive is open and the handler and (Offset > 0), then the handler

+  knows about stub size.

+  UpdateItems():

+  1) the handler MUST copy that stub to outStream

+  2) the caller MUST NOT copy the stub to outStream, if

+     "rsfx" property is set with SetProperties

+

+  the handler must support the case where

+    ISequentialOutStream *outStream

+*/

+

 

 #define INTERFACE_IOutArchive(x) \

   STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \

@@ -182,47 +382,61 @@
 

 ARCHIVE_INTERFACE(ISetProperties, 0x03)

 {

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE;

+};

+

+ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)

+{

+  STDMETHOD(KeepModeForNextOpen)() PURE;

+};

+

+/* Exe handler: the handler for executable format (PE, ELF, Mach-O).

+   SFX archive: executable stub + some tail data.

+     before 9.31: exe handler didn't parse SFX archives as executable format.

+     for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */

+

+ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05)

+{

+  STDMETHOD(AllowTail)(Int32 allowTail) PURE;

 };

 

 

 #define IMP_IInArchive_GetProp(k) \

   (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \

-    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \

-    const STATPROPSTG &srcItem = k[index]; \

-    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \

+    { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \

+    *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID];  *name = 0; return S_OK; } \

 

 #define IMP_IInArchive_GetProp_WITH_NAME(k) \

   (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \

-    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \

+    { 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; } \

 

 #define IMP_IInArchive_Props \

-  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \

-    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \

+    { *numProps = ARRAY_SIZE(kProps); return S_OK; } \

   STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)

 

 #define IMP_IInArchive_Props_WITH_NAME \

-  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \

-    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \

+    { *numProps = ARRAY_SIZE(kProps); return S_OK; } \

   STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)

 

 

 #define IMP_IInArchive_ArcProps \

-  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

-    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \

+    { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \

   STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)

 

 #define IMP_IInArchive_ArcProps_WITH_NAME \

-  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

-    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \

+    { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \

   STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)

 

 #define IMP_IInArchive_ArcProps_NO_Table \

-  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

-    { *numProperties = 0; return S_OK; } \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \

+    { *numProps = 0; return S_OK; } \

   STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \

     { return E_NOTIMPL; } \

 

@@ -231,4 +445,32 @@
   STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \

     { value->vt = VT_EMPTY; return S_OK; }

 

+

+

+#define k_IsArc_Res_NO   0

+#define k_IsArc_Res_YES  1

+#define k_IsArc_Res_NEED_MORE 2

+// #define k_IsArc_Res_YES_LOW_PROB 3

+

+#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI

+#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI

+

+extern "C"

+{

+  typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject);

+

+  typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size);

+  typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc);

+

+  typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats);

+  typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value);

+  typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value);

+

+  typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive);

+  typedef HRESULT (WINAPI *Func_SetLargePageMode)();

+

+  typedef IOutArchive * (*Func_CreateOutArchive)();

+  typedef IInArchive * (*Func_CreateInArchive)();

+}

+

 #endif

diff --git a/CPP/7zip/Archive/Icons/7z.ico b/CPP/7zip/Archive/Icons/7z.ico
old mode 100755
new mode 100644
Binary files differ
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
old mode 100755
new mode 100644
index 9b8db45..a372033
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -4,10 +4,10 @@
 

 #include "../../../C/CpuArch.h"

 

-#include "Common/ComTry.h"

-#include "Common/IntToString.h"

+#include "../../Common/ComTry.h"

+#include "../../Common/IntToString.h"

 

-#include "Windows/PropVariant.h"

+#include "../../Windows/PropVariant.h"

 

 #include "../Common/CreateCoder.h"

 #include "../Common/ProgressUtils.h"

@@ -26,17 +26,24 @@
 static bool CheckDicSize(const Byte *p)

 {

   UInt32 dicSize = GetUi32(p);

-  for (int i = 1; i <= 30; i++)

+  if (dicSize == 1)

+    return true;

+  for (unsigned i = 0; i <= 30; i++)

     if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))

       return true;

   return (dicSize == 0xFFFFFFFF);

 }

 

-STATPROPSTG kProps[] =

+static const Byte kProps[] =

 {

-  { NULL, kpidSize, VT_UI8},

-  { NULL, kpidPackSize, VT_UI8},

-  { NULL, kpidMethod, VT_BSTR}

+  kpidSize,

+  kpidPackSize,

+  kpidMethod

+};

+

+static const Byte kArcProps[] =

+{

+  kpidNumStreams

 };

 

 struct CHeader

@@ -62,16 +69,17 @@
   return

     LzmaProps[0] < 5 * 5 * 9 &&

     FilterID < 2 &&

-    (!HasSize() || Size < ((UInt64)1 << 56)) &&

-    CheckDicSize(LzmaProps + 1);

+    (!HasSize() || Size < ((UInt64)1 << 56))

+    && CheckDicSize(LzmaProps + 1);

 }

 

 class CDecoder

 {

-  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;

   CMyComPtr<ICompressCoder> _lzmaDecoder;

   CMyComPtr<ISequentialOutStream> _bcjStream;

 public:

+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;

+

   ~CDecoder();

   HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS

       bool filtered, ISequentialInStream *inStream);

@@ -86,7 +94,7 @@
     { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }

 };

 

-static const UInt64 k_BCJ = 0x03030103;

+static const UInt32 k_BCJ = 0x03030103;

   

 HRESULT CDecoder::Create(

     DECL_EXTERNAL_CODECS_LOC_VARS

@@ -95,6 +103,7 @@
   if (!_lzmaDecoder)

   {

     _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;

+    _lzmaDecoderSpec->FinishStream = true;

     _lzmaDecoder = _lzmaDecoderSpec;

   }

 

@@ -166,6 +175,10 @@
   }

   RINOK(res);

 

+  if (header.HasSize())

+    if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size)

+      return S_FALSE;

+

   return S_OK;

 }

 

@@ -178,11 +191,24 @@
 {

   CHeader _header;

   bool _lzma86;

-  UInt64 _startPosition;

-  UInt64 _packSize;

-  bool _packSizeDefined;

   CMyComPtr<IInStream> _stream;

   CMyComPtr<ISequentialInStream> _seqStream;

+  

+  bool _isArc;

+  bool _needSeekToStart;

+  bool _dataAfterEnd;

+  bool _needMoreInput;

+

+  bool _packSize_Defined;

+  bool _unpackSize_Defined;

+  bool _numStreams_Defined;

+

+  bool _unsupported;

+  bool _dataError;

+

+  UInt64 _packSize;

+  UInt64 _unpackSize;

+  UInt64 _numStreams;

 

   DECL_EXTERNAL_CODECS_VARS

   DECL_ISetCompressCodecsInfo

@@ -204,14 +230,26 @@
 };

 

 IMP_IInArchive_Props

-IMP_IInArchive_ArcProps_NO_Table

+IMP_IInArchive_ArcProps

 

 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

 {

   NCOM::CPropVariant prop;

-  switch(propID)

+  switch (propID)

   {

-    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;

+    case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;

+    case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;

+    case kpidErrorFlags:

+    {

+      UInt32 v = 0;

+      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;

+      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;

+      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;

+      if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;

+      if (_dataError) v |= kpv_ErrorFlags_DataError;

+      prop = v;

+    }

   }

   prop.Detach(value);

   return S_OK;

@@ -226,50 +264,37 @@
 static void DictSizeToString(UInt32 value, char *s)

 {

   for (int i = 0; i <= 31; i++)

-    if ((UInt32(1) << i) == value)

+    if (((UInt32)1 << i) == value)

     {

       ::ConvertUInt32ToString(i, s);

       return;

     }

   char c = 'b';

-  if ((value & ((1 << 20) - 1)) == 0)

-  {

-    value >>= 20;

-    c = 'm';

-  }

-  else if ((value & ((1 << 10) - 1)) == 0)

-  {

-    value >>= 10;

-    c = 'k';

-  }

+       if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = 'm'; }

+  else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = 'k'; }

   ::ConvertUInt32ToString(value, s);

-  int p = MyStringLen(s);

-  s[p++] = c;

-  s[p++] = '\0';

+  s += MyStringLen(s);

+  *s++ = c;

+  *s = 0;

 }

 

-static void MyStrCat(char *d, const char *s)

-{

-  MyStringCopy(d + MyStringLen(d), s);

-}

-

-STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)

+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)

 {

   NCOM::CPropVariant prop;

-  switch(propID)

+  switch (propID)

   {

     case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;

-    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;

     case kpidMethod:

       if (_stream)

       {

-        char s[64];

-        s[0] = '\0';

+        char sz[64];

+        char *s = sz;

         if (_header.FilterID != 0)

-          MyStrCat(s, "BCJ ");

-        MyStrCat(s, "LZMA:");

-        DictSizeToString(_header.GetDicSize(), s + MyStringLen(s));

-        prop = s;

+          s = MyStpCpy(s, "BCJ ");

+        s = MyStpCpy(s, "LZMA:");

+        DictSizeToString(_header.GetDicSize(), s);

+        prop = sz;

       }

       break;

   }

@@ -277,11 +302,54 @@
   return S_OK;

 }

 

+API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size)

+{

+  const UInt32 kHeaderSize = 1 + 4 + 8;

+  if (size < kHeaderSize)

+    return k_IsArc_Res_NEED_MORE;

+  if (p[0] >= 5 * 5 * 9)

+    return k_IsArc_Res_NO;

+  UInt64 unpackSize = GetUi64(p + 1 + 4);

+  if (unpackSize != (UInt64)(Int64)-1)

+  {

+    if (size >= ((UInt64)1 << 56))

+      return k_IsArc_Res_NO;

+  }

+  if (unpackSize != 0)

+  {

+    if (size < kHeaderSize + 2)

+      return k_IsArc_Res_NEED_MORE;

+    if (p[kHeaderSize] != 0)

+      return k_IsArc_Res_NO;

+    if (unpackSize != (UInt64)(Int64)-1)

+    {

+      if ((p[kHeaderSize + 1] & 0x80) != 0)

+        return k_IsArc_Res_NO;

+    }

+  }

+  if (!CheckDicSize(p + 1))

+    // return k_IsArc_Res_YES_LOW_PROB;

+    return k_IsArc_Res_NO;

+  return k_IsArc_Res_YES;

+}

+}

+

+API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size)

+{

+  if (size < 1)

+    return k_IsArc_Res_NEED_MORE;

+  Byte filterID = p[0];

+  if (filterID != 0 && filterID != 1)

+    return k_IsArc_Res_NO;

+  return IsArc_Lzma(p + 1, size - 1);

+}

+}

+

 STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)

 {

-  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));

+  Close();

   

-  const UInt32 kBufSize = 1 + 5 + 8 + 1;

+  const UInt32 kBufSize = 1 + 5 + 8 + 2;

   Byte buf[kBufSize];

   

   RINOK(ReadStream_FALSE(inStream, buf, kBufSize));

@@ -289,34 +357,71 @@
   if (!_header.Parse(buf, _lzma86))

     return S_FALSE;

   const Byte *start = buf + GetHeaderSize();

-  if (start[0] != 0)

+  if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80

     return S_FALSE;

   

-  UInt64 endPos;

-  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));

-  _packSize = endPos - _startPosition;

-  _packSizeDefined = true;

-  

+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));

+  if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0)

+    return S_FALSE;

+  _isArc = true;

   _stream = inStream;

   _seqStream = inStream;

+  _needSeekToStart = true;

   return S_OK;

 }

 

 STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)

 {

   Close();

+  _isArc = true;

   _seqStream = stream;

   return S_OK;

 }

 

 STDMETHODIMP CHandler::Close()

 {

-  _packSizeDefined = false;

+  _isArc = false;

+  _packSize_Defined = false;

+  _unpackSize_Defined = false;

+  _numStreams_Defined = false;

+

+  _dataAfterEnd = false;

+  _needMoreInput = false;

+  _unsupported = false;

+  _dataError = false;

+

+  _packSize = 0;

+

+  _needSeekToStart = false;

+

   _stream.Release();

   _seqStream.Release();

    return S_OK;

 }

 

+class CCompressProgressInfoImp:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+  CMyComPtr<IArchiveOpenCallback> Callback;

+public:

+  UInt64 Offset;

+ 

+  MY_UNKNOWN_IMP1(ICompressProgressInfo)

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+  void Init(IArchiveOpenCallback *callback) { Callback = callback; }

+};

+

+STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)

+{

+  if (Callback)

+  {

+    UInt64 files = 0;

+    UInt64 value = Offset + *inSize;

+    return Callback->SetCompleted(&files, &value);

+  }

+  return S_OK;

+}

 

 STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

     Int32 testMode, IArchiveExtractCallback *extractCallback)

@@ -324,10 +429,10 @@
   COM_TRY_BEGIN

   if (numItems == 0)

     return S_OK;

-  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))

     return E_INVALIDARG;

 

-  if (_stream)

+  if (_packSize_Defined)

     extractCallback->SetTotal(_packSize);

     

   

@@ -351,10 +456,14 @@
   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(extractCallback, true);

 

-  if (_stream)

+  if (_needSeekToStart)

   {

-    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

+    if (!_stream)

+      return E_FAIL;

+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));

   }

+  else

+    _needSeekToStart = true;

 

   CDecoder decoder;

   HRESULT result = decoder.Create(

@@ -362,67 +471,132 @@
       _lzma86, _seqStream);

   RINOK(result);

  

-  Int32 opRes = NExtract::NOperationResult::kOK;

   bool firstItem = true;

 

+  UInt64 packSize = 0;

+  UInt64 unpackSize = 0;

+  UInt64 numStreams = 0;

+

+  bool dataAfterEnd = false;

+  

   for (;;)

   {

-    lps->OutSize = outStreamSpec->GetSize();

-    lps->InSize = _packSize = decoder.GetInputProcessedSize();

-    _packSizeDefined = true;

+    lps->InSize = packSize;

+    lps->OutSize = unpackSize;

     RINOK(lps->SetCur());

 

-    CHeader st;

-

     const UInt32 kBufSize = 1 + 5 + 8;

     Byte buf[kBufSize];

     const UInt32 headerSize = GetHeaderSize();

     UInt32 processed;

     RINOK(decoder.ReadInput(buf, headerSize, &processed));

     if (processed != headerSize)

+    {

+      if (processed != 0)

+        dataAfterEnd = true;

       break;

+    }

   

+    CHeader st;

     if (!st.Parse(buf, _lzma86))

+    {

+      dataAfterEnd = true;

       break;

+    }

+    numStreams++;

     firstItem = false;

 

     result = decoder.Code(st, outStream, progress);

+

+    packSize = decoder.GetInputProcessedSize();

+    unpackSize = outStreamSpec->GetSize();

+    

     if (result == E_NOTIMPL)

     {

-      opRes = NExtract::NOperationResult::kUnSupportedMethod;

+      _unsupported = true;

+      result = S_FALSE;

       break;

     }

     if (result == S_FALSE)

-    {

-      opRes = NExtract::NOperationResult::kDataError;

       break;

-    }

     RINOK(result);

   }

+

   if (firstItem)

-    return E_FAIL;

+  {

+    _isArc = false;

+    result = S_FALSE;

+  }

+  else if (result == S_OK || result == S_FALSE)

+  {

+    if (dataAfterEnd)

+      _dataAfterEnd = true;

+    else if (decoder._lzmaDecoderSpec->NeedMoreInput)

+      _needMoreInput = true;

+

+    _packSize = packSize;

+    _unpackSize = unpackSize;

+    _numStreams = numStreams;

+  

+    _packSize_Defined = true;

+    _unpackSize_Defined = true;

+    _numStreams_Defined = true;

+  }

+  

+  Int32 opResult = NExtract::NOperationResult::kOK;

+

+  if (!_isArc)

+    opResult = NExtract::NOperationResult::kIsNotArc;

+  else if (_needMoreInput)

+    opResult = NExtract::NOperationResult::kUnexpectedEnd;

+  else if (_unsupported)

+    opResult = NExtract::NOperationResult::kUnsupportedMethod;

+  else if (_dataAfterEnd)

+    opResult = NExtract::NOperationResult::kDataAfterEnd;

+  else if (result == S_FALSE)

+    opResult = NExtract::NOperationResult::kDataError;

+  else if (result == S_OK)

+    opResult = NExtract::NOperationResult::kOK;

+  else

+    return result;

+

   outStream.Release();

-  return extractCallback->SetOperationResult(opRes);

+  return extractCallback->SetOperationResult(opResult);

   COM_TRY_END

 }

 

 IMPL_ISetCompressCodecsInfo

 

-static IInArchive *CreateArc() { return new CHandler(false); }

-static IInArchive *CreateArc86() { return new CHandler(true); }

-

 namespace NLzmaAr {

-  

+

+IMP_CreateArcIn_2(CHandler(false))

+

 static CArcInfo g_ArcInfo =

-  { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL };

+  { "lzma", "lzma", 0, 0xA,

+  0, { 0 },

+  // 2, { 0x5D, 0x00 },

+  0,

+  NArcInfoFlags::kStartOpen |

+  NArcInfoFlags::kKeepName,

+  CreateArc, NULL,

+  IsArc_Lzma };

+

 REGISTER_ARC(Lzma)

 

 }

 

 namespace NLzma86Ar {

 

+IMP_CreateArcIn_2(CHandler(true))

+

 static CArcInfo g_ArcInfo =

-  { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL };

+  { "lzma86", "lzma86", 0, 0xB,

+  0, { 0 },

+  0,

+  NArcInfoFlags::kKeepName,

+  CreateArc, NULL,

+  IsArc_Lzma86 };

+

 REGISTER_ARC(Lzma86)

 

 }

diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
old mode 100755
new mode 100644
index cb98a77..47829f3
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -2,10 +2,10 @@
 

 #include "StdAfx.h"

 

-#include "Common/ComTry.h"

-#include "Common/MyString.h"

+#include "../../Common/ComTry.h"

+#include "../../Common/MyString.h"

 

-#include "Windows/PropVariant.h"

+#include "../../Windows/PropVariant.h"

 

 #include "../Common/ProgressUtils.h"

 #include "../Common/RegisterArc.h"

@@ -19,15 +19,16 @@
 namespace NArchive {

 namespace NSplit {

 

-STATPROPSTG kProps[] =

+static const Byte kProps[] =

 {

-  { NULL, kpidPath, VT_BSTR},

-  { NULL, kpidSize, VT_UI8}

+  kpidPath,

+  kpidSize

 };

 

-STATPROPSTG kArcProps[] =

+static const Byte kArcProps[] =

 {

-  { NULL, kpidNumVolumes, VT_UI4}

+  kpidNumVolumes,

+  kpidTotalPhySize

 };

 

 class CHandler:

@@ -35,10 +36,12 @@
   public IInArchiveGetStream,

   public CMyUnknownImp

 {

-  UString _subName;

   CObjectVector<CMyComPtr<IInStream> > _streams;

   CRecordVector<UInt64> _sizes;

+  UString _subName;

   UInt64 _totalSize;

+

+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);

 public:

   MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)

   INTERFACE_IInArchive(;)

@@ -51,9 +54,11 @@
 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

 {

   NCOM::CPropVariant prop;

-  switch(propID)

+  switch (propID)

   {

     case kpidMainSubfile: prop = (UInt32)0; break;

+    case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break;

+    case kpidTotalPhySize: prop = _totalSize; break;

     case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;

   }

   prop.Detach(value);

@@ -72,20 +77,18 @@
     if (_splitStyle)

     {

       int i;

-      int numLetters = _changedPart.Length();

+      int numLetters = _changedPart.Len();

       for (i = numLetters - 1; i >= 0; i--)

       {

         wchar_t c = _changedPart[i];

         if (c == 'z')

         {

-          c = 'a';

-          newName = c + newName;

+          newName.InsertAtFront('a');

           continue;

         }

         else if (c == 'Z')

         {

-          c = 'A';

-          newName = c + newName;

+          newName.InsertAtFront('A');

           continue;

         }

         c++;

@@ -99,33 +102,32 @@
             newName += newChar;

           break;

         }

-        newName = c + newName;

+        newName.InsertAtFront(c);

         i--;

         for (; i >= 0; i--)

-          newName = _changedPart[i] + newName;

+          newName.InsertAtFront(_changedPart[i]);

         break;

       }

     }

     else

     {

       int i;

-      int numLetters = _changedPart.Length();

+      int numLetters = _changedPart.Len();

       for (i = numLetters - 1; i >= 0; i--)

       {

         wchar_t c = _changedPart[i];

-        if (c == L'9')

+        if (c == '9')

         {

-          c = L'0';

-          newName = c + newName;

+          newName.InsertAtFront('0');

           if (i == 0)

-            newName = UString(L'1') + newName;

+            newName.InsertAtFront('1');

           continue;

         }

         c++;

-        newName = c + newName;

+        newName.InsertAtFront(c);

         i--;

         for (; i >= 0; i--)

-          newName = _changedPart[i] + newName;

+          newName.InsertAtFront(_changedPart[i]);

         break;

       }

     }

@@ -134,142 +136,139 @@
   }

 };

 

-STDMETHODIMP CHandler::Open(IInStream *stream,

-    const UInt64 * /* maxCheckStartPosition */,

-    IArchiveOpenCallback *openArchiveCallback)

+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)

 {

-  COM_TRY_BEGIN

   Close();

-  if (openArchiveCallback == 0)

+  if (!callback)

     return S_FALSE;

-  // try

+

+  CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;

+  callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);

+  if (!volumeCallback)

+    return S_FALSE;

+  

+  UString name;

   {

-    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;

-    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;

-    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,

-        &openVolumeCallback) != S_OK)

+    NCOM::CPropVariant prop;

+    RINOK(volumeCallback->GetProperty(kpidName, &prop));

+    if (prop.vt != VT_BSTR)

       return S_FALSE;

-    

-    UString name;

+    name = prop.bstrVal;

+  }

+  

+  int dotPos = name.ReverseFind('.');

+  const UString prefix = name.Left(dotPos + 1);

+  const UString ext = name.Ptr(dotPos + 1);

+  UString ext2 = ext;

+  ext2.MakeLower_Ascii();

+  

+  CSeqName seqName;

+  

+  unsigned numLetters = 2;

+  bool splitStyle = false;

+  

+  if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa"))

+  {

+    splitStyle = true;

+    while (numLetters < ext2.Len())

+    {

+      if (ext2[ext2.Len() - numLetters - 1] != 'a')

+        break;

+      numLetters++;

+    }

+  }

+  else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01"))

+  {

+    while (numLetters < ext2.Len())

+    {

+      if (ext2[ext2.Len() - numLetters - 1] != '0')

+        break;

+      numLetters++;

+    }

+    if (numLetters != ext.Len())

+      return S_FALSE;

+  }

+  else

+    return S_FALSE;

+  

+  seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters);

+  seqName._changedPart = ext.RightPtr(numLetters);

+  seqName._splitStyle = splitStyle;

+  

+  if (prefix.Len() < 1)

+    _subName = L"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;

+  }

+  

+  _totalSize += size;

+  _sizes.Add(size);

+  _streams.Add(stream);

+  

+  {

+    UInt64 numFiles = _streams.Size();

+    RINOK(callback->SetCompleted(&numFiles, NULL));

+  }

+  

+  for (;;)

+  {

+    const UString fullName = seqName.GetNextName();

+    CMyComPtr<IInStream> nextStream;

+    HRESULT result = volumeCallback->GetStream(fullName, &nextStream);

+    if (result == S_FALSE)

+      break;

+    if (result != S_OK)

+      return result;

+    if (!stream)

+      break;

     {

       NCOM::CPropVariant prop;

-      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));

-      if (prop.vt != VT_BSTR)

-        return S_FALSE;

-      name = prop.bstrVal;

-    }

-    

-    int dotPos = name.ReverseFind('.');

-    UString prefix, ext;

-    if (dotPos >= 0)

-    {

-      prefix = name.Left(dotPos + 1);

-      ext = name.Mid(dotPos + 1);

-    }

-    else

-      ext = name;

-    UString extBig = ext;

-    extBig.MakeUpper();

-

-    CSeqName seqName;

-

-    int numLetters = 2;

-    bool splitStyle = false;

-    if (extBig.Right(2) == L"AA")

-    {

-      splitStyle = true;

-      while (numLetters < extBig.Length())

-      {

-        if (extBig[extBig.Length() - numLetters - 1] != 'A')

-          break;

-        numLetters++;

-      }

-    }

-    else if (ext.Right(2) == L"01")

-    {

-      while (numLetters < extBig.Length())

-      {

-        if (extBig[extBig.Length() - numLetters - 1] != '0')

-          break;

-        numLetters++;

-      }

-      if (numLetters != ext.Length())

-        return S_FALSE;

-    }

-    else

-      return S_FALSE;

-

-    _streams.Add(stream);

-

-    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);

-    seqName._changedPart = ext.Right(numLetters);

-    seqName._splitStyle = splitStyle;

-

-    if (prefix.Length() < 1)

-      _subName = L"file";

-    else

-      _subName = prefix.Left(prefix.Length() - 1);

-

-    _totalSize = 0;

-    UInt64 size;

-    {

-      NCOM::CPropVariant prop;

-      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));

+      RINOK(volumeCallback->GetProperty(kpidSize, &prop));

       if (prop.vt != VT_UI8)

         return E_INVALIDARG;

       size = prop.uhVal.QuadPart;

     }

     _totalSize += size;

     _sizes.Add(size);

-    

-    if (openArchiveCallback != NULL)

+    _streams.Add(nextStream);

     {

       UInt64 numFiles = _streams.Size();

-      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));

+      RINOK(callback->SetCompleted(&numFiles, NULL));

     }

+  }

 

-    for (;;)

-    {

-      UString fullName = seqName.GetNextName();

-      CMyComPtr<IInStream> nextStream;

-      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);

-      if (result == S_FALSE)

-        break;

-      if (result != S_OK)

-        return result;

-      if (!stream)

-        break;

-      {

-        NCOM::CPropVariant prop;

-        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));

-        if (prop.vt != VT_UI8)

-          return E_INVALIDARG;

-        size = prop.uhVal.QuadPart;

-      }

-      _totalSize += size;

-      _sizes.Add(size);

-      _streams.Add(nextStream);

-      if (openArchiveCallback != NULL)

-      {

-        UInt64 numFiles = _streams.Size();

-        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));

-      }

-    }

-  }

-  /*

-  catch(...)

+  if (_streams.Size() == 1)

   {

-    return S_FALSE;

+    if (splitStyle)

+      return S_FALSE;

   }

-  */

   return S_OK;

+}

+

+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)

+{

+  COM_TRY_BEGIN

+  HRESULT res = Open2(stream, callback);

+  if (res != S_OK)

+    Close();

+  return res;

   COM_TRY_END

 }

 

 STDMETHODIMP CHandler::Close()

 {

-  _sizes.Clear();

+  _totalSize = 0;

+  _subName.Empty();

   _streams.Clear();

+  _sizes.Clear();

   return S_OK;

 }

 

@@ -281,8 +280,8 @@
 

 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)

 {

-  NWindows::NCOM::CPropVariant prop;

-  switch(propID)

+  NCOM::CPropVariant prop;

+  switch (propID)

   {

     case kpidPath: prop = _subName; break;

     case kpidSize:

@@ -300,7 +299,7 @@
   COM_TRY_BEGIN

   if (numItems == 0)

     return S_OK;

-  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))

     return E_INVALIDARG;

 

   UInt64 currentTotalSize = 0;

@@ -321,7 +320,7 @@
   CMyComPtr<ICompressProgressInfo> progress = lps;

   lps->Init(extractCallback, false);

 

-  for (int i = 0; i < _streams.Size(); i++)

+  FOR_VECTOR (i, _streams)

   {

     lps->InSize = lps->OutSize = currentTotalSize;

     RINOK(lps->SetCur());

@@ -343,7 +342,7 @@
   *stream = 0;

   CMultiStream *streamSpec = new CMultiStream;

   CMyComPtr<ISequentialInStream> streamTemp = streamSpec;

-  for (int i = 0; i < _streams.Size(); i++)

+  FOR_VECTOR (i, _streams)

   {

     CMultiStream::CSubStreamInfo subStreamInfo;

     subStreamInfo.Stream = _streams[i];

@@ -356,10 +355,14 @@
   COM_TRY_END

 }

 

-static IInArchive *CreateArc() { return new CHandler; }

+IMP_CreateArcIn

 

 static CArcInfo g_ArcInfo =

-{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 };

+  { "Split", "001", 0, 0xEA,

+  0, { 0 },

+  0,

+  0,

+  CreateArc };

 

 REGISTER_ARC(Split)

 

diff --git a/CPP/7zip/Archive/StdAfx.h b/CPP/7zip/Archive/StdAfx.h
old mode 100755
new mode 100644
index f56e92f..42a088f
--- a/CPP/7zip/Archive/StdAfx.h
+++ b/CPP/7zip/Archive/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../Common/MyWindows.h"

-#include "../../Common/NewHandler.h"

+#include "../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
old mode 100755
new mode 100644
index e4029e0..e787c16
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -7,6 +7,7 @@
 #include "../../../C/XzEnc.h"

 

 #include "../../Common/ComTry.h"

+#include "../../Common/Defs.h"

 #include "../../Common/IntToString.h"

 

 #include "../ICoder.h"

@@ -40,37 +41,120 @@
 

 struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;

 

+static const wchar_t *k_LZMA2_Name = L"LZMA2";

+

+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()

+  {

+    InSize = 0;

+    OutSize = 0;

+    PhySize = 0;

+

+    NumStreams = 0;

+    NumBlocks = 0;

+

+    UnpackSize_Defined = false;

+  

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

+}

+

+

 class CHandler:

   public IInArchive,

   public IArchiveOpenSeq,

   #ifndef EXTRACT_ONLY

   public IOutArchive,

   public ISetProperties,

-  public COutHandler,

+  public CMultiMethodProps,

   #endif

   public CMyUnknownImp

 {

-  Int64 _startPosition;

-  UInt64 _packSize;

-  UInt64 _unpackSize;

-  UInt64 _numBlocks;

-  AString _methodsString;

-  bool _useSeq;

-  UInt64 _unpackSizeDefined;

-  UInt64 _packSizeDefined;

+  CStatInfo _stat;

+  

+  bool _isArc;

+  bool _needSeekToStart;

+  bool _phySize_Defined;

   

   CMyComPtr<IInStream> _stream;

   CMyComPtr<ISequentialInStream> _seqStream;

 

-  UInt32 _crcSize;

+  UInt32 _filterId;

+  AString _methodsString;

 

   void Init()

   {

-    _crcSize = 4;

-    COutHandler::Init();

+    _filterId = 0;

+    CMultiMethodProps::Init();

   }

 

-  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);

+  HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);

+

+  HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress)

+  {

+    RINOK(progress.Decode(seqInStream, outStream));

+    _stat = progress;

+    _phySize_Defined = true;

+    return S_OK;

+  }

 

 public:

   MY_QUERYINTERFACE_BEGIN2(IInArchive)

@@ -87,7 +171,7 @@
 

   #ifndef EXTRACT_ONLY

   INTERFACE_IOutArchive(;)

-  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);

   #endif

 

   CHandler();

@@ -98,60 +182,60 @@
   Init();

 }

 

-STATPROPSTG kProps[] =

+static const Byte kProps[] =

 {

-  { NULL, kpidSize, VT_UI8},

-  { NULL, kpidPackSize, VT_UI8},

-  { NULL, kpidMethod, VT_BSTR}

+  kpidSize,

+  kpidPackSize,

+  kpidMethod

 };

 

-STATPROPSTG kArcProps[] =

+static const Byte kArcProps[] =

 {

-  { NULL, kpidMethod, VT_BSTR},

-  { NULL, kpidNumBlocks, VT_UI4}

+  kpidMethod,

+  kpidNumStreams,

+  kpidNumBlocks

 };

 

 IMP_IInArchive_Props

 IMP_IInArchive_ArcProps

 

-static char GetHex(Byte value)

+static inline char GetHex(unsigned value)

 {

   return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

 }

 

-static inline void AddHexToString(AString &res, Byte value)

+static inline void AddHexToString(AString &s, Byte value)

 {

-  res += GetHex((Byte)(value >> 4));

-  res += GetHex((Byte)(value & 0xF));

+  s += GetHex(value >> 4);

+  s += GetHex(value & 0xF);

 }

 

-static AString ConvertUInt32ToString(UInt32 value)

+static void AddUInt32ToString(AString &s, UInt32 value)

 {

-  char temp[32];

-  ::ConvertUInt32ToString(value, temp);

-  return temp;

+  char temp[16];

+  ConvertUInt32ToString(value, temp);

+  s += temp;

 }

 

-static AString Lzma2PropToString(int prop)

+static void Lzma2PropToString(AString &s, unsigned prop)

 {

+  char c = 0;

+  UInt32 size;

   if ((prop & 1) == 0)

-    return ConvertUInt32ToString(prop / 2 + 12);

-  AString res;

-  char c;

-

-  UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1);

-

-  if (prop > 17)

-  {

-    res = ConvertUInt32ToString(size >> 10);

-    c = 'm';

-  }

+    size = prop / 2 + 12;

   else

   {

-    res = ConvertUInt32ToString(size);

     c = 'k';

+    size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1);

+    if (prop > 17)

+    {

+      size >>= 10;

+      c = 'm';

+    }

   }

-  return res + c;

+  AddUInt32ToString(s, size);

+  if (c != 0)

+    s += c;

 }

 

 struct CMethodNamePair

@@ -160,11 +244,11 @@
   const char *Name;

 };

 

-static CMethodNamePair g_NamePairs[] =

+static const CMethodNamePair g_NamePairs[] =

 {

   { XZ_ID_Subblock, "SB" },

   { XZ_ID_Delta, "Delta" },

-  { XZ_ID_X86, "x86" },

+  { XZ_ID_X86, "BCJ" },

   { XZ_ID_PPC, "PPC" },

   { XZ_ID_IA64, "IA64" },

   { XZ_ID_ARM, "ARM" },

@@ -175,25 +259,29 @@
 

 static AString GetMethodString(const CXzFilter &f)

 {

-  AString s;

-

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

+  const char *p = NULL;

+  for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)

     if (g_NamePairs[i].Id == f.id)

-      s = g_NamePairs[i].Name;

-  if (s.IsEmpty())

+    {

+      p = g_NamePairs[i].Name;

+      break;

+    }

+  char temp[32];

+  if (!p)

   {

-    char temp[32];

     ::ConvertUInt64ToString(f.id, temp);

-    s = temp;

+    p = temp;

   }

 

+  AString s = p;

+

   if (f.propsSize > 0)

   {

     s += ':';

     if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)

-      s += Lzma2PropToString(f.props[0]);

+      Lzma2PropToString(s, f.props[0]);

     else if (f.id == XZ_ID_Delta && f.propsSize == 1)

-      s += ConvertUInt32ToString((UInt32)f.props[0] + 1);

+      AddUInt32ToString(s, (UInt32)f.props[0] + 1);

     else

     {

       s += '[';

@@ -214,22 +302,22 @@
 

 static const char *kChecks[] =

 {

-  "NoCheck",

-  "CRC32",

-  NULL,

-  NULL,

-  "CRC64",

-  NULL,

-  NULL,

-  NULL,

-  NULL,

-  NULL,

-  "SHA256",

-  NULL,

-  NULL,

-  NULL,

-  NULL,

-  NULL

+    "NoCheck"

+  , "CRC32"

+  , NULL

+  , NULL

+  , "CRC64"

+  , NULL

+  , NULL

+  , NULL

+  , NULL

+  , NULL

+  , "SHA256"

+  , NULL

+  , NULL

+  , NULL

+  , NULL

+  , NULL

 };

 

 static AString GetCheckString(const CXzs &xzs)

@@ -246,7 +334,10 @@
       if (kChecks[i])

         s2 = kChecks[i];

       else

-        s2 = "Check-" + ConvertUInt32ToString((UInt32)i);

+      {

+        s2 = "Check-";

+        AddUInt32ToString(s2, (UInt32)i);

+      }

       AddString(s, s2);

     }

   return s;

@@ -255,12 +346,26 @@
 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

 {

   COM_TRY_BEGIN

-  NWindows::NCOM::CPropVariant prop;

-  switch(propID)

+  NCOM::CPropVariant prop;

+  switch (propID)

   {

-    case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break;

-    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break;

+    case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;

+    case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;

+    case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;

     case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;

+    case kpidErrorFlags:

+    {

+      UInt32 v = 0;

+      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;

+      if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;

+      if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;

+      if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError;

+      if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;

+      if (_stat.DataError) v |= kpv_ErrorFlags_DataError;

+      if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError;

+      prop = v;

+    }

   }

   prop.Detach(value);

   return S_OK;

@@ -273,14 +378,14 @@
   return S_OK;

 }

 

-STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID,  PROPVARIANT *value)

+STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)

 {

   COM_TRY_BEGIN

-  NWindows::NCOM::CPropVariant prop;

-  switch(propID)

+  NCOM::CPropVariant prop;

+  switch (propID)

   {

-    case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break;

-    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;

+    case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break;

     case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;

   }

   prop.Detach(value);

@@ -318,8 +423,73 @@
   ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }

 };

 

-HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)

+

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

+  {

+    case SZ_OK: return S_OK;

+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;

+    case SZ_ERROR_PROGRESS: return E_ABORT;

+    /*

+    case SZ_ERROR_UNSUPPORTED:

+    case SZ_ERROR_CRC:

+    case SZ_ERROR_DATA:

+    case SZ_ERROR_ARCHIVE:

+    case SZ_ERROR_NO_ARCHIVE:

+      return S_FALSE;

+    */

+  }

+  return S_FALSE;

+}

+

+HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)

+{

+  _needSeekToStart = true;

+

+  {

+    CXzStreamFlags st;

+    CSeqInStreamWrap inStreamWrap(inStream);

+    SRes res = Xz_ReadHeader(&st, &inStreamWrap.p);

+    if (res != SZ_OK)

+      return SRes_to_Open_HRESULT(res);

+

+    {

+      CXzBlock block;

+      Bool isIndex;

+      UInt32 headerSizeRes;

+      SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);

+      if (res2 == SZ_OK && !isIndex)

+      {

+        unsigned numFilters = XzBlock_GetNumFilters(&block);

+        for (unsigned i = 0; i < numFilters; i++)

+          AddString(_methodsString, GetMethodString(block.filters[i]));

+      }

+    }

+  }

+

+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize));

+  RINOK(callback->SetTotal(NULL, &_stat.PhySize));

+

   CSeekInStreamWrap inStreamImp(inStream);

 

   CLookToRead lookStream;

@@ -328,72 +498,49 @@
   LookToRead_Init(&lookStream);

 

   COpenCallbackWrap openWrap(callback);

-  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));

-  RINOK(callback->SetTotal(NULL, &_packSize));

 

   CXzsCPP xzs;

-  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc);

+  Int64 startPosition;

+  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc);

+  if (res == SZ_ERROR_PROGRESS)

+    return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;

+  /*

   if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)

     res = SZ_OK;

-  if (res == SZ_OK)

+  */

+  if (res == SZ_OK && startPosition == 0)

   {

-    _packSize -= _startPosition;

-    _unpackSize = Xzs_GetUnpackSize(&xzs.p);

-    _unpackSizeDefined = _packSizeDefined = true;

-    _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p);

+    _phySize_Defined = true;

 

-    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));

-    CXzStreamFlags st;

-    CSeqInStreamWrap inStreamWrap(inStream);

-    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);

+    _stat.OutSize = Xzs_GetUnpackSize(&xzs.p);

+    _stat.UnpackSize_Defined = true;

 

-    if (res2 == SZ_OK)

-    {

-      CXzBlock block;

-      Bool isIndex;

-      UInt32 headerSizeRes;

-      res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);

-      if (res2 == SZ_OK && !isIndex)

-      {

-        int numFilters = XzBlock_GetNumFilters(&block);

-        for (int i = 0; i < numFilters; i++)

-          AddString(_methodsString, GetMethodString(block.filters[i]));

-      }

-    }

+    _stat.NumStreams = xzs.p.num;

+    _stat.NumStreams_Defined = true;

+    

+    _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);

+    _stat.NumBlocks_Defined = true;

+

     AddString(_methodsString, GetCheckString(xzs.p));

   }

-

-  if (res != SZ_OK || _startPosition != 0)

+  else

   {

-    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));

-    CXzStreamFlags st;

-    CSeqInStreamWrap inStreamWrap(inStream);

-    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);

-    if (res2 == SZ_OK)

-    {

-      res = res2;

-      _startPosition = 0;

-      _useSeq = True;

-      _unpackSizeDefined = _packSizeDefined = false;

-    }

+    res = SZ_OK;

   }

-  if (res == SZ_ERROR_NO_ARCHIVE)

-    return S_FALSE;

-  RINOK(SResToHRESULT(res));

+  RINOK(SRes_to_Open_HRESULT(res));

   _stream = inStream;

   _seqStream = inStream;

+  _isArc = true;

   return S_OK;

 }

 

 STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)

 {

   COM_TRY_BEGIN

-  try

   {

     Close();

-    return Open2(inStream, callback);

+    return Open2(inStream, /* 0, */ callback);

   }

-  catch(...) { return S_FALSE; }

   COM_TRY_END

 }

 

@@ -401,15 +548,21 @@
 {

   Close();

   _seqStream = stream;

+  _isArc = true;

+  _needSeekToStart = false;

   return S_OK;

 }

 

 STDMETHODIMP CHandler::Close()

 {

-  _numBlocks = 0;

-  _useSeq = true;

-  _unpackSizeDefined = _packSizeDefined = false;

-  _methodsString.Empty();

+  _stat.Clear();

+

+  _isArc = false;

+  _needSeekToStart = false;

+

+  _phySize_Defined = false;

+  

+   _methodsString.Empty();

   _stream.Release();

   _seqStream.Release();

   return S_OK;

@@ -439,7 +592,11 @@
   Byte *InBuf;

   Byte *OutBuf;

   CXzUnpacker p;

-  CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}

+  

+  CXzUnpackerCPP(): InBuf(0), OutBuf(0)

+  {

+    XzUnpacker_Construct(&p, &g_Alloc);

+  }

   ~CXzUnpackerCPP()

   {

     XzUnpacker_Free(&p);

@@ -448,16 +605,141 @@
   }

 };

 

+HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream)

+{

+  const size_t kInBufSize = 1 << 15;

+  const size_t kOutBufSize = 1 << 21;

+

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

+

+  UInt32 inSize = 0;

+  SizeT inPos = 0;

+  SizeT outPos = 0;

+

+  for (;;)

+  {

+    if (inPos == inSize)

+    {

+      inPos = inSize = 0;

+      RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize));

+    }

+

+    SizeT inLen = inSize - inPos;

+    SizeT outLen = kOutBufSize - outPos;

+    ECoderStatus status;

+    

+    SRes res = XzUnpacker_Code(&xzu.p,

+        xzu.OutBuf + outPos, &outLen,

+        xzu.InBuf + inPos, &inLen,

+        (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);

+

+    inPos += inLen;

+    outPos += outLen;

+

+    InSize += inLen;

+    OutSize += outLen;

+

+    DecodeRes = res;

+

+    bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK);

+

+    if (outStream)

+    {

+      if (outPos == kOutBufSize || finished)

+      {

+        if (outPos != 0)

+        {

+          RINOK(WriteStream(outStream, xzu.OutBuf, outPos));

+          outPos = 0;

+        }

+      }

+    }

+    else

+      outPos = 0;

+    

+    RINOK(Progress());

+    

+    if (finished)

+    {

+      PhySize = InSize;

+      NumStreams = xzu.p.numStartedStreams;

+      if (NumStreams > 0)

+        IsArc = true;

+      NumBlocks = xzu.p.numTotalBlocks;

+

+      UnpackSize_Defined = true;

+      NumStreams_Defined = true;

+      NumBlocks_Defined = true;

+

+      UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p);

+

+      if (res == SZ_OK)

+      {

+        if (status == CODER_STATUS_NEEDS_MORE_INPUT)

+        {

+          extraSize = 0;

+          if (!XzUnpacker_IsStreamWasFinished(&xzu.p))

+          {

+            // finished at padding bytes, but padding is not aligned for 4

+            UnexpectedEnd = true;

+            res = SZ_ERROR_DATA;

+          }

+        }

+        else // status == CODER_STATUS_NOT_FINISHED

+          res = SZ_ERROR_DATA;

+      }

+      else if (res == SZ_ERROR_NO_ARCHIVE)

+      {

+        if (InSize == extraSize)

+          IsArc = false;

+        else

+        {

+          if (extraSize != 0 || inPos != inSize)

+          {

+            DataAfterEnd = true;

+            res = SZ_OK;

+          }

+        }

+      }

+

+      DecodeRes = res;

+      PhySize -= extraSize;

+

+      switch (res)

+      {

+        case SZ_OK: break;

+        case SZ_ERROR_NO_ARCHIVE: IsArc = false; break;

+        case SZ_ERROR_ARCHIVE: HeadersError = true; break;

+        case SZ_ERROR_UNSUPPORTED: Unsupported = true; break;

+        case SZ_ERROR_CRC: CrcError = true; break;

+        case SZ_ERROR_DATA: DataError = true; break;

+        default: DataError = true; break;

+      }

+

+      break;

+    }

+  }

+

+  return S_OK;

+}

+

 STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

     Int32 testMode, IArchiveExtractCallback *extractCallback)

 {

   COM_TRY_BEGIN

   if (numItems == 0)

     return S_OK;

-  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))

     return E_INVALIDARG;

 

-  extractCallback->SetTotal(_packSize);

+  extractCallback->SetTotal(_stat.PhySize);

   UInt64 currentTotalPacked = 0;

   RINOK(extractCallback->SetCompleted(&currentTotalPacked));

   CMyComPtr<ISequentialOutStream> realOutStream;

@@ -472,109 +754,46 @@
 

   extractCallback->PrepareOperation(askMode);

 

-  if (_stream)

+  CVirtProgress_To_LocalProgress vp;

+  vp.lps = new CLocalProgress;

+  vp.progress = vp.lps;

+  vp.lps->Init(extractCallback, true);

+

+

+  if (_needSeekToStart)

   {

-    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

+    if (!_stream)

+      return E_FAIL;

+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));

   }

+  else

+    _needSeekToStart = true;

 

-  CLocalProgress *lps = new CLocalProgress;

-  CMyComPtr<ICompressProgressInfo> progress = lps;

-  lps->Init(extractCallback, true);

-

-  CCompressProgressWrap progressWrap(progress);

-

-  SRes res;

-

-  const UInt32 kInBufSize = 1 << 15;

-  const UInt32 kOutBufSize = 1 << 21;

-

-  UInt32 inPos = 0;

-  UInt32 inSize = 0;

-  UInt32 outPos = 0;

-  CXzUnpackerCPP xzu;

-  res = XzUnpacker_Create(&xzu.p, &g_Alloc);

-  if (res == SZ_OK)

-  {

-    xzu.InBuf = (Byte *)MyAlloc(kInBufSize);

-    xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);

-    if (xzu.InBuf == 0 || xzu.OutBuf == 0)

-      res = SZ_ERROR_MEM;

-  }

-  if (res == SZ_OK)

-  for (;;)

-  {

-    if (inPos == inSize)

-    {

-      inPos = inSize = 0;

-      RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize));

-    }

-

-    SizeT inLen = inSize - inPos;

-    SizeT outLen = kOutBufSize - outPos;

-    ECoderStatus status;

-    res = XzUnpacker_Code(&xzu.p,

-        xzu.OutBuf + outPos, &outLen,

-        xzu.InBuf + inPos, &inLen,

-        (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);

-

-    // printf("\n_inPos = %6d  inLen = %5d, outLen = %5d", inPos, inLen, outLen);

-

-    inPos += (UInt32)inLen;

-    outPos += (UInt32)outLen;

-    lps->InSize += inLen;

-    lps->OutSize += outLen;

-

-    bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK);

-

-    if (outPos == kOutBufSize || finished)

-    {

-      if (realOutStream && outPos > 0)

-      {

-        RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos));

-      }

-      outPos = 0;

-    }

-    if (finished)

-    {

-      _packSize = lps->InSize;

-      _unpackSize = lps->OutSize;

-      _packSizeDefined = _unpackSizeDefined = true;

-      if (res == SZ_OK)

-      {

-        if (status == CODER_STATUS_NEEDS_MORE_INPUT)

-        {

-          if (XzUnpacker_IsStreamWasFinished(&xzu.p))

-            _packSize -= xzu.p.padSize;

-          else

-            res = SZ_ERROR_DATA;

-        }

-        else

-          res = SZ_ERROR_DATA;

-      }

-      break;

-    }

-    RINOK(lps->SetCur());

-  }

+  RINOK(Decode2(_seqStream, realOutStream, vp));

 

   Int32 opRes;

-  switch(res)

-  {

-    case SZ_OK:

-      opRes = NExtract::NOperationResult::kOK; break;

-    case SZ_ERROR_UNSUPPORTED:

-      opRes = NExtract::NOperationResult::kUnSupportedMethod; break;

-    case SZ_ERROR_CRC:

-      opRes = NExtract::NOperationResult::kCRCError; break;

-    case SZ_ERROR_DATA:

-    case SZ_ERROR_ARCHIVE:

-    case SZ_ERROR_NO_ARCHIVE:

-      opRes = NExtract::NOperationResult::kDataError; break;

-    default:

-      return SResToHRESULT(res);

-  }

+

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

+

   realOutStream.Release();

-  RINOK(extractCallback->SetOperationResult(opRes));

-  return S_OK;

+  return extractCallback->SetOperationResult(opRes);

   COM_TRY_END

 }

 

@@ -619,8 +838,8 @@
 

   if (IntToBool(newData))

   {

+    UInt64 size;

     {

-      UInt64 size;

       NCOM::CPropVariant prop;

       RINOK(updateCallback->GetProperty(0, kpidSize, &prop));

       if (prop.vt != VT_UI8)

@@ -632,24 +851,28 @@
     CLzma2EncProps lzma2Props;

     Lzma2EncProps_Init(&lzma2Props);

 

-    lzma2Props.lzmaProps.level = _level;

+    lzma2Props.lzmaProps.level = GetLevel();

 

     CMyComPtr<ISequentialInStream> fileInStream;

     RINOK(updateCallback->GetStream(0, &fileInStream));

 

     CSeqInStreamWrap seqInStream(fileInStream);

 

-    for (int i = 0; i < _methods.Size(); i++)

+    {

+      NCOM::CPropVariant prop = (UInt64)size;

+      RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));

+    }

+

+    FOR_VECTOR (i, _methods)

     {

       COneMethodInfo &m = _methods[i];

-      SetCompressionMethod2(m

+      SetGlobalLevelAndThreads(m

       #ifndef _7ZIP_ST

       , _numThreads

       #endif

       );

-      if (m.IsLzma())

       {

-        for (int j = 0; j < m.Props.Size(); j++)

+        FOR_VECTOR (j, m.Props)

         {

           const CProp &prop = m.Props[j];

           RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));

@@ -666,7 +889,40 @@
     lps->Init(updateCallback, true);

 

     CCompressProgressWrap progressWrap(progress);

-    SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);

+    CXzProps xzProps;

+    CXzFilterProps filter;

+    XzProps_Init(&xzProps);

+    XzFilterProps_Init(&filter);

+    xzProps.lzma2Props = &lzma2Props;

+    xzProps.filterProps = (_filterId != 0 ? &filter : NULL);

+    switch (_crcSize)

+    {

+      case  0: xzProps.checkId = XZ_CHECK_NO; break;

+      case  4: xzProps.checkId = XZ_CHECK_CRC32; break;

+      case  8: xzProps.checkId = XZ_CHECK_CRC64; break;

+      case 32: xzProps.checkId = XZ_CHECK_SHA256; break;

+      default: return E_INVALIDARG;

+    }

+    filter.id = _filterId;

+    if (_filterId == XZ_ID_Delta)

+    {

+      bool deltaDefined = false;

+      FOR_VECTOR (j, _filterMethod.Props)

+      {

+        const CProp &prop = _filterMethod.Props[j];

+        if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)

+        {

+          UInt32 delta = (UInt32)prop.Value.ulVal;

+          if (delta < 1 || delta > 256)

+            return E_INVALIDARG;

+          filter.delta = delta;

+          deltaDefined = true;

+        }

+      }

+      if (!deltaDefined)

+        return E_INVALIDARG;

+    }

+    SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);

     if (res == SZ_OK)

       return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);

     return SResToHRESULT(res);

@@ -674,33 +930,61 @@
   if (indexInArchive != 0)

     return E_INVALIDARG;

   if (_stream)

-    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

-  return NCompress::CopyStream(_stream, outStream, 0);

+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));

+  return NCompress::CopyStream(_stream, outStream, NULL);

 }

 

-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)

 {

   COM_TRY_BEGIN

-  BeforeSetProperty();

-  for (int i = 0; i < numProps; i++)

+  Init();

+  for (UInt32 i = 0; i < numProps; i++)

   {

     RINOK(SetProperty(names[i], values[i]));

   }

+

+  if (!_filterMethod.MethodName.IsEmpty())

+  {

+    unsigned k;

+    for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++)

+    {

+      const CMethodNamePair &pair = g_NamePairs[k];

+      if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name))

+      {

+        _filterId = pair.Id;

+        break;

+      }

+    }

+    if (k == ARRAY_SIZE(g_NamePairs))

+      return E_INVALIDARG;

+  }

+

+  _methods.DeleteFrontal(GetNumEmptyMethods());

+  if (_methods.Size() > 1)

+    return E_INVALIDARG;

+  if (_methods.Size() == 1)

+  {

+    UString &methodName = _methods[0].MethodName;

+    if (methodName.IsEmpty())

+      methodName = k_LZMA2_Name;

+    else if (!methodName.IsEqualToNoCase(k_LZMA2_Name))

+      return E_INVALIDARG;

+  }

   return S_OK;

   COM_TRY_END

 }

 

 #endif

 

-static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; }

-#ifndef EXTRACT_ONLY

-static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; }

-#else

-#define CreateArcOut 0

-#endif

+IMP_CreateArcIn

+IMP_CreateArcOut

 

 static CArcInfo g_ArcInfo =

-  { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut };

+  { "xz", "xz txz", "* .tar", 0xC,

+  6, { 0xFD, '7' , 'z', 'X', 'Z', 0 },

+  0,

+  NArcInfoFlags::kKeepName,

+  REF_CreateArc_Pair };

 

 REGISTER_ARC(xz)

 

diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
old mode 100755
new mode 100644
index 0284903..1012b16
--- a/CPP/7zip/Asm.mak
+++ b/CPP/7zip/Asm.mak
@@ -1,3 +1,4 @@
+!IFDEF ASM_OBJS

 !IF "$(CPU)" == "ARM"

 $(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm

 	$(COMPL_ASM)

@@ -5,3 +6,4 @@
 $(ASM_OBJS): ../../../../Asm/x86/$(*B).asm

 	$(COMPL_ASM)

 !ENDIF

+!ENDIF

diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
old mode 100755
new mode 100644
index 2b9543f..f96ad74
--- 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" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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 BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -52,7 +52,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98

 # SUBTRACT LINK32 /pdb:none

 

 !ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

@@ -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" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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 BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -77,7 +77,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept

 

 !ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

 

@@ -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" /D "_NO_CRYPTO" /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 BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -103,7 +103,7 @@
 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98

 # SUBTRACT BASE LINK32 /pdb:none

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98

 # SUBTRACT LINK32 /pdb:none

 

 !ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

@@ -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" /D "_NO_CRYPTO" /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 BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -129,7 +129,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept

 

 !ENDIF 

 

@@ -176,6 +176,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\UI\Console\HashCon.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\HashCon.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\UI\Console\List.cpp

 # End Source File

 # Begin Source File

@@ -185,6 +193,7 @@
 # Begin Source File

 

 SOURCE=..\..\UI\Console\Main.cpp

+# ADD CPP /D "PROG_VARIANT_R"

 # End Source File

 # Begin Source File

 

@@ -269,6 +278,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\Common\CrcReg.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\Common\Defs.h

 # End Source File

 # Begin Source File

@@ -337,6 +350,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\Common\Sha256Reg.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\Common\StdInStream.cpp

 # End Source File

 # Begin Source File

@@ -387,6 +404,10 @@
 

 SOURCE=..\..\..\Common\Wildcard.h

 # End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\XzCrc64Reg.cpp

+# End Source File

 # End Group

 # Begin Group "Windows"

 

@@ -409,11 +430,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\Error.cpp

+SOURCE=..\..\..\Windows\ErrorMsg.cpp

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\Error.h

+SOURCE=..\..\..\Windows\ErrorMsg.h

 # End Source File

 # Begin Source File

 

@@ -441,6 +462,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\Windows\FileLink.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\Windows\FileMapping.h

 # End Source File

 # Begin Source File

@@ -473,11 +498,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\PropVariantConversions.cpp

+SOURCE=..\..\..\Windows\PropVariantConv.cpp

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\PropVariantConversions.h

+SOURCE=..\..\..\Windows\PropVariantConv.h

 # End Source File

 # Begin Source File

 

@@ -501,11 +526,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\Time.cpp

+SOURCE=..\..\..\Windows\TimeUtils.cpp

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\Time.h

+SOURCE=..\..\..\Windows\TimeUtils.h

 # End Source File

 # End Group

 # Begin Group "7zip Common"

@@ -633,6 +658,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Common\PropId.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Common\RegisterArc.h

 # End Source File

 # Begin Source File

@@ -665,6 +694,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Common\UniqBlocks.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\UniqBlocks.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Common\VirtThread.cpp

 # End Source File

 # Begin Source File

@@ -791,14 +828,6 @@
 

 SOURCE=..\..\Compress\RangeCoderBit.h

 # End Source File

-# Begin Source File

-

-SOURCE=..\..\Compress\RangeCoderBitTree.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\Compress\RangeCoderOpt.h

-# End Source File

 # End Group

 # Begin Group "Archive"

 

@@ -1077,6 +1106,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\UI\Common\HashCalc.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\HashCalc.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\UI\Common\LoadCodecs.cpp

 # End Source File

 # Begin Source File

@@ -1167,14 +1204,6 @@
 

 SOURCE=..\..\UI\Common\UpdateProduce.h

 # End Source File

-# Begin Source File

-

-SOURCE=..\..\UI\Common\WorkDir.cpp

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\UI\Common\WorkDir.h

-# End Source File

 # End Group

 # Begin Group "7-zip"

 

@@ -1296,6 +1325,30 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\XzCrc64Opt.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\XzDec.c

 

 !IF  "$(CFG)" == "Alone - Win32 Release"

@@ -1412,6 +1465,58 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\..\C\Aes.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\Aes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\AesOpt.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\Alloc.c

 # SUBTRACT CPP /YX /Yc /Yu

 # End Source File

@@ -1660,5 +1765,37 @@
 SOURCE=..\..\..\..\C\Types.h

 # End Source File

 # End Group

+# Begin Group "Crypto"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAesRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\RandGen.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\RandGen.h

+# End Source File

+# End Group

 # End Target

 # End Project

diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsw b/CPP/7zip/Bundles/Alone7z/Alone.dsw
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/Bundles/Alone7z/StdAfx.h
+++ b/CPP/7zip/Bundles/Alone7z/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
old mode 100755
new mode 100644
index 3132895..c68a42e
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -1,52 +1,43 @@
 PROG = 7zr.exe

 MY_CONSOLE = 1

-CFLAGS = $(CFLAGS) -I ../../../ \

-  -D_NO_CRYPTO \

+CFLAGS = $(CFLAGS) -DPROG_VARIANT_R

 

 !IFNDEF UNDER_CE

 CFLAGS = $(CFLAGS) -DWIN_LONG_PATH

 !ENDIF

 

-CONSOLE_OBJS = \

-  $O\BenchCon.obj \

-  $O\ConsoleClose.obj \

-  $O\ExtractCallbackConsole.obj \

-  $O\List.obj \

-  $O\Main.obj \

-  $O\MainAr.obj \

-  $O\OpenCallbackConsole.obj \

-  $O\PercentPrinter.obj \

-  $O\UpdateCallbackConsole.obj \

-  $O\UserInputUtils.obj \

-

 COMMON_OBJS = \

   $O\CommandLineParser.obj \

   $O\CRC.obj \

+  $O\CrcReg.obj \

   $O\IntToString.obj \

   $O\ListFileUtils.obj \

   $O\NewHandler.obj \

   $O\StdInStream.obj \

   $O\StdOutStream.obj \

   $O\MyString.obj \

+  $O\Sha256Reg.obj \

   $O\StringConvert.obj \

   $O\StringToInt.obj \

   $O\UTFConvert.obj \

   $O\MyVector.obj \

   $O\Wildcard.obj \

+  $O\XzCrc64Reg.obj \

 

 WIN_OBJS = \

   $O\DLL.obj \

-  $O\Error.obj \

+  $O\ErrorMsg.obj \

   $O\FileDir.obj \

   $O\FileFind.obj \

   $O\FileIO.obj \

+  $O\FileLink.obj \

   $O\FileName.obj \

   $O\MemoryLock.obj \

   $O\PropVariant.obj \

-  $O\PropVariantConversions.obj \

+  $O\PropVariantConv.obj \

   $O\Synchronization.obj \

   $O\System.obj \

-  $O\Time.obj \

+  $O\TimeUtils.obj \

 

 7ZIP_COMMON_OBJS = \

   $O\CreateCoder.obj \

@@ -63,33 +54,13 @@
   $O\OffsetStream.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

+  $O\PropId.obj \

   $O\StreamBinder.obj \

   $O\StreamObjects.obj \

   $O\StreamUtils.obj \

+  $O\UniqBlocks.obj \

   $O\VirtThread.obj \

 

-UI_COMMON_OBJS = \

-  $O\ArchiveCommandLine.obj \

-  $O\ArchiveExtractCallback.obj \

-  $O\ArchiveOpenCallback.obj \

-  $O\Bench.obj \

-  $O\DefaultName.obj \

-  $O\EnumDirItems.obj \

-  $O\Extract.obj \

-  $O\ExtractingFilePath.obj \

-  $O\LoadCodecs.obj \

-  $O\OpenArchive.obj \

-  $O\PropIDUtils.obj \

-  $O\SetProperties.obj \

-  $O\SortUtils.obj \

-  $O\TempFiles.obj \

-  $O\Update.obj \

-  $O\UpdateAction.obj \

-  $O\UpdateCallback.obj \

-  $O\UpdatePair.obj \

-  $O\UpdateProduce.obj \

-  $O\WorkDir.obj \

-

 AR_OBJS = \

   $O\LzmaHandler.obj \

   $O\SplitHandler.obj \

@@ -144,6 +115,13 @@
   $O\LzmaEncoder.obj \

   $O\LzmaRegister.obj \

 

+CRYPTO_OBJS = \

+  $O\7zAes.obj \

+  $O\7zAesRegister.obj \

+  $O\MyAes.obj \

+  $O\MyAesReg.obj \

+  $O\RandGen.obj \

+

 C_OBJS = \

   $O\7zStream.obj \

   $O\Alloc.obj \

@@ -160,54 +138,17 @@
   $O\LzmaEnc.obj \

   $O\MtCoder.obj \

   $O\Sha256.obj \

+  $O\Sort.obj \

   $O\Threads.obj \

   $O\Xz.obj \

-  $O\XzCrc64.obj \

   $O\XzDec.obj \

   $O\XzEnc.obj \

   $O\XzIn.obj \

 

+!include "../../UI/Console/Console.mak"

+

+!include "../../Aes.mak"

 !include "../../Crc.mak"

+!include "../../Crc64.mak"

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(CONSOLE_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-  $(UI_COMMON_OBJS) \

-  $(AR_OBJS) \

-  $(AR_COMMON_OBJS) \

-  $(7Z_OBJS) \

-  $(COMPRESS_OBJS) \

-  $(C_OBJS) \

-  $(ASM_OBJS) \

-  $O\resource.res

-

-

-!include "../../../Build.mak"

-

-$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp

-	$(COMPL)

-

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

-$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp

-	$(COMPL)

-$(AR_OBJS): ../../Archive/$(*B).cpp

-	$(COMPL)

-$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

-	$(COMPL)

-

-$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

-	$(COMPL)

-$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

-	$(COMPL_O2)

-$(C_OBJS): ../../../../C/$(*B).c

-	$(COMPL_O2)

-

-!include "../../Asm.mak"

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc
old mode 100755
new mode 100644
index 0f90dfb..3be08c9
--- a/CPP/7zip/Bundles/Alone7z/resource.rc
+++ b/CPP/7zip/Bundles/Alone7z/resource.rc
@@ -1,3 +1,3 @@
-#include "../../MyVersionInfo.rc"

+#include "../../../../C/7zVersion.rc"

 

-MY_VERSION_INFO_APP("7-Zip Standalone Console", "7zr")

+MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr")

diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
+++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
old mode 100755
new mode 100644
index 34a9bb3..0b2f581
--- a/CPP/7zip/Bundles/Format7zExtractR/makefile
+++ b/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -1,11 +1,12 @@
 PROG = 7zxr.dll

 DEF_FILE = ../../Archive/Archive2.def

-CFLAGS = $(CFLAGS) -I ../../../ \

+CFLAGS = $(CFLAGS) \

   -DEXTRACT_ONLY \

   -D_NO_CRYPTO

 

 COMMON_OBJS = \

   $O\CRC.obj \

+  $O\CrcReg.obj \

   $O\IntToString.obj \

   $O\NewHandler.obj \

   $O\MyString.obj \

@@ -30,6 +31,7 @@
   $O\MethodProps.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

+  $O\PropId.obj \

   $O\StreamBinder.obj \

   $O\StreamObjects.obj \

   $O\StreamUtils.obj \

@@ -92,41 +94,4 @@
 

 !include "../../Crc.mak"

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(CONSOLE_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-  $(AR_OBJS) \

-  $(AR_COMMON_OBJS) \

-  $(7Z_OBJS) \

-  $(COMPRESS_OBJS) \

-  $(C_OBJS) \

-  $(ASM_OBJS) \

-  $O\resource.res

-

-

-!include "../../../Build.mak"

-

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

-$(AR_OBJS): ../../Archive/$(*B).cpp

-	$(COMPL)

-$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

-	$(COMPL)

-

-$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

-	$(COMPL)

-

-$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

-	$(COMPL_O2)

-

-$(C_OBJS): ../../../../C/$(*B).c

-	$(COMPL_O2)

-

-!include "../../Asm.mak"

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
old mode 100755
new mode 100644
index 652c4a1..dac02a6
--- a/CPP/7zip/Bundles/Format7zExtractR/resource.rc
+++ b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
@@ -1,5 +1,5 @@
-#include "../../MyVersionInfo.rc"

+#include "../../../../C/7zVersion.rc"

 

-MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr")

+MY_VERSION_INFO_DLL("7z Extracting Reduced Standalone Plugin", "7zxr")

 

 101  ICON  "../../Archive/Icons/7z.ico"

diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/Bundles/Format7zR/StdAfx.h
+++ b/CPP/7zip/Bundles/Format7zR/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
old mode 100755
new mode 100644
index 65d1f65..0e885c0
--- a/CPP/7zip/Bundles/Format7zR/makefile
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -1,10 +1,11 @@
 PROG = 7zra.dll

 DEF_FILE = ../../Archive/Archive2.def

-CFLAGS = $(CFLAGS) -I ../../../ \

+CFLAGS = $(CFLAGS) \

   -D_NO_CRYPTO

 

 COMMON_OBJS = \

   $O\CRC.obj \

+  $O\CrcReg.obj \

   $O\IntToString.obj \

   $O\NewHandler.obj \

   $O\MyString.obj \

@@ -17,6 +18,7 @@
   $O\FileDir.obj \

   $O\FileFind.obj \

   $O\FileIO.obj \

+  $O\FileName.obj \

   $O\PropVariant.obj \

   $O\Synchronization.obj \

   $O\System.obj \

@@ -33,9 +35,11 @@
   $O\MethodProps.obj \

   $O\OutBuffer.obj \

   $O\ProgressUtils.obj \

+  $O\PropId.obj \

   $O\StreamBinder.obj \

   $O\StreamObjects.obj \

   $O\StreamUtils.obj \

+  $O\UniqBlocks.obj \

   $O\VirtThread.obj \

 

 AR_OBJS = \

@@ -109,41 +113,4 @@
 

 !include "../../Crc.mak"

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(CONSOLE_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-  $(AR_OBJS) \

-  $(AR_COMMON_OBJS) \

-  $(7Z_OBJS) \

-  $(COMPRESS_OBJS) \

-  $(C_OBJS) \

-  $(ASM_OBJS) \

-  $O\resource.res

-

-

-!include "../../../Build.mak"

-

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

-$(AR_OBJS): ../../Archive/$(*B).cpp

-	$(COMPL)

-$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

-	$(COMPL)

-

-$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

-	$(COMPL)

-

-$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

-	$(COMPL_O2)

-

-$(C_OBJS): ../../../../C/$(*B).c

-	$(COMPL_O2)

-

-!include "../../Asm.mak"

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/Format7zR/resource.rc b/CPP/7zip/Bundles/Format7zR/resource.rc
old mode 100755
new mode 100644
index b67ef0c..262125c
--- a/CPP/7zip/Bundles/Format7zR/resource.rc
+++ b/CPP/7zip/Bundles/Format7zR/resource.rc
@@ -1,5 +1,5 @@
-#include "../../MyVersionInfo.rc"

+#include "../../../../C/7zVersion.rc"

 

-MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr")

+MY_VERSION_INFO_DLL("7z Reduced Standalone Plugin", "7zr")

 

 101  ICON  "../../Archive/Icons/7z.ico"

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
old mode 100755
new mode 100644
index 1f759b4..677fb8f
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -49,6 +49,8 @@
 {

   kHelp1 = 0,

   kHelp2,

+  kMethod,

+  kLevel,

   kAlgo,

   kDict,

   kFb,

@@ -67,25 +69,25 @@
 

 static const CSwitchForm kSwitchForms[] =

 {

-  { L"?",  NSwitchType::kSimple, false },

-  { L"H",  NSwitchType::kSimple, false },

-  { L"A", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"D", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"MC", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },

-  { L"MT", NSwitchType::kUnLimitedPostString, false, 0 },

-  { L"EOS", NSwitchType::kSimple, false },

-  { L"SI",  NSwitchType::kSimple, false },

-  { L"SO",  NSwitchType::kSimple, false },

-  { L"F86",  NSwitchType::kPostChar, false, 0, 0, L"+" }

+  { "?",  NSwitchType::kSimple, false },

+  { "H",  NSwitchType::kSimple, false },

+  { "MM", NSwitchType::kString, false, 1 },

+  { "X", NSwitchType::kString, false, 1 },

+  { "A", NSwitchType::kString, false, 1 },

+  { "D", NSwitchType::kString, false, 1 },

+  { "FB", NSwitchType::kString, false, 1 },

+  { "MC", NSwitchType::kString, false, 1 },

+  { "LC", NSwitchType::kString, false, 1 },

+  { "LP", NSwitchType::kString, false, 1 },

+  { "PB", NSwitchType::kString, false, 1 },

+  { "MF", NSwitchType::kString, false, 1 },

+  { "MT", NSwitchType::kString, false, 0 },

+  { "EOS", NSwitchType::kSimple, false },

+  { "SI",  NSwitchType::kSimple, false },

+  { "SO",  NSwitchType::kSimple, false },

+  { "F86",  NSwitchType::kChar, false, 0, "+" }

 };

 

-static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);

-

 static void PrintMessage(const char *s)

 {

   fputs(s, stderr);

@@ -134,19 +136,14 @@
 static bool GetNumber(const wchar_t *s, UInt32 &value)

 {

   value = 0;

-  if (MyStringLen(s) == 0)

+  if (*s == 0)

     return false;

   const wchar_t *end;

-  UInt64 res = ConvertStringToUInt64(s, &end);

-  if (*end != L'\0')

-    return false;

-  if (res > 0xFFFFFFFF)

-    return false;

-  value = UInt32(res);

-  return true;

+  value = ConvertStringToUInt32(s, &end);

+  return *end == 0;

 }

 

-static void ParseUInt32(const CParser &parser, int index, UInt32 &res)

+static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)

 {

   if (parser[index].ThereIs)

     if (!GetNumber(parser[index].PostStrings[0], res))

@@ -176,7 +173,8 @@
 

   UStringVector commandStrings;

   WriteArgumentsToStringList(numArgs, args, commandStrings);

-  CParser parser(kNumSwitches);

+  

+  CParser parser(ARRAY_SIZE(kSwitchForms));

   try

   {

     parser.ParseStrings(kSwitchForms, commandStrings);

@@ -186,33 +184,50 @@
     IncorrectCommand();

   }

 

-  if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)

+  if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)

   {

     PrintHelp();

     return 0;

   }

   const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

 

-  int paramIndex = 0;

+  unsigned paramIndex = 0;

   if (paramIndex >= nonSwitchStrings.Size())

     IncorrectCommand();

   const UString &command = nonSwitchStrings[paramIndex++];

 

+  CObjectVector<CProperty> props;

   bool dictDefined = false;

-  UInt32 dict = (UInt32)-1;

-  if(parser[NKey::kDict].ThereIs)

+  UInt32 dict = (UInt32)(Int32)-1;

+  if (parser[NKey::kDict].ThereIs)

   {

     UInt32 dicLog;

-    if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog))

+    const UString &s = parser[NKey::kDict].PostStrings[0];

+    if (!GetNumber(s, dicLog))

       IncorrectCommand();

     dict = 1 << dicLog;

     dictDefined = true;

+    CProperty prop;

+    prop.Name = L"d";

+    prop.Value = s;

+    props.Add(prop);

+  }

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

   }

   UString mf = L"BT4";

   if (parser[NKey::kMatchFinder].ThereIs)

     mf = parser[NKey::kMatchFinder].PostStrings[0];

 

-  UInt32 numThreads = (UInt32)-1;

+  UInt32 numThreads = (UInt32)(Int32)-1;

 

   #ifndef _7ZIP_ST

   if (parser[NKey::kMultiThread].ThereIs)

@@ -224,10 +239,25 @@
     else

       if (!GetNumber(s, numThreads))

         IncorrectCommand();

+    CProperty prop;

+    prop.Name = L"mt";

+    prop.Value = s;

+    props.Add(prop);

   }

   #endif

 

-  if (command.CompareNoCase(L"b") == 0)

+  if (parser[NKey::kMethod].ThereIs)

+  {

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

+  }

+

+  if (MyStringCompareNoCase(command, L"b") == 0)

   {

     const UInt32 kNumDefaultItereations = 1;

     UInt32 numIterations = kNumDefaultItereations;

@@ -236,16 +266,25 @@
         if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))

           numIterations = kNumDefaultItereations;

     }

-    return LzmaBenchCon(stderr, numIterations, numThreads, dict);

+    HRESULT res = BenchCon(props, numIterations, stderr);

+    if (res != S_OK)

+    {

+      if (res != E_ABORT)

+      {

+        PrintMessage("Benchmark Error");

+        return 1;

+      }

+    }

+    return 0;

   }

 

-  if (numThreads == (UInt32)-1)

+  if (numThreads == (UInt32)(Int32)-1)

     numThreads = 1;

 

   bool encodeMode = false;

-  if (command.CompareNoCase(L"e") == 0)

+  if (MyStringCompareNoCase(command, L"e") == 0)

     encodeMode = true;

-  else if (command.CompareNoCase(L"d") == 0)

+  else if (MyStringCompareNoCase(command, L"d") == 0)

     encodeMode = false;

   else

     IncorrectCommand();

@@ -267,7 +306,7 @@
     const UString &inputName = nonSwitchStrings[paramIndex++];

     inStreamSpec = new CInFileStream;

     inStream = inStreamSpec;

-    if (!inStreamSpec->Open(GetSystemString(inputName)))

+    if (!inStreamSpec->Open(us2fs(inputName)))

     {

       fprintf(stderr, "\nError: can not open input file %s\n",

           (const char *)GetOemString(inputName));

@@ -289,7 +328,7 @@
     const UString &outputName = nonSwitchStrings[paramIndex++];

     outStreamSpec = new COutFileStream;

     outStream = outStreamSpec;

-    if (!outStreamSpec->Create(GetSystemString(outputName), true))

+    if (!outStreamSpec->Create(us2fs(outputName), true))

     {

       fprintf(stderr, "\nError: can not open output file %s\n",

         (const char *)GetOemString(outputName));

@@ -398,7 +437,7 @@
       if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))

         IncorrectCommand();

     

-    PROPID propIDs[] =

+    const PROPID propIDs[] =

     {

       NCoderPropID::kDictionarySize,

       NCoderPropID::kPosStateBits,

@@ -411,7 +450,7 @@
       NCoderPropID::kNumThreads,

       NCoderPropID::kMatchFinderCycles,

     };

-    const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);

+    const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);

 

     PROPVARIANT props[kNumPropsMax];

     for (int p = 0; p < 6; p++)

@@ -437,7 +476,7 @@
     props[9].vt = VT_UI4;

     props[9].ulVal = (UInt32)mc;

 

-    int numProps = kNumPropsMax;

+    unsigned numProps = kNumPropsMax;

     if (!mcDefined)

       numProps--;

 

@@ -467,7 +506,7 @@
     }

     else if (result != S_OK)

     {

-      fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);

+      fprintf(stderr, "\nEncoder error = %X\n", (unsigned)result);

       return 1;

     }

   }

@@ -492,11 +531,18 @@
     for (int i = 0; i < 8; i++)

       fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);

 

-    if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK)

+    bool isSizeDefined = (fileSize != (UInt64)(Int64)-1);

+    HRESULT res = decoder->Code(inStream, outStream, 0, isSizeDefined ? &fileSize : NULL, 0) != S_OK;

+    if (res != S_OK)

     {

       PrintMessage("Decoder error");

       return 1;

     }

+    if (isSizeDefined && decoderSpec->GetOutputProcessedSize() != fileSize)

+    {

+      PrintMessage("Error: incorrect uncompressed size in header");

+      return 1;

+    }

   }

   if (outStreamSpec != NULL)

   {

@@ -512,7 +558,7 @@
 int MY_CDECL main(int numArgs, const char *args[])

 {

   try { return main2(numArgs, args); }

-  catch(const char *s)

+  catch (const char *s)

   {

     fprintf(stderr, "\nError: %s\n", s);

     return 1;

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
old mode 100755
new mode 100644
index edac514..3e43804
--- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.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 /Gr /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -66,7 +66,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 /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c

+# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -132,6 +132,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\Windows\Synchronization.cpp

 # End Source File

 # Begin Source File

@@ -172,6 +180,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\..\Common\CrcReg.cpp

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\..\Common\Defs.h

 # End Source File

 # Begin Source File

@@ -280,6 +292,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\Common\MethodProps.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\MethodProps.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\Common\StreamUtils.cpp

 # End Source File

 # Begin Source File

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
old mode 100755
new mode 100644
index 83fdd22..59d9ac1
--- a/CPP/7zip/Bundles/LzmaCon/StdAfx.h
+++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
@@ -3,6 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile
old mode 100755
new mode 100644
index b0b84f1..2609763
--- a/CPP/7zip/Bundles/LzmaCon/makefile
+++ b/CPP/7zip/Bundles/LzmaCon/makefile
@@ -2,7 +2,7 @@
 MY_CONSOLE = 1

 CFLAGS = $(CFLAGS)

 

-LZMA_OBJS = \

+CURRENT_OBJS = \

   $O\LzmaAlone.obj \

 

 COMPRESS_OBJS = \

@@ -13,14 +13,17 @@
 COMMON_OBJS = \

   $O\CommandLineParser.obj \

   $O\CRC.obj \

+  $O\CrcReg.obj \

   $O\IntToString.obj \

   $O\MyString.obj \

+  $O\NewHandler.obj \

   $O\StringConvert.obj \

   $O\StringToInt.obj \

   $O\MyVector.obj

 

 WIN_OBJS = \

   $O\FileIO.obj \

+  $O\PropVariant.obj \

   $O\System.obj

 

 7ZIP_COMMON_OBJS = \

@@ -28,6 +31,7 @@
   $O\CreateCoder.obj \

   $O\FileStreams.obj \

   $O\FilterCoder.obj \

+  $O\MethodProps.obj \

   $O\OutBuffer.obj \

   $O\StreamUtils.obj \

 

@@ -52,36 +56,4 @@
 

 !include "../../Crc.mak"

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(LZMA_OBJS) \

-  $(COMPRESS_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-  $(UI_COMMON_OBJS) \

-  $(CONSOLE_OBJS) \

-  $(C_OBJS) \

-  $(ASM_OBJS) \

-

-!include "../../../Build.mak"

-

-

-$(LZMA_OBJS): $(*B).cpp

-	$(COMPL)

-$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

-	$(COMPL_O2)

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

-$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp

-	$(COMPL)

-$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp

-	$(COMPL)

-$(C_OBJS): ../../../../C/$(*B).c

-	$(COMPL_O2)

-

-!include "../../Asm.mak"

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
old mode 100755
new mode 100644
index 59a70de..ae9e27a
--- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc
+++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
@@ -1,24 +1,42 @@
 PROG = lzma

-CXX = g++ -O2 -Wall

-CXX_C = gcc -O2 -Wall

-LIB = -lm

-RM = rm -f

-CFLAGS = -c -D_7ZIP_ST

+CXX = g++ -O2

+# -Wall -Werror -Wno-delete-non-virtual-dtor

+CXX_C = gcc -O2 -Wall -Werror

 

 ifdef SystemDrive

 IS_MINGW = 1

 endif

 

 ifdef IS_MINGW

+

+RM = del

+CFLAGS = -c

+LIB2 = -loleaut32 -luuid

+LDFLAGS = -s

+

 FILE_IO =FileIO

 FILE_IO_2 =Windows/$(FILE_IO)

-LIB2 = -luuid

+

+MT_FILES = \

+  System.o \

+  LzFindMt.o \

+  Threads.o \

+

 else

+

+RM = rm -f

+CFLAGS = -c -D_7ZIP_ST

+

 FILE_IO =C_FileIO

 FILE_IO_2 =Common/$(FILE_IO)

+

+

 endif

 

+

 OBJS = \

+  $(MT_FILES) \

+  $(FILE_IO).o \

   LzmaAlone.o \

   Bench.o \

   BenchCon.o \

@@ -30,15 +48,18 @@
   CWrappers.o \

   FileStreams.o \

   FilterCoder.o \

+  MethodProps.o \

   StreamUtils.o \

-  $(FILE_IO).o \

   CommandLineParser.o \

   CRC.o \

+  CrcReg.o \

   IntToString.o \

   MyString.o \

+  MyVector.o \

+  MyWindows.o \

   StringConvert.o \

   StringToInt.o \

-  MyVector.o \

+  PropVariant.o \

   7zCrc.o \

   7zCrcOpt.o \

   Alloc.o \

@@ -54,7 +75,7 @@
 all: $(PROG)

 

 $(PROG): $(OBJS)

-	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)

+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB2)

 

 LzmaAlone.o: LzmaAlone.cpp

 	$(CXX) $(CFLAGS) LzmaAlone.cpp

@@ -89,6 +110,9 @@
 FilterCoder.o: ../../Common/FilterCoder.cpp

 	$(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp

 

+MethodProps.o: ../../Common/MethodProps.cpp

+	$(CXX) $(CFLAGS) ../../Common/MethodProps.cpp

+

 StreamUtils.o: ../../Common/StreamUtils.cpp

 	$(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp

 

@@ -102,8 +126,8 @@
 CRC.o: ../../../Common/CRC.cpp

 	$(CXX) $(CFLAGS) ../../../Common/CRC.cpp

 

-MyWindows.o: ../../../Common/MyWindows.cpp

-	$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp

+CrcReg.o: ../../../Common/CrcReg.cpp

+	$(CXX) $(CFLAGS) ../../../Common/CrcReg.cpp

 

 IntToString.o: ../../../Common/IntToString.cpp

 	$(CXX) $(CFLAGS) ../../../Common/IntToString.cpp

@@ -111,14 +135,25 @@
 MyString.o: ../../../Common/MyString.cpp

 	$(CXX) $(CFLAGS) ../../../Common/MyString.cpp

 

+MyVector.o: ../../../Common/MyVector.cpp

+	$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp

+

+MyWindows.o: ../../../Common/MyWindows.cpp

+	$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp

+

 StringConvert.o: ../../../Common/StringConvert.cpp

 	$(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp

 

 StringToInt.o: ../../../Common/StringToInt.cpp

 	$(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp

 

-MyVector.o: ../../../Common/MyVector.cpp

-	$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp

+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

@@ -138,6 +173,14 @@
 LzFind.o: ../../../../C/LzFind.c

 	$(CXX_C) $(CFLAGS) ../../../../C/LzFind.c

 

+ifdef MT_FILES

+LzFindMt.o: ../../../../C/LzFindMt.c

+	$(CXX_C) $(CFLAGS) ../../../../C/LzFindMt.c

+

+Threads.o: ../../../../C/Threads.c

+	$(CXX_C) $(CFLAGS) ../../../../C/Threads.c

+endif

+

 LzmaDec.o: ../../../../C/LzmaDec.c

 	$(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c

 

diff --git a/CPP/7zip/Bundles/LzmaCon/resource.rc b/CPP/7zip/Bundles/LzmaCon/resource.rc
new file mode 100644
index 0000000..6b5918d
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/resource.rc
@@ -0,0 +1,3 @@
+#include "../../../../C/7zVersion.rc"

+

+MY_VERSION_INFO_APP("LZMA", "lzma")

diff --git a/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp b/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
new file mode 100644
index 0000000..bd79123
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
@@ -0,0 +1,713 @@
+/* LzmaSpec.c -- LZMA Reference Decoder

+2013-07-28 : Igor Pavlov : Public domain */

+

+// This code implements LZMA file decoding according to LZMA specification.

+// This code is not optimized for speed.

+

+#include <stdio.h>

+

+#ifdef _MSC_VER

+  #pragma warning(disable : 4710) // function not inlined

+  #pragma warning(disable : 4996) // This function or variable may be unsafe

+#endif

+

+typedef unsigned char Byte;

+typedef unsigned short UInt16;

+

+#ifdef _LZMA_UINT32_IS_ULONG

+  typedef unsigned long UInt32;

+#else

+  typedef unsigned int UInt32;

+#endif

+

+#if defined(_MSC_VER) || defined(__BORLANDC__)

+  typedef unsigned __int64 UInt64;

+#else

+  typedef unsigned long long int UInt64;

+#endif

+

+

+struct CInputStream

+{

+  FILE *File;

+  UInt64 Processed;

+  

+  void Init() { Processed = 0; }

+

+  Byte ReadByte()

+  {

+    int c = getc(File);

+    if (c < 0)

+      throw "Unexpected end of file";

+    Processed++;

+    return (Byte)c;

+  }

+};

+

+

+struct COutStream

+{

+  FILE *File;

+  UInt64 Processed;

+

+  void Init() { Processed = 0; }

+

+  void WriteByte(Byte b)

+  {

+    if (putc(b, File) == EOF)

+      throw "File writing error";

+    Processed++;

+  }

+};

+

+

+class COutWindow

+{

+  Byte *Buf;

+  UInt32 Pos;

+  UInt32 Size;

+  bool IsFull;

+

+public:

+  unsigned TotalPos;

+  COutStream OutStream;

+

+  COutWindow(): Buf(NULL) {}

+  ~COutWindow() { delete []Buf; }

+ 

+  void Create(UInt32 dictSize)

+  {

+    Buf = new Byte[dictSize];

+    Pos = 0;

+    Size = dictSize;

+    IsFull = false;

+    TotalPos = 0;

+  }

+

+  void PutByte(Byte b)

+  {

+    TotalPos++;

+    Buf[Pos++] = b;

+    if (Pos == Size)

+    {

+      Pos = 0;

+      IsFull = true;

+    }

+    OutStream.WriteByte(b);

+  }

+

+  Byte GetByte(UInt32 dist) const

+  {

+    return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];

+  }

+

+  void CopyMatch(UInt32 dist, unsigned len)

+  {

+    for (; len > 0; len--)

+      PutByte(GetByte(dist));

+  }

+

+  bool CheckDistance(UInt32 dist) const

+  {

+    return dist <= Pos || IsFull;

+  }

+

+  bool IsEmpty() const

+  {

+    return Pos == 0 && !IsFull;

+  }

+};

+

+

+#define kNumBitModelTotalBits 11

+#define kNumMoveBits 5

+

+typedef UInt16 CProb;

+

+#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)

+

+#define INIT_PROBS(p) \

+ { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }

+

+class CRangeDecoder

+{

+  UInt32 Range;

+  UInt32 Code;

+

+  void Normalize();

+

+public:

+

+  CInputStream *InStream;

+  bool Corrupted;

+

+  void Init();

+  bool IsFinishedOK() const { return Code == 0; }

+

+  UInt32 DecodeDirectBits(unsigned numBits);

+  unsigned DecodeBit(CProb *prob);

+};

+

+void CRangeDecoder::Init()

+{

+  Corrupted = false;

+  

+  if (InStream->ReadByte() != 0)

+    Corrupted = true;

+  

+  Range = 0xFFFFFFFF;

+  Code = 0;

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

+    Code = (Code << 8) | InStream->ReadByte();

+  

+  if (Code == Range)

+    Corrupted = true;

+}

+

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

+

+void CRangeDecoder::Normalize()

+{

+  if (Range < kTopValue)

+  {

+    Range <<= 8;

+    Code = (Code << 8) | InStream->ReadByte();

+  }

+}

+

+UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)

+{

+  UInt32 res = 0;

+  do

+  {

+    Range >>= 1;

+    Code -= Range;

+    UInt32 t = 0 - ((UInt32)Code >> 31);

+    Code += Range & t;

+    

+    if (Code == Range)

+      Corrupted = true;

+    

+    Normalize();

+    res <<= 1;

+    res += t + 1;

+  }

+  while (--numBits);

+  return res;

+}

+

+unsigned CRangeDecoder::DecodeBit(CProb *prob)

+{

+  unsigned v = *prob;

+  UInt32 bound = (Range >> kNumBitModelTotalBits) * v;

+  unsigned symbol;

+  if (Code < bound)

+  {

+    v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;

+    Range = bound;

+    symbol = 0;

+  }

+  else

+  {

+    v -= v >> kNumMoveBits;

+    Code -= bound;

+    Range -= bound;

+    symbol = 1;

+  }

+  *prob = (CProb)v;

+  Normalize();

+  return symbol;

+}

+

+

+unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)

+{

+  unsigned m = 1;

+  unsigned symbol = 0;

+  for (unsigned i = 0; i < numBits; i++)

+  {

+    unsigned bit = rc->DecodeBit(&probs[m]);

+    m <<= 1;

+    m += bit;

+    symbol |= (bit << i);

+  }

+  return symbol;

+}

+

+template <unsigned NumBits>

+class CBitTreeDecoder

+{

+  CProb Probs[(unsigned)1 << NumBits];

+

+public:

+

+  void Init()

+  {

+    INIT_PROBS(Probs);

+  }

+

+  unsigned Decode(CRangeDecoder *rc)

+  {

+    unsigned m = 1;

+    for (unsigned i = 0; i < NumBits; i++)

+      m = (m << 1) + rc->DecodeBit(&Probs[m]);

+    return m - ((unsigned)1 << NumBits);

+  }

+

+  unsigned ReverseDecode(CRangeDecoder *rc)

+  {

+    return BitTreeReverseDecode(Probs, NumBits, rc);

+  }

+};

+

+#define kNumPosBitsMax 4

+

+#define kNumStates 12

+#define kNumLenToPosStates 4

+#define kNumAlignBits 4

+#define kStartPosModelIndex 4

+#define kEndPosModelIndex 14

+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))

+#define kMatchMinLen 2

+

+class CLenDecoder

+{

+  CProb Choice;

+  CProb Choice2;

+  CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];

+  CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];

+  CBitTreeDecoder<8> HighCoder;

+

+public:

+

+  void Init()

+  {

+    Choice = PROB_INIT_VAL;

+    Choice2 = PROB_INIT_VAL;

+    HighCoder.Init();

+    for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)

+    {

+      LowCoder[i].Init();

+      MidCoder[i].Init();

+    }

+  }

+

+  unsigned Decode(CRangeDecoder *rc, unsigned posState)

+  {

+    if (rc->DecodeBit(&Choice) == 0)

+      return LowCoder[posState].Decode(rc);

+    if (rc->DecodeBit(&Choice2) == 0)

+      return 8 + MidCoder[posState].Decode(rc);

+    return 16 + HighCoder.Decode(rc);

+  }

+};

+

+unsigned UpdateState_Literal(unsigned state)

+{

+  if (state < 4) return 0;

+  else if (state < 10) return state - 3;

+  else return state - 6;

+}

+unsigned UpdateState_Match   (unsigned state) { return state < 7 ? 7 : 10; }

+unsigned UpdateState_Rep     (unsigned state) { return state < 7 ? 8 : 11; }

+unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }

+

+#define LZMA_DIC_MIN (1 << 12)

+

+class CLzmaDecoder

+{

+public:

+  CRangeDecoder RangeDec;

+  COutWindow OutWindow;

+

+  bool markerIsMandatory;

+  unsigned lc, pb, lp;

+  UInt32 dictSize;

+  UInt32 dictSizeInProperties;

+

+  void DecodeProperties(const Byte *properties)

+  {

+    unsigned d = properties[0];

+    if (d >= (9 * 5 * 5))

+      throw "Incorrect LZMA properties";

+    lc = d % 9;

+    d /= 9;

+    pb = d / 5;

+    lp = d % 5;

+    dictSizeInProperties = 0;

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

+      dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);

+    dictSize = dictSizeInProperties;

+    if (dictSize < LZMA_DIC_MIN)

+      dictSize = LZMA_DIC_MIN;

+  }

+

+  CLzmaDecoder(): LitProbs(NULL) {}

+  ~CLzmaDecoder() { delete []LitProbs; }

+

+  void Create()

+  {

+    OutWindow.Create(dictSize);

+    CreateLiterals();

+  }

+

+  int Decode(bool unpackSizeDefined, UInt64 unpackSize);

+  

+private:

+

+  CProb *LitProbs;

+

+  void CreateLiterals()

+  {

+    LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];

+  }

+  

+  void InitLiterals()

+  {

+    UInt32 num = (UInt32)0x300 << (lc + lp);

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

+      LitProbs[i] = PROB_INIT_VAL;

+  }

+  

+  void DecodeLiteral(unsigned state, UInt32 rep0)

+  {

+    unsigned prevByte = 0;

+    if (!OutWindow.IsEmpty())

+      prevByte = OutWindow.GetByte(1);

+    

+    unsigned symbol = 1;

+    unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));

+    CProb *probs = &LitProbs[(UInt32)0x300 * litState];

+    

+    if (state >= 7)

+    {

+      unsigned matchByte = OutWindow.GetByte(rep0 + 1);

+      do

+      {

+        unsigned matchBit = (matchByte >> 7) & 1;

+        matchByte <<= 1;

+        unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);

+        symbol = (symbol << 1) | bit;

+        if (matchBit != bit)

+          break;

+      }

+      while (symbol < 0x100);

+    }

+    while (symbol < 0x100)

+      symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);

+    OutWindow.PutByte((Byte)(symbol - 0x100));

+  }

+

+  CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];

+  CBitTreeDecoder<kNumAlignBits> AlignDecoder;

+  CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];

+  

+  void InitDist()

+  {

+    for (unsigned i = 0; i < kNumLenToPosStates; i++)

+      PosSlotDecoder[i].Init();

+    AlignDecoder.Init();

+    INIT_PROBS(PosDecoders);

+  }

+  

+  unsigned DecodeDistance(unsigned len)

+  {

+    unsigned lenState = len;

+    if (lenState > kNumLenToPosStates - 1)

+      lenState = kNumLenToPosStates - 1;

+    

+    unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);

+    if (posSlot < 4)

+      return posSlot;

+    

+    unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);

+    UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);

+    if (posSlot < kEndPosModelIndex)

+      dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);

+    else

+    {

+      dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;

+      dist += AlignDecoder.ReverseDecode(&RangeDec);

+    }

+    return dist;

+  }

+

+  CProb IsMatch[kNumStates << kNumPosBitsMax];

+  CProb IsRep[kNumStates];

+  CProb IsRepG0[kNumStates];

+  CProb IsRepG1[kNumStates];

+  CProb IsRepG2[kNumStates];

+  CProb IsRep0Long[kNumStates << kNumPosBitsMax];

+

+  CLenDecoder LenDecoder;

+  CLenDecoder RepLenDecoder;

+

+  void Init()

+  {

+    InitLiterals();

+    InitDist();

+

+    INIT_PROBS(IsMatch);

+    INIT_PROBS(IsRep);

+    INIT_PROBS(IsRepG0);

+    INIT_PROBS(IsRepG1);

+    INIT_PROBS(IsRepG2);

+    INIT_PROBS(IsRep0Long);

+

+    LenDecoder.Init();

+    RepLenDecoder.Init();

+  }

+};

+    

+

+#define LZMA_RES_ERROR                   0

+#define LZMA_RES_FINISHED_WITH_MARKER    1

+#define LZMA_RES_FINISHED_WITHOUT_MARKER 2

+

+int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)

+{

+  Init();

+  RangeDec.Init();

+

+  UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;

+  unsigned state = 0;

+  

+  for (;;)

+  {

+    if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)

+      if (RangeDec.IsFinishedOK())

+        return LZMA_RES_FINISHED_WITHOUT_MARKER;

+

+    unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);

+

+    if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)

+    {

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+      DecodeLiteral(state, rep0);

+      state = UpdateState_Literal(state);

+      unpackSize--;

+      continue;

+    }

+    

+    unsigned len;

+    

+    if (RangeDec.DecodeBit(&IsRep[state]) != 0)

+    {

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+      if (OutWindow.IsEmpty())

+        return LZMA_RES_ERROR;

+      if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)

+      {

+        if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)

+        {

+          state = UpdateState_ShortRep(state);

+          OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));

+          unpackSize--;

+          continue;

+        }

+      }

+      else

+      {

+        UInt32 dist;

+        if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)

+          dist = rep1;

+        else

+        {

+          if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)

+            dist = rep2;

+          else

+          {

+            dist = rep3;

+            rep3 = rep2;

+          }

+          rep2 = rep1;

+        }

+        rep1 = rep0;

+        rep0 = dist;

+      }

+      len = RepLenDecoder.Decode(&RangeDec, posState);

+      state = UpdateState_Rep(state);

+    }

+    else

+    {

+      rep3 = rep2;

+      rep2 = rep1;

+      rep1 = rep0;

+      len = LenDecoder.Decode(&RangeDec, posState);

+      state = UpdateState_Match(state);

+      rep0 = DecodeDistance(len);

+      if (rep0 == 0xFFFFFFFF)

+        return RangeDec.IsFinishedOK() ?

+            LZMA_RES_FINISHED_WITH_MARKER :

+            LZMA_RES_ERROR;

+

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+      if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))

+        return LZMA_RES_ERROR;

+    }

+    len += kMatchMinLen;

+    bool isError = false;

+    if (unpackSizeDefined && unpackSize < len)

+    {

+      len = (unsigned)unpackSize;

+      isError = true;

+    }

+    OutWindow.CopyMatch(rep0 + 1, len);

+    unpackSize -= len;

+    if (isError)

+      return LZMA_RES_ERROR;

+  }

+}

+

+static void Print(const char *s)

+{

+  fputs(s, stdout);

+}

+

+static void PrintError(const char *s)

+{

+  fputs(s, stderr);

+}

+

+

+#define CONVERT_INT_TO_STR(charType, tempSize) \

+

+void ConvertUInt64ToString(UInt64 val, char *s)

+{

+  char temp[32];

+  unsigned i = 0;

+  while (val >= 10)

+  {

+    temp[i++] = (char)('0' + (unsigned)(val % 10));

+    val /= 10;

+  }

+  *s++ = (char)('0' + (unsigned)val);

+  while (i != 0)

+  {

+    i--;

+    *s++ = temp[i];

+  }

+  *s = 0;

+}

+

+void PrintUInt64(const char *title, UInt64 v)

+{

+  Print(title);

+  Print(" : ");

+  char s[32];

+  ConvertUInt64ToString(v, s);

+  Print(s);

+  Print(" bytes \n");

+}

+

+int main2(int numArgs, const char *args[])

+{

+  Print("\nLZMA Reference Decoder 9.31 : Igor Pavlov : Public domain : 2013-02-06\n");

+  if (numArgs == 1)

+    Print("\nUse: lzmaSpec a.lzma outFile");

+

+  if (numArgs != 3)

+    throw "you must specify two parameters";

+

+  CInputStream inStream;

+  inStream.File = fopen(args[1], "rb");

+  inStream.Init();

+  if (inStream.File == 0)

+    throw "Can't open input file";

+

+  CLzmaDecoder lzmaDecoder;

+  lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+");

+  lzmaDecoder.OutWindow.OutStream.Init();

+  if (inStream.File == 0)

+    throw "Can't open output file";

+

+  Byte header[13];

+  int i;

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

+    header[i] = inStream.ReadByte();

+

+  lzmaDecoder.DecodeProperties(header);

+

+  printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb);

+  printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties);

+  printf("\nDictionary Size for decoding  = %u", lzmaDecoder.dictSize);

+

+  UInt64 unpackSize = 0;

+  bool unpackSizeDefined = false;

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

+  {

+    Byte b = header[5 + i];

+    if (b != 0xFF)

+      unpackSizeDefined = true;

+    unpackSize |= (UInt64)b << (8 * i);

+  }

+

+  lzmaDecoder.markerIsMandatory = !unpackSizeDefined;

+

+  Print("\n");

+  if (unpackSizeDefined)

+    PrintUInt64("Uncompressed Size", unpackSize);

+  else

+    Print("End marker is expected\n");

+  lzmaDecoder.RangeDec.InStream = &inStream;

+

+  Print("\n");

+

+  lzmaDecoder.Create();

+  // we support the streams that have uncompressed size and marker.

+  int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);

+

+  PrintUInt64("Read    ", inStream.Processed);

+  PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed);

+

+  if (res == LZMA_RES_ERROR)

+    throw "LZMA decoding error";

+  else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER)

+    Print("Finished without end marker");

+  else if (res == LZMA_RES_FINISHED_WITH_MARKER)

+  {

+    if (unpackSizeDefined)

+    {

+      if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize)

+        throw "Finished with end marker before than specified size";

+      Print("Warning: ");

+    }

+    Print("Finished with end marker");

+  }

+  else

+    throw "Internal Error";

+

+  Print("\n");

+  

+  if (lzmaDecoder.RangeDec.Corrupted)

+  {

+    Print("\nWarning: LZMA stream is corrupted\n");

+  }

+

+  return 0;

+}

+

+

+int

+  #ifdef _MSC_VER

+    __cdecl

+  #endif

+main(int numArgs, const char *args[])

+{

+  try { return main2(numArgs, args); }

+  catch (const char *s)

+  {

+    PrintError("\nError:\n");

+    PrintError(s);

+    PrintError("\n");

+    return 1;

+  }

+  catch(...)

+  {

+    PrintError("\nError\n");

+    return 1;

+  }

+}

diff --git a/CPP/7zip/Bundles/SFXCon/7z.ico b/CPP/7zip/Bundles/SFXCon/7z.ico
new file mode 100644
index 0000000..47ffb78
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/7z.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
new file mode 100644
index 0000000..6f380b1
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -0,0 +1,837 @@
+# Microsoft Developer Studio Project File - Name="SFXCon" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=SFXCon - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXCon.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXCon.mak" CFG="SFXCon - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "SFXCon - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# 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 /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /c

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "SFXCon - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# 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 /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c

+# ADD BASE RSC /l 0x419 /d "_DEBUG"

+# ADD RSC /l 0x419 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\7zCon.exe" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "SFXCon - Win32 Release"

+# Name "SFXCon - Win32 Debug"

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\resource.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"StdAfx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "Archive Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.h

+# 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

+

+SOURCE=..\..\Archive\Common\ItemNameUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h

+# End Source File

+# End Group

+# Begin Group "Console"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\List.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\List.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\MainAr.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\OpenCallbackConsole.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UserInputUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UserInputUtils.h

+# End Source File

+# End Group

+# Begin Group "7z"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zExtract.cpp

+# 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

+

+SOURCE=..\..\Archive\7z\7zHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHeader.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zItem.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\SplitHandler.cpp

+# End Source File

+# End Group

+# Begin Group "Compress"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Coder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\PpmdDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\PpmdRegister.cpp

+# End Source File

+# End Group

+# Begin Group "Crypto"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAesRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.h

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConv.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConv.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.h

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdInStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdInStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdOutStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdOutStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.h

+# End Source File

+# End Group

+# Begin Group "7zip Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.h

+# 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\OffsetStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OffsetStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OutBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OutBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\PropId.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.h

+# End Source File

+# End Group

+# Begin Group "UI"

+

+# PROP Default_Filter ""

+# Begin Group "UI Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExitCode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractMode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\PropIDUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\PropIDUtils.h

+# End Source File

+# End Group

+# End Group

+# Begin Group "C"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrcOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Aes.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Aes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\AesOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra86.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\Lzma2Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sha256.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sha256.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\7z.ico

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\IArchive.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\SfxCon.cpp

+# End Source File

+# End Target

+# End Project

diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
new file mode 100644
index 0000000..bfbc2b7
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "SFXCon"=.\SFXCon.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
new file mode 100644
index 0000000..ae525fe
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -0,0 +1,453 @@
+// Main.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/MyInitGuid.h"

+

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/MyException.h"

+

+#ifdef _WIN32

+#include "../../../Windows/DLL.h"

+#include "../../../Windows/FileDir.h"

+#endif

+#include "../../../Windows/FileName.h"

+

+#include "../../UI/Common/ExitCode.h"

+#include "../../UI/Common/Extract.h"

+

+#include "../../UI/Console/ExtractCallbackConsole.h"

+#include "../../UI/Console/List.h"

+#include "../../UI/Console/OpenCallbackConsole.h"

+

+#include "../../MyVersion.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+using namespace NCommandLineParser;

+

+#ifdef _WIN32

+HINSTANCE g_hInstance = 0;

+#endif

+int g_CodePage = -1;

+extern CStdOutStream *g_StdStream;

+

+static const char *kCopyrightString =

+"\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n";

+

+static const int kNumSwitches = 6;

+

+namespace NKey {

+enum Enum

+{

+  kHelp1 = 0,

+  kHelp2,

+  kDisablePercents,

+  kYes,

+  kPassword,

+  kOutputDir

+};

+

+}

+

+namespace NRecursedType {

+enum EEnum

+{

+  kRecursed,

+  kWildcardOnlyRecursed,

+  kNonRecursed

+};

+}

+/*

+static const char kRecursedIDChar = 'R';

+static const wchar_t *kRecursedPostCharSet = L"0-";

+

+namespace NRecursedPostCharIndex {

+  enum EEnum

+  {

+    kWildcardRecursionOnly = 0,

+    kNoRecursion = 1

+  };

+}

+

+static const char kFileListID = '@';

+static const char kImmediateNameID = '!';

+

+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be

+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be

+*/

+static const CSwitchForm kSwitchForms[kNumSwitches] =

+{

+  { "?",  NSwitchType::kSimple },

+  { "H",  NSwitchType::kSimple },

+  { "BD", NSwitchType::kSimple },

+  { "Y",  NSwitchType::kSimple },

+  { "P",  NSwitchType::kString, false, 1 },

+  { "O",  NSwitchType::kString, false, 1 },

+};

+

+static const int kNumCommandForms = 3;

+

+static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =

+{

+  NRecursedType::kRecursed

+};

+

+// static const bool kTestExtractRecursedDefault = true;

+// static const bool kAddRecursedDefault = false;

+

+static const wchar_t *kUniversalWildcard = L"*";

+static const int kCommandIndex = 0;

+

+static const char *kHelpString =

+    "\nUsage: 7zSFX [<command>] [<switches>...]\n"

+    "\n"

+    "<Commands>\n"

+    "  l: List contents of archive\n"

+    "  t: Test integrity of archive\n"

+    "  x: eXtract files with full pathname (default)\n"

+    "<Switches>\n"

+    // "  -bd Disable percentage indicator\n"

+    "  -o{Directory}: set Output directory\n"

+    "  -p{Password}: set Password\n"

+    "  -y: assume Yes on all queries\n";

+

+

+// ---------------------------

+// exception messages

+

+static const char *kUserErrorMessage  = "Incorrect command line"; // NExitCode::kUserError

+// static const char *kIncorrectListFile = "Incorrect wildcard in listfile";

+static const char *kIncorrectWildcardInCommandLine  = "Incorrect wildcard in command line";

+

+// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";

+// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";

+

+// static const char *kProcessArchiveMessage = " archive: ";

+

+static const char *kCantFindSFX = " cannot find sfx";

+

+namespace NCommandType

+{

+  enum EEnum

+  {

+    kTest = 0,

+    kFullExtract,

+    kList

+  };

+}

+

+static const char *g_Commands = "txl";

+

+struct CArchiveCommand

+{

+  NCommandType::EEnum CommandType;

+

+  NRecursedType::EEnum DefaultRecursedType() const;

+};

+

+bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)

+{

+  UString s = commandString;

+  s.MakeLower_Ascii();

+  if (s.Len() != 1)

+    return false;

+  if (s[0] >= 0x80)

+    return false;

+  int index = FindCharPosInString(g_Commands, (char)s[0]);

+  if (index < 0)

+    return false;

+  command.CommandType = (NCommandType::EEnum)index;

+  return true;

+}

+

+NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const

+{

+  return kCommandRecursedDefault[CommandType];

+}

+

+void PrintHelp(void)

+{

+  g_StdOut << kHelpString;

+}

+

+static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)

+{

+  g_StdOut << message << endl;

+  throw code;

+}

+

+static void PrintHelpAndExit() // yyy

+{

+  PrintHelp();

+  ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);

+}

+

+// ------------------------------------------------------------------

+// filenames functions

+

+static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,

+    const UString &name, bool include, NRecursedType::EEnum type)

+{

+  /*

+  if (!IsWildcardFilePathLegal(name))

+    return false;

+  */

+  bool isWildcard = DoesNameContainWildcard(name);

+  bool recursed = false;

+

+  switch (type)

+  {

+    case NRecursedType::kWildcardOnlyRecursed:

+      recursed = isWildcard;

+      break;

+    case NRecursedType::kRecursed:

+      recursed = true;

+      break;

+    case NRecursedType::kNonRecursed:

+      recursed = false;

+      break;

+  }

+  wildcardCensor.AddPreItem(include, name, recursed, true);

+  return true;

+}

+

+void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,

+    const UString &name, bool include, NRecursedType::EEnum type)

+{

+  if (!AddNameToCensor(wildcardCensor, name, include, type))

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

+{

+  parts.Clear();

+  for (int i = 0; i < numArgs; i++)

+  {

+    UString s = MultiByteToUnicodeString(args[i]);

+    parts.Add(s);

+  }

+}

+#endif

+

+int Main2(

+  #ifndef _WIN32

+  int numArgs, const char *args[]

+  #endif

+)

+{

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  SetFileApisToOEM();

+  #endif

+  

+  g_StdOut << kCopyrightString;

+

+  UStringVector commandStrings;

+  #ifdef _WIN32

+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);

+  #else

+  GetArguments(numArgs, args, commandStrings);

+  #endif

+

+  #ifdef _WIN32

+  

+  FString arcPath;

+  {

+    FString path;

+    NDLL::MyGetModuleFileName(path);

+    if (!MyGetFullPathName(path, arcPath))

+    {

+      g_StdOut << "GetFullPathName Error";

+      return NExitCode::kFatalError;

+    }

+  }

+

+  #else

+

+  UString arcPath = commandStrings.Front();

+

+  #endif

+

+  commandStrings.Delete(0);

+

+  NCommandLineParser::CParser parser(kNumSwitches);

+  try

+  {

+    parser.ParseStrings(kSwitchForms, commandStrings);

+  }

+  catch(...)

+  {

+    PrintHelpAndExit();

+  }

+

+  if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)

+  {

+    PrintHelp();

+    return 0;

+  }

+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

+

+  int numNonSwitchStrings = nonSwitchStrings.Size();

+

+  CArchiveCommand command;

+  if (numNonSwitchStrings == 0)

+    command.CommandType = NCommandType::kFullExtract;

+  else

+  {

+    if (numNonSwitchStrings > 1)

+      PrintHelpAndExit();

+    if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command))

+      PrintHelpAndExit();

+  }

+

+

+  NRecursedType::EEnum recursedType;

+  recursedType = command.DefaultRecursedType();

+

+  NWildcard::CCensor wildcardCensor;

+  

+  bool thereAreSwitchIncludeWildcards;

+  thereAreSwitchIncludeWildcards = false;

+

+  AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType,

+      thereAreSwitchIncludeWildcards);

+

+  bool yesToAll = parser[NKey::kYes].ThereIs;

+

+  // NExtractMode::EEnum extractMode;

+  // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);

+

+  bool passwordEnabled = parser[NKey::kPassword].ThereIs;

+

+  UString password;

+  if (passwordEnabled)

+    password = parser[NKey::kPassword].PostStrings[0];

+

+  if (!NFind::DoesFileExist(arcPath))

+    throw kCantFindSFX;

+  

+  FString outputDir;

+  if (parser[NKey::kOutputDir].ThereIs)

+  {

+    outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);

+    NName::NormalizeDirPathPrefix(outputDir);

+  }

+

+

+  wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);

+  

+  {

+    UStringVector v1, v2;

+    v1.Add(fs2us(arcPath));

+    v2.Add(fs2us(arcPath));

+    const NWildcard::CCensorNode &wildcardCensorHead =

+      wildcardCensor.Pairs.Front().Head;

+

+    CCodecs *codecs = new CCodecs;

+    CMyComPtr<

+      #ifdef EXTERNAL_CODECS

+      ICompressCodecsInfo

+      #else

+      IUnknown

+      #endif

+      > compressCodecsInfo = codecs;

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

+

+      #ifndef _NO_CRYPTO

+      ecs->PasswordIsDefined = passwordEnabled;

+      ecs->Password = password;

+      #endif

+

+      ecs->Init();

+

+      COpenCallbackConsole openCallback;

+      openCallback.OutStream = g_StdStream;

+

+      #ifndef _NO_CRYPTO

+      openCallback.PasswordIsDefined = passwordEnabled;

+      openCallback.Password = password;

+      #endif

+

+      CExtractOptions eo;

+      eo.StdOutMode = false;

+      eo.YesToAll = yesToAll;

+      eo.TestMode = command.CommandType == NCommandType::kTest;

+      eo.PathMode = NExtract::NPathMode::kFullPaths;

+      eo.OverwriteMode = yesToAll ?

+          NExtract::NOverwriteMode::kOverwrite :

+          NExtract::NOverwriteMode::kAsk;

+      eo.OutputDir = outputDir;

+

+      UString errorMessage;

+      CDecompressStat stat;

+      HRESULT result = Extract(

+          codecs, CObjectVector<COpenType>(), CIntVector(),

+          v1, v2,

+          wildcardCensorHead,

+          eo, &openCallback, ecs,

+          // NULL, // hash

+          errorMessage, stat);

+      if (!errorMessage.IsEmpty())

+      {

+        (*g_StdStream) << endl << "Error: " << errorMessage;;

+        if (result == S_OK)

+          result = E_FAIL;

+      }

+

+      if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)

+      {

+        if (ecs->NumArcsWithError != 0)

+          (*g_StdStream) << endl << "Archive Errors" << endl;

+        if (ecs->NumFileErrors != 0)

+          (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl;

+        return NExitCode::kFatalError;

+      }

+      if (result != S_OK)

+        throw CSystemException(result);

+    }

+    else

+    {

+      UInt64 numErrors = 0;

+      UInt64 numWarnings = 0;

+      HRESULT result = ListArchives(

+          codecs, CObjectVector<COpenType>(), CIntVector(),

+          false, // stdInMode

+          v1, v2,

+          true, // processAltStreams

+          false, // showAltStreams

+          wildcardCensorHead,

+          true, // enableHeaders

+          false, // techMode

+          #ifndef _NO_CRYPTO

+          passwordEnabled, password,

+          #endif

+          numErrors, numWarnings);

+      if (numErrors > 0)

+      {

+        g_StdOut << endl << "Errors: " << numErrors;

+        return NExitCode::kFatalError;

+      }

+      if (result != S_OK)

+        throw CSystemException(result);

+    }

+  }

+  return 0;

+}

diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
new file mode 100644
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/SFXCon/StdAfx.h b/CPP/7zip/Bundles/SFXCon/StdAfx.h
new file mode 100644
index 0000000..59d9ac1
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/Common.h"

+

+#endif

diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
new file mode 100644
index 0000000..4d35d7e
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/makefile
@@ -0,0 +1,124 @@
+PROG = 7zCon.sfx

+MY_CONSOLE = 1

+CFLAGS = $(CFLAGS) \

+  -DEXTRACT_ONLY \

+  -DNO_READ_FROM_CODER \

+  -D_SFX \

+

+CURRENT_OBJS = \

+  $O\SfxCon.obj \

+

+CONSOLE_OBJS = \

+  $O\ConsoleClose.obj \

+  $O\ExtractCallbackConsole.obj \

+  $O\List.obj \

+  $O\MainAr.obj \

+  $O\OpenCallbackConsole.obj \

+  $O\UserInputUtils.obj \

+

+COMMON_OBJS = \

+  $O\CommandLineParser.obj \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\MyString.obj \

+  $O\MyVector.obj \

+  $O\NewHandler.obj \

+  $O\StdInStream.obj \

+  $O\StdOutStream.obj \

+  $O\StringConvert.obj \

+  $O\Wildcard.obj \

+  $O\UTFConvert.obj \

+

+WIN_OBJS = \

+  $O\DLL.obj \

+  $O\ErrorMsg.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\PropVariant.obj \

+  $O\PropVariantConv.obj \

+  $O\Synchronization.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\CWrappers.obj \

+  $O\FilePathAutoRename.obj \

+  $O\FileStreams.obj \

+  $O\InBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\PropId.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveExtractCallback.obj \

+  $O\ArchiveOpenCallback.obj \

+  $O\DefaultName.obj \

+  $O\LoadCodecs.obj \

+  $O\Extract.obj \

+  $O\ExtractingFilePath.obj \

+  $O\OpenArchive.obj \

+  $O\PropIDUtils.obj \

+

+AR_OBJS = \

+  $O\SplitHandler.obj \

+

+AR_COMMON_OBJS = \

+  $O\CoderMixer2.obj \

+  $O\CoderMixer2MT.obj \

+  $O\CrossThreadProgress.obj \

+  $O\ItemNameUtils.obj \

+  $O\MultiStream.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\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaRegister.obj \

+  $O\PpmdDecoder.obj \

+  $O\PpmdRegister.obj \

+

+CRYPTO_OBJS = \

+  $O\7zAes.obj \

+  $O\7zAesRegister.obj \

+  $O\MyAes.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra86.obj \

+  $O\CpuArch.obj \

+  $O\Lzma2Dec.obj \

+  $O\LzmaDec.obj \

+  $O\Ppmd7.obj \

+  $O\Ppmd7Dec.obj \

+  $O\Sha256.obj \

+  $O\Threads.obj \

+

+!include "../../Aes.mak"

+!include "../../Crc.mak"

+

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc
new file mode 100644
index 0000000..1c34357
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXCon/resource.rc
@@ -0,0 +1,5 @@
+#include "../../../../C/7zVersion.rc"

+

+MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")

+

+101 ICON "7z.ico"
\ No newline at end of file
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
new file mode 100644
index 0000000..0811978
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -0,0 +1,238 @@
+// ExtractCallbackSfx.h

+

+#include "StdAfx.h"

+

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/PropVariant.h"

+

+#include "ExtractCallbackSfx.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+

+static LPCWSTR kCantDeleteFile = L"Can not delete output file";

+static LPCWSTR kCantOpenFile = L"Can not open output file";

+static LPCWSTR kUnsupportedMethod = L"Unsupported Method";

+

+void CExtractCallbackImp::Init(IInArchive *archiveHandler,

+    const FString &directoryPath,

+    const UString &itemDefaultName,

+    const FILETIME &defaultMTime,

+    UInt32 defaultAttributes)

+{

+  _message.Empty();

+  _isCorrupt = false;

+  _itemDefaultName = itemDefaultName;

+  _defaultMTime = defaultMTime;

+  _defaultAttributes = defaultAttributes;

+  _archiveHandler = archiveHandler;

+  _directoryPath = directoryPath;

+  NName::NormalizeDirPathPrefix(_directoryPath);

+}

+

+HRESULT CExtractCallbackImp::Open_CheckBreak()

+{

+  #ifndef _NO_PROGRESS

+  return ProgressDialog.Sync.ProcessStopAndPause();

+  #else

+  return S_OK;

+  #endif

+}

+

+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+{

+  return S_OK;

+}

+

+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+{

+  #ifndef _NO_PROGRESS

+  return ProgressDialog.Sync.ProcessStopAndPause();

+  #else

+  return S_OK;

+  #endif

+}

+

+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)

+{

+  #ifndef _NO_PROGRESS

+  ProgressDialog.Sync.SetProgress(size, 0);

+  #endif

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)

+{

+  #ifndef _NO_PROGRESS

+  RINOK(ProgressDialog.Sync.ProcessStopAndPause());

+  if (completeValue != NULL)

+    ProgressDialog.Sync.SetPos(*completeValue);

+  #endif

+  return S_OK;

+}

+

+void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)

+{

+  FString fullPath = _directoryPath;

+  FOR_VECTOR (i, dirPathParts)

+  {

+    fullPath += us2fs(dirPathParts[i]);

+    CreateDir(fullPath);

+    fullPath += FCHAR_PATH_SEPARATOR;

+  }

+}

+

+STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,

+    ISequentialOutStream **outStream, Int32 askExtractMode)

+{

+  #ifndef _NO_PROGRESS

+  if (ProgressDialog.Sync.GetStopped())

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

+  }

+  _filePath = fullPath;

+

+  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)

+  {

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));

+    if (prop.vt == VT_EMPTY)

+      _processedFileInfo.Attributes = _defaultAttributes;

+    else

+    {

+      if (prop.vt != VT_UI4)

+        return E_FAIL;

+      _processedFileInfo.Attributes = prop.ulVal;

+    }

+

+    RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));

+    _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);

+

+    bool isAnti = false;

+    {

+      NCOM::CPropVariant propTemp;

+      RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));

+      if (propTemp.vt == VT_BOOL)

+        isAnti = VARIANT_BOOLToBool(propTemp.boolVal);

+    }

+

+    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));

+    switch(prop.vt)

+    {

+      case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;

+      case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;

+      default: return E_FAIL;

+    }

+

+    UStringVector pathParts;

+    SplitPathToParts(fullPath, pathParts);

+    if (pathParts.IsEmpty())

+      return E_FAIL;

+

+    UString processedPath = fullPath;

+

+    if (!_processedFileInfo.IsDir)

+      pathParts.DeleteBack();

+    if (!pathParts.IsEmpty())

+    {

+      if (!isAnti)

+        CreateComplexDirectory(pathParts);

+    }

+

+    FString fullProcessedPath = _directoryPath + us2fs(processedPath);

+

+    if (_processedFileInfo.IsDir)

+    {

+      _diskFilePath = fullProcessedPath;

+

+      if (isAnti)

+        RemoveDir(_diskFilePath);

+      else

+        SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);

+      return S_OK;

+    }

+

+    NFind::CFileInfo fileInfo;

+    if (fileInfo.Find(fullProcessedPath))

+    {

+      if (!DeleteFileAlways(fullProcessedPath))

+      {

+        _message = kCantDeleteFile;

+        return E_FAIL;

+      }

+    }

+

+    if (!isAnti)

+    {

+      _outFileStreamSpec = new COutFileStream;

+      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

+      if (!_outFileStreamSpec->Create(fullProcessedPath, true))

+      {

+        _message = kCantOpenFile;

+        return E_FAIL;

+      }

+      _outFileStream = outStreamLoc;

+      *outStream = outStreamLoc.Detach();

+    }

+    _diskFilePath = fullProcessedPath;

+  }

+  else

+  {

+    *outStream = NULL;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)

+{

+  _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)

+{

+  switch(resultEOperationResult)

+  {

+    case NArchive::NExtract::NOperationResult::kOK:

+      break;

+

+    default:

+    {

+      _outFileStream.Release();

+      switch(resultEOperationResult)

+      {

+        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

+          _message = kUnsupportedMethod;

+          break;

+        default:

+          _isCorrupt = true;

+      }

+      return E_FAIL;

+    }

+  }

+  if (_outFileStream != NULL)

+  {

+    _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);

+    RINOK(_outFileStreamSpec->Close());

+  }

+  _outFileStream.Release();

+  if (_extractMode)

+    SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);

+  return S_OK;

+}

diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
new file mode 100644
index 0000000..b7f04e0
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
@@ -0,0 +1,86 @@
+// ExtractCallbackSfx.h

+

+#ifndef __EXTRACT_CALLBACK_SFX_H

+#define __EXTRACT_CALLBACK_SFX_H

+

+#include "resource.h"

+

+#include "../../../Windows/ResourceString.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "../../Common/FileStreams.h"

+#include "../../ICoder.h"

+

+#include "../../UI/FileManager/LangUtils.h"

+

+#ifndef _NO_PROGRESS

+#include "../../UI/FileManager/ProgressDialog.h"

+#endif

+#include "../../UI/Common/ArchiveOpenCallback.h"

+

+class CExtractCallbackImp:

+  public IArchiveExtractCallback,

+  public IOpenCallbackUI,

+  public CMyUnknownImp

+{

+public:

+  

+  MY_UNKNOWN_IMP

+

+  INTERFACE_IArchiveExtractCallback(;)

+  INTERFACE_IOpenCallbackUI(;)

+

+private:

+  CMyComPtr<IInArchive> _archiveHandler;

+  FString _directoryPath;

+  UString _filePath;

+  FString _diskFilePath;

+

+  bool _extractMode;

+  struct CProcessedFileInfo

+  {

+    FILETIME MTime;

+    bool IsDir;

+    UInt32 Attributes;

+  } _processedFileInfo;

+

+  COutFileStream *_outFileStreamSpec;

+  CMyComPtr<ISequentialOutStream> _outFileStream;

+

+  UString _itemDefaultName;

+  FILETIME _defaultMTime;

+  UInt32 _defaultAttributes;

+

+  void CreateComplexDirectory(const UStringVector &dirPathParts);

+public:

+  #ifndef _NO_PROGRESS

+  CProgressDialog ProgressDialog;

+  #endif

+

+  bool _isCorrupt;

+  UString _message;

+

+  void Init(IInArchive *archiveHandler,

+    const FString &directoryPath,

+    const UString &itemDefaultName,

+    const FILETIME &defaultMTime,

+    UInt32 defaultAttributes);

+

+  #ifndef _NO_PROGRESS

+  HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread)

+  {

+    ProgressDialog.Create(title, thread, 0);

+    {

+      ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING));

+    }

+

+    ProgressDialog.Show(SW_SHOWNORMAL);

+    return S_OK;

+  }

+  virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); }

+  #endif

+

+};

+

+#endif

diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
new file mode 100644
index 0000000..ba0e960
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
@@ -0,0 +1,138 @@
+// ExtractEngine.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/Thread.h"

+

+#include "../../UI/Common/OpenArchive.h"

+

+#include "../../UI/FileManager/FormatUtils.h"

+#include "../../UI/FileManager/LangUtils.h"

+

+#include "ExtractCallbackSfx.h"

+#include "ExtractEngine.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+

+static LPCWSTR kCantFindArchive = L"Can not find archive file";

+static LPCWSTR kCantOpenArchive = L"Can not open the file as archive";

+

+struct CThreadExtracting

+{

+  CCodecs *Codecs;

+  FString FileName;

+  FString DestFolder;

+

+  CExtractCallbackImp *ExtractCallbackSpec;

+  CMyComPtr<IArchiveExtractCallback> ExtractCallback;

+

+  CArchiveLink ArchiveLink;

+  HRESULT Result;

+  UString ErrorMessage;

+

+  void Process2()

+  {

+    NFind::CFileInfo fi;

+    if (!fi.Find(FileName))

+    {

+      ErrorMessage = kCantFindArchive;

+      Result = E_FAIL;

+      return;

+    }

+

+    CObjectVector<COpenType> incl;

+    CIntVector excl;

+    COpenOptions options;

+    options.codecs = Codecs;

+    options.types = &incl;

+    options.excludedFormats = &excl;

+    options.filePath = fs2us(FileName);

+    

+    Result = ArchiveLink.Open2(options, ExtractCallbackSpec);

+    if (Result != S_OK)

+    {

+      if (Result != S_OK)

+        ErrorMessage = kCantOpenArchive;

+      return;

+    }

+

+    FString dirPath = DestFolder;

+    NName::NormalizeDirPathPrefix(dirPath);

+    

+    if (!CreateComplexDir(dirPath))

+    {

+      ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,

+        #ifdef LANG

+        0x02000603,

+        #endif

+        fs2us(dirPath));

+      Result = E_FAIL;

+      return;

+    }

+

+    ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0);

+

+    Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback);

+  }

+

+  void Process()

+  {

+    try

+    {

+      #ifndef _NO_PROGRESS

+      CProgressCloser closer(ExtractCallbackSpec->ProgressDialog);

+      #endif

+      Process2();

+    }

+    catch(...) { Result = E_FAIL; }

+  }

+  

+  static THREAD_FUNC_DECL MyThreadFunction(void *param)

+  {

+    ((CThreadExtracting *)param)->Process();

+    return 0;

+  }

+};

+

+HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,

+    bool showProgress, bool &isCorrupt, UString &errorMessage)

+{

+  isCorrupt = false;

+  CThreadExtracting t;

+

+  t.Codecs = codecs;

+  t.FileName = fileName;

+  t.DestFolder = destFolder;

+

+  t.ExtractCallbackSpec = new CExtractCallbackImp;

+  t.ExtractCallback = t.ExtractCallbackSpec;

+  

+  #ifndef _NO_PROGRESS

+

+  if (showProgress)

+  {

+    t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON;

+    NWindows::CThread thread;

+    RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t));

+    

+    UString title;

+    LangString(IDS_PROGRESS_EXTRACTING, title);

+    t.ExtractCallbackSpec->StartProgressDialog(title, thread);

+  }

+  else

+

+  #endif

+  {

+    t.Process2();

+  }

+

+  errorMessage = t.ErrorMessage;

+  if (errorMessage.IsEmpty())

+    errorMessage = t.ExtractCallbackSpec->_message;

+  isCorrupt = t.ExtractCallbackSpec->_isCorrupt;

+  return t.Result;

+}

diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
new file mode 100644
index 0000000..8aa9724
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
@@ -0,0 +1,11 @@
+// ExtractEngine.h

+

+#ifndef __EXTRACT_ENGINE_H

+#define __EXTRACT_ENGINE_H

+

+#include "../../UI/Common/LoadCodecs.h"

+

+HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,

+    bool showProgress, bool &isCorrupt, UString &errorMessage);

+

+#endif

diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
new file mode 100644
index 0000000..1024311
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -0,0 +1,752 @@
+# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Application" 0x0101

+

+CFG=SFXSetup - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXSetup.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXSetup.mak" CFG="SFXSetup - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application")

+!MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application")

+!MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+MTL=midl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "SFXSetup - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c

+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386

+# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "SFXSetup - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c

+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "_DEBUG"

+# ADD RSC /l 0x419 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept

+

+!ELSEIF  "$(CFG)" == "SFXSetup - Win32 ReleaseD"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "ReleaseD"

+# PROP BASE Intermediate_Dir "ReleaseD"

+# PROP BASE Ignore_Export_Lib 0

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "ReleaseD"

+# PROP Intermediate_Dir "ReleaseD"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c

+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe"

+# SUBTRACT BASE LINK32 /debug /nodefaultlib

+# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ENDIF 

+

+# Begin Target

+

+# Name "SFXSetup - Win32 Release"

+# Name "SFXSetup - Win32 Debug"

+# Name "SFXSetup - Win32 ReleaseD"

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"StdAfx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "Interface"

+

+# PROP Default_Filter ""

+# End Group

+# Begin Group "7z"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zExtract.cpp

+# 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

+

+SOURCE=..\..\Archive\7z\7zHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHeader.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zItem.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zRegister.cpp

+# End Source File

+# End Group

+# Begin Group "Archive Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.h

+# 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

+

+SOURCE=..\..\Archive\Common\ItemNameUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h

+# End Source File

+# End Group

+# Begin Group "Compress"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Coder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaRegister.cpp

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\TextConfig.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\TextConfig.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.h

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Group "Control"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\Dialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\Dialog.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ResourceString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ResourceString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Window.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Window.h

+# End Source File

+# End Group

+# Begin Group "7z Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.h

+# 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

+

+SOURCE=..\..\Common\OutBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\PropId.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.h

+# End Source File

+# End Group

+# Begin Group "UI"

+

+# PROP Default_Filter ""

+# Begin Group "Explorer"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Explorer\MyMessages.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Explorer\MyMessages.h

+# End Source File

+# End Group

+# Begin Group "UI Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractMode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.h

+# End Source File

+# End Group

+# End Group

+# Begin Group "File Manager"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\FormatUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\FormatUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\LangUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ProgressDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ProgressDialog.h

+# End Source File

+# End Group

+# Begin Group "C"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrcOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra86.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\CpuArch.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\ExtractCallbackSfx.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=.\ExtractCallbackSfx.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\ExtractEngine.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=.\ExtractEngine.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\setup.ico

+# End Source File

+# Begin Source File

+

+SOURCE=.\SfxSetup.cpp

+# End Source File

+# End Target

+# End Project

diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
new file mode 100644
index 0000000..2970370
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
new file mode 100644
index 0000000..202c262
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -0,0 +1,356 @@
+// Main.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/MyInitGuid.h"

+

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/TextConfig.h"

+

+#include "../../../Windows/DLL.h"

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileIO.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/NtCheck.h"

+#include "../../../Windows/ResourceString.h"

+

+#include "../../UI/Explorer/MyMessages.h"

+

+#include "ExtractEngine.h"

+

+#include "resource.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+

+HINSTANCE g_hInstance;

+

+static CFSTR kTempDirPrefix = FTEXT("7zS");

+

+#define _SHELL_EXECUTE

+

+static bool ReadDataString(CFSTR fileName, LPCSTR startID,

+    LPCSTR endID, AString &stringResult)

+{

+  stringResult.Empty();

+  NIO::CInFile inFile;

+  if (!inFile.Open(fileName))

+    return false;

+  const int kBufferSize = (1 << 12);

+

+  Byte buffer[kBufferSize];

+  int signatureStartSize = MyStringLen(startID);

+  int signatureEndSize = MyStringLen(endID);

+  

+  UInt32 numBytesPrev = 0;

+  bool writeMode = false;

+  UInt64 posTotal = 0;

+  for (;;)

+  {

+    if (posTotal > (1 << 20))

+      return (stringResult.IsEmpty());

+    UInt32 numReadBytes = kBufferSize - numBytesPrev;

+    UInt32 processedSize;

+    if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize))

+      return false;

+    if (processedSize == 0)

+      return true;

+    UInt32 numBytesInBuffer = numBytesPrev + processedSize;

+    UInt32 pos = 0;

+    for (;;)

+    {

+      if (writeMode)

+      {

+        if (pos > numBytesInBuffer - signatureEndSize)

+          break;

+        if (memcmp(buffer + pos, endID, signatureEndSize) == 0)

+          return true;

+        char b = buffer[pos];

+        if (b == 0)

+          return false;

+        stringResult += b;

+        pos++;

+      }

+      else

+      {

+        if (pos > numBytesInBuffer - signatureStartSize)

+          break;

+        if (memcmp(buffer + pos, startID, signatureStartSize) == 0)

+        {

+          writeMode = true;

+          pos += signatureStartSize;

+        }

+        else

+          pos++;

+      }

+    }

+    numBytesPrev = numBytesInBuffer - pos;

+    posTotal += pos;

+    memmove(buffer, buffer + pos, numBytesPrev);

+  }

+}

+

+static char kStartID[] = ",!@Install@!UTF-8!";

+static char kEndID[] = ",!@InstallEnd@!";

+

+class CInstallIDInit

+{

+public:

+  CInstallIDInit()

+  {

+    kStartID[0] = ';';

+    kEndID[0] = ';';

+  };

+} g_CInstallIDInit;

+

+

+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;

+

+static void ShowErrorMessageSpec(const UString &name)

+{

+  UString message = NError::MyFormatMessage(::GetLastError());

+  int pos = message.Find(L"%1");

+  if (pos >= 0)

+  {

+    message.Delete(pos, 2);

+    message.Insert(pos, name);

+  }

+  ShowErrorMessage(NULL, message);

+}

+

+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,

+    #ifdef UNDER_CE

+    LPWSTR

+    #else

+    LPSTR

+    #endif

+    /* lpCmdLine */,int /* nCmdShow */)

+{

+  g_hInstance = (HINSTANCE)hInstance;

+

+  NT_CHECK

+

+  // InitCommonControls();

+

+  UString archiveName, switches;

+  #ifdef _SHELL_EXECUTE

+  UString executeFile, executeParameters;

+  #endif

+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);

+

+  FString fullPath;

+  NDLL::MyGetModuleFileName(fullPath);

+

+  switches.Trim();

+  bool assumeYes = false;

+  if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0)

+  {

+    assumeYes = true;

+    switches = switches.Ptr(2);

+    switches.Trim();

+  }

+

+  AString config;

+  if (!ReadDataString(fullPath, kStartID, kEndID, config))

+  {

+    if (!assumeYes)

+      ShowErrorMessage(L"Can't load config info");

+    return 1;

+  }

+

+  UString dirPrefix = L"." WSTRING_PATH_SEPARATOR;

+  UString appLaunched;

+  bool showProgress = true;

+  if (!config.IsEmpty())

+  {

+    CObjectVector<CTextConfigPair> pairs;

+    if (!GetTextConfig(config, pairs))

+    {

+      if (!assumeYes)

+        ShowErrorMessage(L"Config failed");

+      return 1;

+    }

+    UString friendlyName = GetTextConfigValue(pairs, L"Title");

+    UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");

+    UString progress = GetTextConfigValue(pairs, L"Progress");

+    if (progress.IsEqualToNoCase(L"no"))

+      showProgress = false;

+    int index = FindTextConfigItem(pairs, L"Directory");

+    if (index >= 0)

+      dirPrefix = pairs[index].String;

+    if (!installPrompt.IsEmpty() && !assumeYes)

+    {

+      if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |

+          MB_ICONQUESTION) != IDYES)

+        return 0;

+    }

+    appLaunched = GetTextConfigValue(pairs, L"RunProgram");

+    

+    #ifdef _SHELL_EXECUTE

+    executeFile = GetTextConfigValue(pairs, L"ExecuteFile");

+    executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters");

+    #endif

+  }

+

+  CTempDir tempDir;

+  if (!tempDir.Create(kTempDirPrefix))

+  {

+    if (!assumeYes)

+      ShowErrorMessage(L"Can not create temp folder archive");

+    return 1;

+  }

+

+  CCodecs *codecs = new CCodecs;

+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;

+  HRESULT result = codecs->Load();

+  if (result != S_OK)

+  {

+    ShowErrorMessage(L"Can not load codecs");

+    return 1;

+  }

+

+  const FString tempDirPath = tempDir.GetPath();

+  // tempDirPath = L"M:\\1\\"; // to test low disk space

+  {

+    bool isCorrupt = false;

+    UString errorMessage;

+    HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,

+      isCorrupt, errorMessage);

+    

+    if (result != S_OK)

+    {

+      if (!assumeYes)

+      {

+        if (result == S_FALSE || isCorrupt)

+        {

+          NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);

+          result = E_FAIL;

+        }

+        if (result != E_ABORT)

+        {

+          if (errorMessage.IsEmpty())

+            errorMessage = NError::MyFormatMessage(result);

+          ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);

+        }

+      }

+      return 1;

+    }

+  }

+

+  #ifndef UNDER_CE

+  CCurrentDirRestorer currentDirRestorer;

+  if (!SetCurrentDir(tempDirPath))

+    return 1;

+  #endif

+  

+  HANDLE hProcess = 0;

+#ifdef _SHELL_EXECUTE

+  if (!executeFile.IsEmpty())

+  {

+    CSysString filePath = GetSystemString(executeFile);

+    SHELLEXECUTEINFO execInfo;

+    execInfo.cbSize = sizeof(execInfo);

+    execInfo.fMask = SEE_MASK_NOCLOSEPROCESS

+      #ifndef UNDER_CE

+      | SEE_MASK_FLAG_DDEWAIT

+      #endif

+      ;

+    execInfo.hwnd = NULL;

+    execInfo.lpVerb = NULL;

+    execInfo.lpFile = filePath;

+

+    if (!switches.IsEmpty())

+    {

+      if (!executeParameters.IsEmpty())

+        executeParameters += L' ';

+      executeParameters += switches;

+    }

+

+    CSysString parametersSys = GetSystemString(executeParameters);

+    if (parametersSys.IsEmpty())

+      execInfo.lpParameters = NULL;

+    else

+      execInfo.lpParameters = parametersSys;

+

+    execInfo.lpDirectory = NULL;

+    execInfo.nShow = SW_SHOWNORMAL;

+    execInfo.hProcess = 0;

+    /* BOOL success = */ ::ShellExecuteEx(&execInfo);

+    UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;

+    if(result <= 32)

+    {

+      if (!assumeYes)

+        ShowErrorMessage(L"Can not open file");

+      return 1;

+    }

+    hProcess = execInfo.hProcess;

+  }

+  else

+#endif

+  {

+    if (appLaunched.IsEmpty())

+    {

+      appLaunched = L"setup.exe";

+      if (!NFind::DoesFileExist(us2fs(appLaunched)))

+      {

+        if (!assumeYes)

+          ShowErrorMessage(L"Can not find setup.exe");

+        return 1;

+      }

+    }

+    

+    {

+      FString s2 = tempDirPath;

+      NName::NormalizeDirPathPrefix(s2);

+      appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2));

+    }

+    

+    UString appNameForError = appLaunched; // actually we need to rtemove parameters also

+

+    appLaunched.Replace(L"%%T", fs2us(tempDirPath));

+

+    if (!switches.IsEmpty())

+    {

+      appLaunched += L' ';

+      appLaunched += switches;

+    }

+    STARTUPINFO startupInfo;

+    startupInfo.cb = sizeof(startupInfo);

+    startupInfo.lpReserved = 0;

+    startupInfo.lpDesktop = 0;

+    startupInfo.lpTitle = 0;

+    startupInfo.dwFlags = 0;

+    startupInfo.cbReserved2 = 0;

+    startupInfo.lpReserved2 = 0;

+    

+    PROCESS_INFORMATION processInformation;

+    

+    CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched);

+    

+    BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,

+      NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,

+      &startupInfo, &processInformation);

+    if (createResult == 0)

+    {

+      if (!assumeYes)

+      {

+        // we print name of exe file, if error message is

+        // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application".

+        ShowErrorMessageSpec(appNameForError);

+      }

+      return 1;

+    }

+    ::CloseHandle(processInformation.hThread);

+    hProcess = processInformation.hProcess;

+  }

+  if (hProcess != 0)

+  {

+    WaitForSingleObject(hProcess, INFINITE);

+    ::CloseHandle(hProcess);

+  }

+  return 0;

+}

diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
new file mode 100644
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/CPP/7zip/Bundles/SFXSetup/StdAfx.h
new file mode 100644
index 0000000..72410ee
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/StdAfx.h
@@ -0,0 +1,13 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/Common.h"

+

+#include <commctrl.h>

+

+// #define printf(x) NO_PRINTF_(x)

+// #define sprintf(x) NO_SPRINTF_(x)

+

+#endif

diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
new file mode 100644
index 0000000..47c65f9
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/makefile
@@ -0,0 +1,107 @@
+PROG = 7zS.sfx

+CFLAGS = $(CFLAGS) \

+  -DNO_REGISTRY \

+  -DEXTRACT_ONLY \

+  -DNO_READ_FROM_CODER \

+  -D_SFX \

+  -D_NO_CRYPTO \

+

+CURRENT_OBJS = \

+  $O\SfxSetup.obj \

+  $O\ExtractCallbackSfx.obj \

+  $O\ExtractEngine.obj \

+

+COMMON_OBJS = \

+  $O\CommandLineParser.obj \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\NewHandler.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\TextConfig.obj \

+  $O\UTFConvert.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\DLL.obj \

+  $O\ErrorMsg.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\PropVariant.obj \

+  $O\ResourceString.obj \

+  $O\Synchronization.obj \

+  $O\Window.obj \

+

+WIN_CTRL_OBJS = \

+  $O\Dialog.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\FileStreams.obj \

+  $O\InBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\PropId.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveOpenCallback.obj \

+  $O\DefaultName.obj \

+  $O\LoadCodecs.obj \

+  $O\OpenArchive.obj \

+

+EXPLORER_OBJS = \

+  $O\MyMessages.obj \

+

+FM_OBJS = \

+  $O\FormatUtils.obj \

+  $O\ProgressDialog.obj \

+

+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\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaRegister.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra86.obj \

+  $O\CpuArch.obj \

+  $O\Lzma2Dec.obj \

+  $O\LzmaDec.obj \

+  $O\Threads.obj \

+

+!include "../../Crc.mak"

+

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/SFXSetup/resource.h b/CPP/7zip/Bundles/SFXSetup/resource.h
new file mode 100644
index 0000000..533197e
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/resource.h
@@ -0,0 +1,6 @@
+#define IDI_ICON  1

+

+#define IDS_EXTRACTION_ERROR_TITLE       7

+#define IDS_EXTRACTION_ERROR_MESSAGE     8

+#define IDS_CANNOT_CREATE_FOLDER      3003

+#define IDS_PROGRESS_EXTRACTING       3300

diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc
new file mode 100644
index 0000000..7a16044
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/resource.rc
@@ -0,0 +1,16 @@
+#include "../../../../C/7zVersion.rc"

+#include "resource.h"

+

+MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx")

+

+IDI_ICON  ICON "setup.ico"

+

+STRINGTABLE

+BEGIN

+  IDS_EXTRACTION_ERROR_TITLE  "Extraction Failed"

+  IDS_EXTRACTION_ERROR_MESSAGE  "File is corrupt"

+  IDS_CANNOT_CREATE_FOLDER  "Cannot create folder '{0}'"

+  IDS_PROGRESS_EXTRACTING  "Extracting"

+END

+

+#include "../../UI/FileManager/ProgressDialog.rc"

diff --git a/CPP/7zip/Bundles/SFXSetup/setup.ico b/CPP/7zip/Bundles/SFXSetup/setup.ico
new file mode 100644
index 0000000..bb455be
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXSetup/setup.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXWin/7z.ico b/CPP/7zip/Bundles/SFXWin/7z.ico
new file mode 100644
index 0000000..47ffb78
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/7z.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
new file mode 100644
index 0000000..711582f
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -0,0 +1,937 @@
+# Microsoft Developer Studio Project File - Name="SFXWin" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Application" 0x0101

+

+CFG=SFXWin - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXWin.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "SFXWin.mak" CFG="SFXWin - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "SFXWin - Win32 Release" (based on "Win32 (x86) Application")

+!MESSAGE "SFXWin - Win32 Debug" (based on "Win32 (x86) Application")

+!MESSAGE "SFXWin - Win32 ReleaseD" (based on "Win32 (x86) Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+MTL=midl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "SFXWin - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c

+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "SFXWin - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /GZ /c

+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "_DEBUG"

+# ADD RSC /l 0x419 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zsfx.exe" /pdbtype:sept

+

+!ELSEIF  "$(CFG)" == "SFXWin - Win32 ReleaseD"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "SFXWin___Win32_ReleaseD"

+# PROP BASE Intermediate_Dir "SFXWin___Win32_ReleaseD"

+# PROP BASE Ignore_Export_Lib 0

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "SFXWin___Win32_ReleaseD"

+# PROP Intermediate_Dir "SFXWin___Win32_ReleaseD"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c

+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98

+# SUBTRACT BASE LINK32 /pdb:none

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zD.sfx" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ENDIF 

+

+# Begin Target

+

+# Name "SFXWin - Win32 Release"

+# Name "SFXWin - Win32 Debug"

+# Name "SFXWin - Win32 ReleaseD"

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"StdAfx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "7z"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zExtract.cpp

+# 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

+

+SOURCE=..\..\Archive\7z\7zHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHeader.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\SplitHandler.cpp

+# End Source File

+# End Group

+# Begin Group "Archive Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.h

+# 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

+

+SOURCE=..\..\Archive\Common\ItemNameUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h

+# End Source File

+# End Group

+# Begin Group "Compress"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Coder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\PpmdDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\PpmdRegister.cpp

+# End Source File

+# End Group

+# Begin Group "Crypto"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\7zAesRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Crypto\MyAes.h

+# End Source File

+# End Group

+# Begin Group "Dialogs"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\BrowseDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\BrowseDialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ComboDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ComboDialog.h

+# 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

+

+SOURCE=..\..\UI\FileManager\OverwriteDialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\PasswordDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\PasswordDialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ProgressDialog2.h

+# End Source File

+# End Group

+# Begin Group "7zip Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.h

+# 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

+

+SOURCE=..\..\Common\OutBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\PropId.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.h

+# End Source File

+# End Group

+# Begin Group "File Manager"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ExtractCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\ExtractCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\FormatUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\FormatUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\SysIconUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\FileManager\SysIconUtils.h

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Group "Control"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\ComboBox.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\ComboBox.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\Dialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\Dialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\ListView.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Control\ListView.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=..\..\..\Windows\CommonDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\CommonDialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ErrorMsg.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConv.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConv.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ResourceString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\ResourceString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Shell.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Shell.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Window.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Window.h

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.h

+# End Source File

+# End Group

+# Begin Group "UI"

+

+# PROP Default_Filter ""

+# Begin Group "UI Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.h

+# End Source File

+# End Group

+# Begin Group "GUI"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\GUI\ExtractDialog.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\GUI\ExtractDialog.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\GUI\ExtractGUI.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\GUI\ExtractGUI.h

+# End Source File

+# End Group

+# Begin Group "Explorer"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Explorer\MyMessages.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Explorer\MyMessages.h

+# End Source File

+# End Group

+# End Group

+# Begin Group "C"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrcOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Aes.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Aes.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\AesOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra86.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\Lzma2Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Ppmd7Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sha256.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\7z.ico

+# End Source File

+# Begin Source File

+

+SOURCE=.\7z1.ico

+# End Source File

+# Begin Source File

+

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

+SOURCE=.\SfxWin.cpp

+# End Source File

+# End Target

+# End Project

diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
new file mode 100644
index 0000000..6695803
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "SFXWin"=.\SFXWin.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
new file mode 100644
index 0000000..42e940f
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -0,0 +1,233 @@
+// Main.cpp

+

+#include "StdAfx.h"

+

+#include <Shlwapi.h>

+

+#include "../../../Common/MyInitGuid.h"

+

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/DLL.h"

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/NtCheck.h"

+#include "../../../Windows/ResourceString.h"

+

+#include "../../ICoder.h"

+#include "../../IPassword.h"

+#include "../../Archive/IArchive.h"

+#include "../../UI/Common/Extract.h"

+#include "../../UI/Common/ExitCode.h"

+#include "../../UI/Explorer/MyMessages.h"

+#include "../../UI/FileManager/MyWindowsNew.h"

+#include "../../UI/GUI/ExtractGUI.h"

+#include "../../UI/GUI/ExtractRes.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+

+HINSTANCE g_hInstance;

+

+#ifndef UNDER_CE

+

+DWORD g_ComCtl32Version;

+

+static DWORD GetDllVersion(LPCTSTR dllName)

+{

+  DWORD dwVersion = 0;

+  HINSTANCE hinstDll = LoadLibrary(dllName);

+  if (hinstDll)

+  {

+    DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");

+    if (pDllGetVersion)

+    {

+      DLLVERSIONINFO dvi;

+      ZeroMemory(&dvi, sizeof(dvi));

+      dvi.cbSize = sizeof(dvi);

+      HRESULT hr = (*pDllGetVersion)(&dvi);

+      if (SUCCEEDED(hr))

+        dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);

+    }

+    FreeLibrary(hinstDll);

+  }

+  return dwVersion;

+}

+

+#endif

+

+bool g_LVN_ITEMACTIVATE_Support = true;

+

+static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!";

+

+void ErrorMessageForHRESULT(HRESULT res)

+{

+  ShowErrorMessage(HResultToMessage(res));

+}

+

+int APIENTRY WinMain2()

+{

+  // OleInitialize is required for ProgressBar in TaskBar.

+  #ifndef UNDER_CE

+  OleInitialize(NULL);

+  #endif

+

+  #ifndef UNDER_CE

+  g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));

+  g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));

+  #endif

+  

+  UString password;

+  bool assumeYes = false;

+  bool outputFolderDefined = false;

+  FString outputFolder;

+  UStringVector commandStrings;

+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);

+

+  #ifndef UNDER_CE

+  if (commandStrings.Size() > 0)

+    commandStrings.Delete(0);

+  #endif

+

+  FOR_VECTOR (i, commandStrings)

+  {

+    const UString &s = commandStrings[i];

+    if (s.Len() > 1 && s[0] == '-')

+    {

+      wchar_t c = MyCharLower_Ascii(s[1]);

+      if (c == 'y')

+      {

+        assumeYes = true;

+        if (s.Len() != 2)

+        {

+          ShowErrorMessage(L"Bad command");

+          return 1;

+        }

+      }

+      else if (c == 'o')

+      {

+        outputFolder = us2fs(s.Ptr(2));

+        NName::NormalizeDirPathPrefix(outputFolder);

+        outputFolderDefined = !outputFolder.IsEmpty();

+      }

+      else if (c == 'p')

+      {

+        password = s.Ptr(2);

+      }

+    }

+  }

+

+  FString path;

+  NDLL::MyGetModuleFileName(path);

+

+  FString fullPath;

+  if (!MyGetFullPathName(path, fullPath))

+  {

+    ShowErrorMessage(L"Error 1329484");

+    return 1;

+  }

+

+  CCodecs *codecs = new CCodecs;

+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;

+  HRESULT result = codecs->Load();

+  if (result != S_OK)

+  {

+    ErrorMessageForHRESULT(result);

+    return 1;

+  }

+

+  // COpenCallbackGUI openCallback;

+

+  // openCallback.PasswordIsDefined = !password.IsEmpty();

+  // openCallback.Password = password;

+

+  CExtractCallbackImp *ecs = new CExtractCallbackImp;

+  CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

+  ecs->Init();

+

+  #ifndef _NO_CRYPTO

+  ecs->PasswordIsDefined = !password.IsEmpty();

+  ecs->Password = password;

+  #endif

+

+  CExtractOptions eo;

+

+  FString dirPrefix;

+  if (!GetOnlyDirPrefix(path, dirPrefix))

+  {

+    ShowErrorMessage(L"Error 1329485");

+    return 1;

+  }

+

+  eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;

+  eo.YesToAll = assumeYes;

+  eo.OverwriteMode = assumeYes ?

+      NExtract::NOverwriteMode::kOverwrite :

+      NExtract::NOverwriteMode::kAsk;

+  eo.PathMode = NExtract::NPathMode::kFullPaths;

+  eo.TestMode = false;

+  

+  UStringVector v1, v2;

+  v1.Add(fs2us(fullPath));

+  v2.Add(fs2us(fullPath));

+  NWildcard::CCensorNode wildcardCensor;

+  wildcardCensor.AddItem(true, L"*", true, true, true, true);

+

+  bool messageWasDisplayed = false;

+  result = ExtractGUI(codecs,

+      CObjectVector<COpenType>(), CIntVector(),

+      v1, v2,

+      wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);

+

+  if (result == S_OK)

+  {

+    if (!ecs->IsOK())

+      return NExitCode::kFatalError;

+    return 0;

+  }

+  if (result == E_ABORT)

+    return NExitCode::kUserBreak;

+  if (!messageWasDisplayed)

+  {

+    if (result == S_FALSE)

+      ShowErrorMessage(L"Error in archive");

+    else

+      ErrorMessageForHRESULT(result);

+  }

+  if (result == E_OUTOFMEMORY)

+    return NExitCode::kMemoryError;

+  return NExitCode::kFatalError;

+}

+

+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError;

+

+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,

+  #ifdef UNDER_CE

+  LPWSTR

+  #else

+  LPSTR

+  #endif

+  /* lpCmdLine */, int /* nCmdShow */)

+{

+  g_hInstance = (HINSTANCE)hInstance;

+

+  NT_CHECK

+

+  try

+  {

+    return WinMain2();

+  }

+  catch(const CNewException &)

+  {

+    ErrorMessageForHRESULT(E_OUTOFMEMORY);

+    return NExitCode::kMemoryError;

+  }

+  catch(...)

+  {

+    ShowErrorMessage(kUnknownExceptionMessage);

+    return NExitCode::kFatalError;

+  }

+}

diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
new file mode 100644
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/SFXWin/StdAfx.h b/CPP/7zip/Bundles/SFXWin/StdAfx.h
new file mode 100644
index 0000000..f263ecb
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/StdAfx.h
@@ -0,0 +1,14 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/Common.h"

+

+#include <commctrl.h>

+#include <ShlObj.h>

+

+// #define printf(x) NO_PRINTF_(x)

+// #define sprintf(x) NO_SPRINTF_(x)

+

+#endif

diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
new file mode 100644
index 0000000..36806c8
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -0,0 +1,143 @@
+PROG = 7z.sfx

+CFLAGS = $(CFLAGS) \

+  -DNO_REGISTRY \

+  -DEXTRACT_ONLY \

+  -DNO_READ_FROM_CODER \

+  -D_SFX \

+

+!IFDEF UNDER_CE

+LIBS = $(LIBS) ceshell.lib Commctrl.lib

+!ELSE

+LIBS = $(LIBS) comctl32.lib comdlg32.lib

+!ENDIF

+

+CURRENT_OBJS = \

+  $O\SfxWin.obj \

+

+GUI_OBJS = \

+  $O\ExtractDialog.obj \

+  $O\ExtractGUI.obj \

+

+COMMON_OBJS = \

+  $O\CRC.obj \

+  $O\CommandLineParser.obj \

+  $O\IntToString.obj \

+  $O\NewHandler.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\CommonDialog.obj \

+  $O\DLL.obj \

+  $O\ErrorMsg.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\PropVariant.obj \

+  $O\PropVariantConv.obj \

+  $O\ResourceString.obj \

+  $O\Shell.obj \

+  $O\Synchronization.obj \

+  $O\Window.obj \

+

+WIN_CTRL_OBJS = \

+  $O\ComboBox.obj \

+  $O\Dialog.obj \

+  $O\ListView.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\CWrappers.obj \

+  $O\FilePathAutoRename.obj \

+  $O\FileStreams.obj \

+  $O\InBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\PropId.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveExtractCallback.obj \

+  $O\ArchiveOpenCallback.obj \

+  $O\DefaultName.obj \

+  $O\Extract.obj \

+  $O\ExtractingFilePath.obj \

+  $O\LoadCodecs.obj \

+  $O\OpenArchive.obj \

+

+EXPLORER_OBJS = \

+  $O\MyMessages.obj \

+

+FM_OBJS = \

+  $O\BrowseDialog.obj \

+  $O\ComboDialog.obj \

+  $O\ExtractCallback.obj \

+  $O\FormatUtils.obj \

+  $O\OverwriteDialog.obj \

+  $O\PasswordDialog.obj \

+  $O\ProgressDialog2.obj \

+  $O\SysIconUtils.obj \

+

+AR_OBJS = \

+  $O\SplitHandler.obj \

+

+AR_COMMON_OBJS = \

+  $O\CoderMixer2.obj \

+  $O\CoderMixer2MT.obj \

+  $O\CrossThreadProgress.obj \

+  $O\ItemNameUtils.obj \

+  $O\MultiStream.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\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaRegister.obj \

+  $O\PpmdDecoder.obj \

+  $O\PpmdRegister.obj \

+

+CRYPTO_OBJS = \

+  $O\7zAes.obj \

+  $O\7zAesRegister.obj \

+  $O\MyAes.obj \

+  

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra86.obj \

+  $O\CpuArch.obj \

+  $O\Lzma2Dec.obj \

+  $O\LzmaDec.obj \

+  $O\Ppmd7.obj \

+  $O\Ppmd7Dec.obj \

+  $O\Sha256.obj \

+  $O\Threads.obj \

+

+!include "../../Aes.mak"

+!include "../../Crc.mak"

+

+!include "../../7zip.mak"

diff --git a/CPP/7zip/Bundles/SFXWin/resource.h b/CPP/7zip/Bundles/SFXWin/resource.h
new file mode 100644
index 0000000..d9fae1b
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/resource.h
@@ -0,0 +1 @@
+#define IDI_ICON  1

diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc
new file mode 100644
index 0000000..3e24fa6
--- /dev/null
+++ b/CPP/7zip/Bundles/SFXWin/resource.rc
@@ -0,0 +1,50 @@
+#include "../../../../C/7zVersion.rc"

+#include "../../GuiCommon.rc"

+#include "../../UI/GUI/ExtractDialogRes.h"

+#include "../../UI/FileManager/PropertyNameRes.h"

+

+#include "resource.h"

+

+MY_VERSION_INFO_APP("7z SFX", "7z.sfx")

+

+#define xc 240

+#define yc 64

+

+IDI_ICON ICON "7z.ico"

+

+IDD_EXTRACT  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "7-Zip self-extracting archive"

+BEGIN

+  LTEXT          "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8

+  EDITTEXT       IDC_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL

+  PUSHBUTTON     "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP

+  DEFPUSHBUTTON  "Extract", IDOK,     bx2, by, bxs, bys, WS_GROUP

+  PUSHBUTTON     "Cancel",  IDCANCEL, bx1, by, bxs, bys

+END

+

+#ifdef UNDER_CE

+

+#undef xc

+#define xc 144

+

+IDD_EXTRACT_2  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "7-Zip self-extracting archive"

+BEGIN

+  LTEXT          "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8

+  EDITTEXT       IDC_EXTRACT_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL

+  PUSHBUTTON     "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP

+  DEFPUSHBUTTON  "Extract", IDOK,     bx2, by, bxs, bys, WS_GROUP

+  PUSHBUTTON     "Cancel",  IDCANCEL, bx1, by, bxs, bys

+END

+

+#endif

+

+#include "../../UI/FileManager/OverwriteDialog.rc"

+#include "../../UI/FileManager/PasswordDialog.rc"

+#include "../../UI/FileManager/ProgressDialog2.rc"

+#include "../../UI/GUI/Extract.rc"

+

+STRINGTABLE DISCARDABLE

+BEGIN

+  IDS_PROP_MTIME        "Modified"

+END

diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
old mode 100755
new mode 100644
index 66b8449..14424d5
--- a/CPP/7zip/Common/CWrappers.cpp
+++ b/CPP/7zip/Common/CWrappers.cpp
@@ -12,14 +12,14 @@
 

 #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)

 

-static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize)

+static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw()

 {

   CCompressProgressWrap *p = (CCompressProgressWrap *)pp;

   p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));

   return (SRes)p->Res;

 }

 

-CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress)

+CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw()

 {

   p.Progress = CompressProgress;

   Progress = progress;

@@ -30,29 +30,31 @@
 

 SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes)

 {

-  switch(res)

+  switch (res)

   {

     case S_OK: return SZ_OK;

     case E_OUTOFMEMORY: return SZ_ERROR_MEM;

     case E_INVALIDARG: return SZ_ERROR_PARAM;

     case E_ABORT: return SZ_ERROR_PROGRESS;

     case S_FALSE: return SZ_ERROR_DATA;

+    case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;

   }

   return defaultRes;

 }

 

-static SRes MyRead(void *object, void *data, size_t *size)

+static SRes MyRead(void *object, void *data, size_t *size) throw()

 {

   CSeqInStreamWrap *p = (CSeqInStreamWrap *)object;

   UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);

   p->Res = (p->Stream->Read(data, curSize, &curSize));

   *size = curSize;

+  p->Processed += curSize;

   if (p->Res == S_OK)

     return SZ_OK;

   return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);

 }

 

-static size_t MyWrite(void *object, const void *data, size_t size)

+static size_t MyWrite(void *object, const void *data, size_t size) throw()

 {

   CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object;

   if (p->Stream)

@@ -67,13 +69,14 @@
   return size;

 }

 

-CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream)

+CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw()

 {

   p.Read = MyRead;

   Stream = stream;

+  Processed = 0;

 }

 

-CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream)

+CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw()

 {

   p.Write = MyWrite;

   Stream = stream;

@@ -81,7 +84,7 @@
   Processed = 0;

 }

 

-HRESULT SResToHRESULT(SRes res)

+HRESULT SResToHRESULT(SRes res) throw()

 {

   switch(res)

   {

@@ -90,11 +93,12 @@
     case SZ_ERROR_PARAM: return E_INVALIDARG;

     case SZ_ERROR_PROGRESS: return E_ABORT;

     case SZ_ERROR_DATA: return S_FALSE;

+    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;

   }

   return E_FAIL;

 }

 

-static SRes InStreamWrap_Read(void *pp, void *data, size_t *size)

+static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw()

 {

   CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;

   UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);

@@ -103,7 +107,7 @@
   return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;

 }

 

-static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin)

+static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw()

 {

   CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;

   UInt32 moveMethod;

@@ -120,7 +124,7 @@
   return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;

 }

 

-CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream)

+CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) throw()

 {

   Stream = stream;

   p.Read = InStreamWrap_Read;

@@ -131,13 +135,13 @@
 

 /* ---------- CByteInBufWrap ---------- */

 

-void CByteInBufWrap::Free()

+void CByteInBufWrap::Free() throw()

 {

   ::MidFree(Buf);

   Buf = 0;

 }

 

-bool CByteInBufWrap::Alloc(UInt32 size)

+bool CByteInBufWrap::Alloc(UInt32 size) throw()

 {

   if (Buf == 0 || size != Size)

   {

@@ -148,7 +152,7 @@
   return (Buf != 0);

 }

 

-Byte CByteInBufWrap::ReadByteFromNewBlock()

+Byte CByteInBufWrap::ReadByteFromNewBlock() throw()

 {

   if (Res == S_OK)

   {

@@ -164,7 +168,7 @@
   return 0;

 }

 

-static Byte Wrap_ReadByte(void *pp)

+static Byte Wrap_ReadByte(void *pp) throw()

 {

   CByteInBufWrap *p = (CByteInBufWrap *)pp;

   if (p->Cur != p->Lim)

@@ -180,13 +184,13 @@
 

 /* ---------- CByteOutBufWrap ---------- */

 

-void CByteOutBufWrap::Free()

+void CByteOutBufWrap::Free() throw()

 {

   ::MidFree(Buf);

   Buf = 0;

 }

 

-bool CByteOutBufWrap::Alloc(size_t size)

+bool CByteOutBufWrap::Alloc(size_t size) throw()

 {

   if (Buf == 0 || size != Size)

   {

@@ -197,7 +201,7 @@
   return (Buf != 0);

 }

 

-HRESULT CByteOutBufWrap::Flush()

+HRESULT CByteOutBufWrap::Flush() throw()

 {

   if (Res == S_OK)

   {

@@ -210,7 +214,7 @@
   return Res;

 }

 

-static void Wrap_WriteByte(void *pp, Byte b)

+static void Wrap_WriteByte(void *pp, Byte b) throw()

 {

   CByteOutBufWrap *p = (CByteOutBufWrap *)pp;

   Byte *dest = p->Cur;

@@ -220,7 +224,7 @@
     p->Flush();

 }

 

-CByteOutBufWrap::CByteOutBufWrap(): Buf(0)

+CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)

 {

   p.Write = Wrap_WriteByte;

 }

diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h
old mode 100755
new mode 100644
index dd4197c..0872133
--- a/CPP/7zip/Common/CWrappers.h
+++ b/CPP/7zip/Common/CWrappers.h
@@ -11,7 +11,8 @@
   ICompressProgress p;

   ICompressProgressInfo *Progress;

   HRESULT Res;

-  CCompressProgressWrap(ICompressProgressInfo *progress);

+  

+  CCompressProgressWrap(ICompressProgressInfo *progress) throw();

 };

 

 struct CSeqInStreamWrap

@@ -19,7 +20,9 @@
   ISeqInStream p;

   ISequentialInStream *Stream;

   HRESULT Res;

-  CSeqInStreamWrap(ISequentialInStream *stream);

+  UInt64 Processed;

+  

+  CSeqInStreamWrap(ISequentialInStream *stream) throw();

 };

 

 struct CSeekInStreamWrap

@@ -27,7 +30,8 @@
   ISeekInStream p;

   IInStream *Stream;

   HRESULT Res;

-  CSeekInStreamWrap(IInStream *stream);

+  

+  CSeekInStreamWrap(IInStream *stream) throw();

 };

 

 struct CSeqOutStreamWrap

@@ -36,10 +40,11 @@
   ISequentialOutStream *Stream;

   HRESULT Res;

   UInt64 Processed;

-  CSeqOutStreamWrap(ISequentialOutStream *stream);

+  

+  CSeqOutStreamWrap(ISequentialOutStream *stream) throw();

 };

 

-HRESULT SResToHRESULT(SRes res);

+HRESULT SResToHRESULT(SRes res) throw();

 

 struct CByteInBufWrap

 {

@@ -54,9 +59,9 @@
   HRESULT Res;

   

   CByteInBufWrap();

-  ~CByteInBufWrap() { Free();  }

-  void Free();

-  bool Alloc(UInt32 size);

+  ~CByteInBufWrap() { Free(); }

+  void Free() throw();

+  bool Alloc(UInt32 size) throw();

   void Init()

   {

     Lim = Cur = Buf;

@@ -65,7 +70,7 @@
     Res = S_OK;

   }

   UInt64 GetProcessed() const { return Processed + (Cur - Buf); }

-  Byte ReadByteFromNewBlock();

+  Byte ReadByteFromNewBlock() throw();

   Byte ReadByte()

   {

     if (Cur != Lim)

@@ -85,10 +90,10 @@
   UInt64 Processed;

   HRESULT Res;

   

-  CByteOutBufWrap();

-  ~CByteOutBufWrap() { Free();  }

-  void Free();

-  bool Alloc(size_t size);

+  CByteOutBufWrap() throw();

+  ~CByteOutBufWrap() { Free(); }

+  void Free() throw();

+  bool Alloc(size_t size) throw();

   void Init()

   {

     Cur = Buf;

@@ -97,7 +102,7 @@
     Res = S_OK;

   }

   UInt64 GetProcessed() const { return Processed + (Cur - Buf); }

-  HRESULT Flush();

+  HRESULT Flush() throw();

   void WriteByte(Byte b)

   {

     *Cur++ = b;

diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
old mode 100755
new mode 100644
index 55bad3c..8be4e05
--- a/CPP/7zip/Common/CreateCoder.cpp
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -13,12 +13,21 @@
 static const unsigned int kNumCodecsMax = 64;

 unsigned int g_NumCodecs = 0;

 const CCodecInfo *g_Codecs[kNumCodecsMax];

-void RegisterCodec(const CCodecInfo *codecInfo)

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

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

 {

@@ -46,56 +55,74 @@
   return S_OK;

 }

 

-HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)

+HRESULT CExternalCodecs::LoadCodecs()

 {

-  UInt32 num;

-  RINOK(codecsInfo->GetNumberOfMethods(&num));

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

+  if (GetCodecs)

   {

-    CCodecInfoEx info;

-    NWindows::NCOM::CPropVariant prop;

-    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));

-    // if (prop.vt != VT_BSTR)

-    // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);

-    // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);

-    if (prop.vt != VT_UI8)

+    UInt32 num;

+    RINOK(GetCodecs->GetNumberOfMethods(&num));

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

     {

-      continue; // old Interface

-      // return E_INVALIDARG;

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

+      

+      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop));

+      if (prop.vt == VT_BSTR)

+        info.Name = prop.bstrVal;

+      else if (prop.vt != VT_EMPTY)

+        return E_INVALIDARG;

+      

+      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams));

+      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams));

+      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));

+      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));

+      

+      Codecs.Add(info);

     }

-    info.Id = prop.uhVal.QuadPart;

-    prop.Clear();

-    

-    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));

-    if (prop.vt == VT_BSTR)

-      info.Name = prop.bstrVal;

-    else if (prop.vt != VT_EMPTY)

-      return E_INVALIDARG;;

-    

-    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));

-    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));

-    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));

-    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));

-    

-    externalCodecs.Add(info);

+  }

+  if (GetHashers)

+  {

+    UInt32 num = GetHashers->GetNumHashers();

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

+      

+      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop));

+      if (prop.vt == VT_BSTR)

+        info.Name = prop.bstrVal;

+      else if (prop.vt != VT_EMPTY)

+        return E_INVALIDARG;

+      

+      Hashers.Add(info);

+    }

   }

   return S_OK;

 }

 

 #endif

 

-bool FindMethod(

-  #ifdef EXTERNAL_CODECS

-  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,

-  #endif

-  const UString &name,

-  CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)

+bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS

+    const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)

 {

   UInt32 i;

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

   {

     const CCodecInfo &codec = *g_Codecs[i];

-    if (name.CompareNoCase(codec.Name) == 0)

+    if (name.IsEqualToNoCase(codec.Name))

     {

       methodId = codec.Id;

       numInStreams = codec.NumInStreams;

@@ -104,11 +131,11 @@
     }

   }

   #ifdef EXTERNAL_CODECS

-  if (externalCodecs)

-    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+  if (__externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

     {

-      const CCodecInfoEx &codec = (*externalCodecs)[i];

-      if (codec.Name.CompareNoCase(name) == 0)

+      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

+      if (codec.Name.IsEqualToNoCase(name))

       {

         methodId = codec.Id;

         numInStreams = codec.NumInStreams;

@@ -120,11 +147,8 @@
   return false;

 }

 

-bool FindMethod(

-  #ifdef EXTERNAL_CODECS

-  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,

-  #endif

-  CMethodId methodId, UString &name)

+bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS

+   CMethodId methodId, UString &name)

 {

   UInt32 i;

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

@@ -137,10 +161,10 @@
     }

   }

   #ifdef EXTERNAL_CODECS

-  if (externalCodecs)

-    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+  if (__externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

     {

-      const CCodecInfoEx &codec = (*externalCodecs)[i];

+      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

       if (methodId == codec.Id)

       {

         name = codec.Name;

@@ -151,6 +175,49 @@
   return false;

 }

 

+bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS

+  const UString &name,

+  CMethodId &methodId)

+{

+  UInt32 i;

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

+  {

+    const CHasherInfo &codec = *g_Hashers[i];

+    if (name.IsEqualToNoCase(codec.Name))

+    {

+      methodId = codec.Id;

+      return true;

+    }

+  }

+  #ifdef EXTERNAL_CODECS

+  if (__externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+    {

+      const CHasherInfoEx &codec = __externalCodecs->Hashers[i];

+      if (codec.Name.IsEqualToNoCase(name))

+      {

+        methodId = codec.Id;

+        return true;

+      }

+    }

+  #endif

+  return false;

+}

+

+void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS

+    CRecordVector<CMethodId> &methods)

+{

+  methods.ClearAndSetSize(g_NumHashers);

+  UInt32 i;

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

+    methods[i] = (*g_Hashers[i]).Id;

+  #ifdef EXTERNAL_CODECS

+  if (__externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+      methods.Add(__externalCodecs->Hashers[i].Id);

+  #endif

+}

+

 HRESULT CreateCoder(

   DECL_EXTERNAL_CODECS_LOC_VARS

   CMethodId methodId,

@@ -159,7 +226,6 @@
   CMyComPtr<ICompressCoder2> &coder2,

   bool encode, bool onlyCoder)

 {

-  bool created = false;

   UInt32 i;

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

   {

@@ -174,7 +240,6 @@
           if (codec.IsFilter) filter = (ICompressFilter *)p;

           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

           else coder2 = (ICompressCoder2 *)p;

-          created = (p != 0);

           break;

         }

       }

@@ -185,17 +250,16 @@
           if (codec.IsFilter) filter = (ICompressFilter *)p;

           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

           else coder2 = (ICompressCoder2 *)p;

-          created = (p != 0);

           break;

         }

     }

   }

 

   #ifdef EXTERNAL_CODECS

-  if (!created && externalCodecs)

-    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+  if (!filter && !coder && !coder2 && __externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)

     {

-      const CCodecInfoEx &codec = (*externalCodecs)[i];

+      const CCodecInfoEx &codec = __externalCodecs->Codecs[i];

       if (codec.Id == methodId)

       {

         if (encode)

@@ -204,17 +268,17 @@
           {

             if (codec.IsSimpleCodec())

             {

-              HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);

+              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(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));

+                RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));

               }

             }

             else

             {

-              RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));

+              RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));

             }

             break;

           }

@@ -224,17 +288,17 @@
           {

             if (codec.IsSimpleCodec())

             {

-              HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);

+              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(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));

+                RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));

               }

             }

             else

             {

-              RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));

+              RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));

             }

             break;

           }

@@ -291,3 +355,37 @@
     methodId,

     filter, coder, coder2, encode, false);

 }

+

+HRESULT CreateHasher(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  UString &name,

+  CMyComPtr<IHasher> &hasher)

+{

+  UInt32 i;

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

+  {

+    const CHasherInfo &codec = *g_Hashers[i];

+    if (codec.Id == methodId)

+    {

+      hasher = (IHasher *)codec.CreateHasher();

+      name = codec.Name;

+      break;

+    }

+  }

+

+  #ifdef EXTERNAL_CODECS

+  if (!hasher && __externalCodecs)

+    for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)

+    {

+      const CHasherInfoEx &codec = __externalCodecs->Hashers[i];

+      if (codec.Id == methodId)

+      {

+        name = codec.Name;

+        return __externalCodecs->GetHashers->CreateHasher(i, &hasher);

+      }

+    }

+  #endif

+

+  return S_OK;

+}

diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
old mode 100755
new mode 100644
index 9a59d45..50dc148
--- a/CPP/7zip/Common/CreateCoder.h
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -19,27 +19,43 @@
   UInt32 NumOutStreams;

   bool EncoderIsAssigned;

   bool DecoderIsAssigned;

+  

   bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }

   CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}

 };

 

-HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs);

+struct CHasherInfoEx

+{

+  UString Name;

+  CMethodId Id;

+};

 

 #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,

 #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)

 #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);

 #define IMPL_ISetCompressCodecsInfo2(x) \

 STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \

-  COM_TRY_BEGIN _codecsInfo = compressCodecsInfo;  return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }

+  COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo;  return __externalCodecs.LoadCodecs(); COM_TRY_END }

 #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)

 

-#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs

+struct CExternalCodecs

+{

+  CMyComPtr<ICompressCodecsInfo> GetCodecs;

+  CMyComPtr<IHashers> GetHashers;

 

-#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs;

+  CObjectVector<CCodecInfoEx> Codecs;

+  CObjectVector<CHasherInfoEx> Hashers;

+

+  HRESULT LoadCodecs();

+};

+

+#define EXTERNAL_CODECS_VARS2 &__externalCodecs

+

+#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;

 #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,

 

-#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs

-#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs

+#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs

+#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs

 

 #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,

 #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,

@@ -68,6 +84,13 @@
   DECL_EXTERNAL_CODECS_LOC_VARS

   CMethodId methodId, UString &name);

 

+bool FindHashMethod(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  const UString &name, CMethodId &methodId);

+

+void GetHashMethods(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CRecordVector<CMethodId> &methods);

 

 HRESULT CreateCoder(

   DECL_EXTERNAL_CODECS_LOC_VARS

@@ -95,4 +118,10 @@
   CMyComPtr<ICompressFilter> &filter,

   bool encode);

 

+HRESULT CreateHasher(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  UString &name,

+  CMyComPtr<IHasher> &hacher);

+

 #endif

diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
old mode 100755
new mode 100644
index d357c5b..db151c0
--- a/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -2,19 +2,19 @@
 

 #include "StdAfx.h"

 

-#include "Common/Defs.h"

-#include "Common/IntToString.h"

+#include "../../Common/Defs.h"

+#include "../../Common/IntToString.h"

 

-#include "Windows/FileFind.h"

+#include "../../Windows/FileFind.h"

 

 #include "FilePathAutoRename.h"

 

 using namespace NWindows;

 

-static bool MakeAutoName(const UString &name,

-    const UString &extension, unsigned value, UString &path)

+static bool MakeAutoName(const FString &name,

+    const FString &extension, unsigned value, FString &path)

 {

-  wchar_t number[16];

+  FChar number[16];

   ConvertUInt32ToString(value, number);

   path = name;

   path += number;

@@ -22,22 +22,22 @@
   return NFile::NFind::DoesFileOrDirExist(path);

 }

 

-bool AutoRenamePath(UString &fullProcessedPath)

+bool AutoRenamePath(FString &fullProcessedPath)

 {

-  UString path;

-  int dotPos = fullProcessedPath.ReverseFind(L'.');

+  FString path;

+  int dotPos = fullProcessedPath.ReverseFind(FTEXT('.'));

 

-  int slashPos = fullProcessedPath.ReverseFind(L'/');

+  int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));

   #ifdef _WIN32

-  int slash1Pos = fullProcessedPath.ReverseFind(L'\\');

+  int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));

   slashPos = MyMax(slashPos, slash1Pos);

   #endif

 

-  UString name, extension;

+  FString name, extension;

   if (dotPos > slashPos && dotPos > 0)

   {

-    name = fullProcessedPath.Left(dotPos);

-    extension = fullProcessedPath.Mid(dotPos);

+    name.SetFrom(fullProcessedPath, dotPos);

+    extension = fullProcessedPath.Ptr(dotPos);

   }

   else

     name = fullProcessedPath;

diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h
old mode 100755
new mode 100644
index 4303962..cb2d71b
--- a/CPP/7zip/Common/FilePathAutoRename.h
+++ b/CPP/7zip/Common/FilePathAutoRename.h
@@ -1,10 +1,10 @@
-// Util/FilePathAutoRename.h

+// FilePathAutoRename.h

 

-#ifndef __FILEPATHAUTORENAME_H

-#define __FILEPATHAUTORENAME_H

+#ifndef __FILE_PATH_AUTO_RENAME_H

+#define __FILE_PATH_AUTO_RENAME_H

 

-#include "Common/MyString.h"

+#include "../../Common/MyString.h"

 

-bool AutoRenamePath(UString &fullProcessedPath);

+bool AutoRenamePath(FString &fullProcessedPath);

 

 #endif

diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
old mode 100755
new mode 100644
index de49911..96f79a0
--- a/CPP/7zip/Common/FileStreams.cpp
+++ b/CPP/7zip/Common/FileStreams.cpp
@@ -29,42 +29,15 @@
   #endif

 }

 

-bool CInFileStream::Open(LPCTSTR fileName)

-{

-  return File.Open(fileName);

-}

-

-#ifdef USE_WIN_FILE

-#ifndef _UNICODE

-bool CInFileStream::Open(LPCWSTR fileName)

-{

-  return File.Open(fileName);

-}

-#endif

-#endif

-

-bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)

-{

-  return File.OpenShared(fileName, shareForWrite);

-}

-

-#ifdef USE_WIN_FILE

-#ifndef _UNICODE

-bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)

-{

-  return File.OpenShared(fileName, shareForWrite);

-}

-#endif

-#endif

-

 #ifdef SUPPORT_DEVICE_FILE

 

 static const UInt32 kClusterSize = 1 << 18;

 CInFileStream::CInFileStream():

   VirtPos(0),

   PhyPos(0),

-  Buffer(0),

-  BufferSize(0)

+  Buf(0),

+  BufSize(0),

+  SupportHardLinks(false)

 {

 }

 

@@ -73,7 +46,7 @@
 CInFileStream::~CInFileStream()

 {

   #ifdef SUPPORT_DEVICE_FILE

-  MidFree(Buffer);

+  MidFree(Buf);

   #endif

 }

 

@@ -82,41 +55,41 @@
   #ifdef USE_WIN_FILE

   

   #ifdef SUPPORT_DEVICE_FILE

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   if (size == 0)

     return S_OK;

   if (File.IsDeviceFile)

   {

-    if (File.LengthDefined)

+    if (File.SizeDefined)

     {

-      if (VirtPos >= File.Length)

-        return VirtPos == File.Length ? S_OK : E_FAIL;

-      UInt64 rem = File.Length - VirtPos;

+      if (VirtPos >= File.Size)

+        return VirtPos == File.Size ? S_OK : E_FAIL;

+      UInt64 rem = File.Size - VirtPos;

       if (size > rem)

         size = (UInt32)rem;

     }

     for (;;)

     {

       const UInt32 mask = kClusterSize - 1;

-      UInt64 mask2 = ~(UInt64)mask;

+      const UInt64 mask2 = ~(UInt64)mask;

       UInt64 alignedPos = VirtPos & mask2;

-      if (BufferSize > 0 && BufferStartPos == alignedPos)

+      if (BufSize > 0 && BufStartPos == alignedPos)

       {

         UInt32 pos = (UInt32)VirtPos & mask;

-        if (pos >= BufferSize)

+        if (pos >= BufSize)

           return S_OK;

-        UInt32 rem = MyMin(BufferSize - pos, size);

-        memcpy(data, Buffer + pos, rem);

+        UInt32 rem = MyMin(BufSize - pos, size);

+        memcpy(data, Buf + pos, rem);

         VirtPos += rem;

-        if (processedSize != NULL)

+        if (processedSize)

           *processedSize += rem;

         return S_OK;

       }

       

-      bool useBuffer = false;

+      bool useBuf = false;

       if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )

-        useBuffer = true;

+        useBuf = true;

       else

       {

         UInt64 end = VirtPos + size;

@@ -124,12 +97,12 @@
         {

           end &= mask2;

           if (end <= VirtPos)

-            useBuffer = true;

+            useBuf = true;

           else

             size = (UInt32)(end - VirtPos);

         }

       }

-      if (!useBuffer)

+      if (!useBuf)

         break;

       if (alignedPos != PhyPos)

       {

@@ -140,24 +113,24 @@
         PhyPos = realNewPosition;

       }

 

-      BufferStartPos = alignedPos;

+      BufStartPos = alignedPos;

       UInt32 readSize = kClusterSize;

-      if (File.LengthDefined)

-        readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize);

+      if (File.SizeDefined)

+        readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);

 

-      if (Buffer == 0)

+      if (!Buf)

       {

-        Buffer = (Byte *)MidAlloc(kClusterSize);

-        if (Buffer == 0)

+        Buf = (Byte *)MidAlloc(kClusterSize);

+        if (!Buf)

           return E_OUTOFMEMORY;

       }

-      bool result = File.Read1(Buffer, readSize, BufferSize);

+      bool result = File.Read1(Buf, readSize, BufSize);

       if (!result)

         return ConvertBoolToHRESULT(result);

 

-      if (BufferSize == 0)

+      if (BufSize == 0)

         return S_OK;

-      PhyPos += BufferSize;

+      PhyPos += BufSize;

     }

 

     if (VirtPos != PhyPos)

@@ -173,7 +146,7 @@
 

   UInt32 realProcessedSize;

   bool result = File.ReadPart(data, size, realProcessedSize);

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = realProcessedSize;

   #ifdef SUPPORT_DEVICE_FILE

   VirtPos += realProcessedSize;

@@ -183,12 +156,12 @@
   

   #else

   

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   ssize_t res = File.Read(data, (size_t)size);

   if (res == -1)

     return E_FAIL;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = (UInt32)res;

   return S_OK;

 

@@ -198,10 +171,13 @@
 #ifdef UNDER_CE

 STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  size_t s2 = fread(data, 1, size, stdout);

-  if (processedSize != 0)

+  size_t s2 = fread(data, 1, size, stdin);

+  int error = ferror(stdin);

+  if (processedSize)

     *processedSize = s2;

-  return (s2 = size) ? S_OK : E_FAIL;

+  if (s2 <= size && error == 0)

+    return S_OK;

+  return E_FAIL;

 }

 #else

 STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

@@ -213,7 +189,7 @@
   if (sizeTemp > size)

     sizeTemp = size;

   BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = realProcessedSize;

   if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)

     return S_OK;

@@ -221,7 +197,7 @@
   

   #else

 

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   ssize_t res;

   do

@@ -231,7 +207,7 @@
   while (res < 0 && (errno == EINTR));

   if (res == -1)

     return E_FAIL;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = (UInt32)res;

   return S_OK;

   

@@ -240,8 +216,7 @@
   

 #endif

 

-STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,

-    UInt64 *newPosition)

+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

   if (seekOrigin >= 3)

     return STG_E_INVALIDFUNCTION;

@@ -249,19 +224,20 @@
   #ifdef USE_WIN_FILE

 

   #ifdef SUPPORT_DEVICE_FILE

-  if (File.IsDeviceFile)

+  if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))

   {

-    UInt64 newVirtPos = offset;

-    switch(seekOrigin)

+    switch (seekOrigin)

     {

       case STREAM_SEEK_SET: break;

-      case STREAM_SEEK_CUR: newVirtPos += VirtPos; break;

-      case STREAM_SEEK_END: newVirtPos += File.Length; break;

+      case STREAM_SEEK_CUR: offset += VirtPos; break;

+      case STREAM_SEEK_END: offset += File.Size; break;

       default: return STG_E_INVALIDFUNCTION;

     }

-    VirtPos = newVirtPos;

+    if (offset < 0)

+      return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+    VirtPos = offset;

     if (newPosition)

-      *newPosition = newVirtPos;

+      *newPosition = offset;

     return S_OK;

   }

   #endif

@@ -273,16 +249,16 @@
   PhyPos = VirtPos = realNewPosition;

   #endif

 

-  if (newPosition != NULL)

+  if (newPosition)

     *newPosition = realNewPosition;

   return ConvertBoolToHRESULT(result);

   

   #else

   

-  off_t res = File.Seek(offset, seekOrigin);

+  off_t res = File.Seek((off_t)offset, seekOrigin);

   if (res == -1)

     return E_FAIL;

-  if (newPosition != NULL)

+  if (newPosition)

     *newPosition = (UInt64)res;

   return S_OK;

   

@@ -294,6 +270,43 @@
   return ConvertBoolToHRESULT(File.GetLength(*size));

 }

 

+#ifdef USE_WIN_FILE

+

+STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)

+{

+  BY_HANDLE_FILE_INFORMATION info;

+  if (File.GetFileInformation(&info))

+  {

+    if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;

+    if (cTime) *cTime = info.ftCreationTime;

+    if (aTime) *aTime = info.ftLastAccessTime;

+    if (mTime) *mTime = info.ftLastWriteTime;

+    if (attrib) *attrib = info.dwFileAttributes;

+    return S_OK;

+  }

+  return GetLastError();

+}

+

+STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)

+{

+  BY_HANDLE_FILE_INFORMATION info;

+  if (File.GetFileInformation(&info))

+  {

+    props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;

+    props->VolID = info.dwVolumeSerialNumber;

+    props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;

+    props->FileID_High = 0;

+    props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;

+    props->Attrib = info.dwFileAttributes;

+    props->CTime = info.ftCreationTime;

+    props->ATime = info.ftLastAccessTime;

+    props->MTime = info.ftLastWriteTime;

+    return S_OK;

+  }

+  return GetLastError();

+}

+

+#endif

 

 //////////////////////////

 // COutFileStream

@@ -310,18 +323,18 @@
   UInt32 realProcessedSize;

   bool result = File.WritePart(data, size, realProcessedSize);

   ProcessedSize += realProcessedSize;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = realProcessedSize;

   return ConvertBoolToHRESULT(result);

   

   #else

   

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   ssize_t res = File.Write(data, (size_t)size);

   if (res == -1)

     return E_FAIL;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = (UInt32)res;

   ProcessedSize += res;

   return S_OK;

@@ -337,16 +350,16 @@
 

   UInt64 realNewPosition;

   bool result = File.Seek(offset, seekOrigin, realNewPosition);

-  if (newPosition != NULL)

+  if (newPosition)

     *newPosition = realNewPosition;

   return ConvertBoolToHRESULT(result);

   

   #else

   

-  off_t res = File.Seek(offset, seekOrigin);

+  off_t res = File.Seek((off_t)offset, seekOrigin);

   if (res == -1)

     return E_FAIL;

-  if (newPosition != NULL)

+  if (newPosition)

     *newPosition = (UInt64)res;

   return S_OK;

   

@@ -372,14 +385,14 @@
 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

   size_t s2 = fwrite(data, 1, size, stdout);

-  if (processedSize != 0)

+  if (processedSize)

     *processedSize = s2;

-  return (s2 = size) ? S_OK : E_FAIL;

+  return (s2 == size) ? S_OK : E_FAIL;

 }

 #else

 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

 

   #ifdef _WIN32

@@ -396,7 +409,7 @@
         data, sizeTemp, (DWORD *)&realProcessedSize, NULL);

     size -= realProcessedSize;

     data = (const void *)((const Byte *)data + realProcessedSize);

-    if (processedSize != NULL)

+    if (processedSize)

       *processedSize += realProcessedSize;

   }

   return ConvertBoolToHRESULT(res != FALSE);

@@ -411,7 +424,7 @@
   while (res < 0 && (errno == EINTR));

   if (res == -1)

     return E_FAIL;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = (UInt32)res;

   return S_OK;

   

diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
old mode 100755
new mode 100644
index f979294..1cd2d1a
--- a/CPP/7zip/Common/FileStreams.h
+++ b/CPP/7zip/Common/FileStreams.h
@@ -1,12 +1,14 @@
 // FileStreams.h

 

-#ifndef __FILESTREAMS_H

-#define __FILESTREAMS_H

+#ifndef __FILE_STREAMS_H

+#define __FILE_STREAMS_H

 

 #ifdef _WIN32

 #define USE_WIN_FILE

 #endif

 

+#include "../../Common/MyString.h"

+

 #ifdef USE_WIN_FILE

 #include "../../Windows/FileIO.h"

 #else

@@ -20,47 +22,63 @@
 class CInFileStream:

   public IInStream,

   public IStreamGetSize,

+  #ifdef USE_WIN_FILE

+  public IStreamGetProps,

+  public IStreamGetProps2,

+  #endif

   public CMyUnknownImp

 {

 public:

   #ifdef USE_WIN_FILE

   NWindows::NFile::NIO::CInFile File;

+  

   #ifdef SUPPORT_DEVICE_FILE

   UInt64 VirtPos;

   UInt64 PhyPos;

-  UInt64 BufferStartPos;

-  Byte *Buffer;

-  UInt32 BufferSize;

+  UInt64 BufStartPos;

+  Byte *Buf;

+  UInt32 BufSize;

   #endif

+

   #else

   NC::NFile::NIO::CInFile File;

   #endif

+

+  bool SupportHardLinks;

+  

   virtual ~CInFileStream();

 

   #ifdef SUPPORT_DEVICE_FILE

   CInFileStream();

   #endif

   

-  bool Open(LPCTSTR fileName);

-  #ifdef USE_WIN_FILE

-  #ifndef _UNICODE

-  bool Open(LPCWSTR fileName);

-  #endif

-  #endif

+  bool Open(CFSTR fileName)

+  {

+    return File.Open(fileName);

+  }

+  

+  bool OpenShared(CFSTR fileName, bool shareForWrite)

+  {

+    return File.OpenShared(fileName, shareForWrite);

+  }

 

-  bool OpenShared(LPCTSTR fileName, bool shareForWrite);

+  MY_QUERYINTERFACE_BEGIN2(IInStream)

+  MY_QUERYINTERFACE_ENTRY(IStreamGetSize)

   #ifdef USE_WIN_FILE

-  #ifndef _UNICODE

-  bool OpenShared(LPCWSTR fileName, bool shareForWrite);

+  MY_QUERYINTERFACE_ENTRY(IStreamGetProps)

+  MY_QUERYINTERFACE_ENTRY(IStreamGetProps2)

   #endif

-  #endif

-

-  MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

 

   STDMETHOD(GetSize)(UInt64 *size);

+  #ifdef USE_WIN_FILE

+  STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib);

+  STDMETHOD(GetProps2)(CStreamFileProps *props);

+  #endif

 };

 

 class CStdInFileStream:

@@ -78,37 +96,23 @@
   public IOutStream,

   public CMyUnknownImp

 {

+public:

   #ifdef USE_WIN_FILE

   NWindows::NFile::NIO::COutFile File;

   #else

   NC::NFile::NIO::COutFile File;

   #endif

-public:

   virtual ~COutFileStream() {}

-  bool Create(LPCTSTR fileName, bool createAlways)

+  bool Create(CFSTR fileName, bool createAlways)

   {

     ProcessedSize = 0;

     return File.Create(fileName, createAlways);

   }

-  bool Open(LPCTSTR fileName, DWORD creationDisposition)

+  bool Open(CFSTR fileName, DWORD creationDisposition)

   {

     ProcessedSize = 0;

     return File.Open(fileName, creationDisposition);

   }

-  #ifdef USE_WIN_FILE

-  #ifndef _UNICODE

-  bool Create(LPCWSTR fileName, bool createAlways)

-  {

-    ProcessedSize = 0;

-    return File.Create(fileName, createAlways);

-  }

-  bool Open(LPCWSTR fileName, DWORD creationDisposition)

-  {

-    ProcessedSize = 0;

-    return File.Open(fileName, creationDisposition);

-  }

-  #endif

-  #endif

 

   HRESULT Close();

   

diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
old mode 100755
new mode 100644
index 03a2aa0..bed8298
--- a/CPP/7zip/Common/FilterCoder.cpp
+++ b/CPP/7zip/Common/FilterCoder.cpp
@@ -153,10 +153,16 @@
 }

 

 

-STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)

+void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream)

 {

   _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;

   _inStream = inStream;

+  Init2();

+}

+

+STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)

+{

+  SetInStream_NoSubFilterInit(inStream);

   return Init();

 }

 

@@ -210,10 +216,22 @@
 }

 

 #ifndef _NO_CRYPTO

+

 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)

 {

   return _setPassword->CryptoSetPassword(data, size);

 }

+

+STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)

+{

+  return _cryptoProperties->SetKey(data, size);

+}

+

+STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)

+{

+  return _cryptoProperties->SetInitVector(data, size);

+}

+

 #endif

 

 #ifndef EXTRACT_ONLY

diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
old mode 100755
new mode 100644
index 1b0125d..35e877f
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -7,9 +7,9 @@
 #include "../ICoder.h"

 #include "../IPassword.h"

 

-#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \

-{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \

-*outObject = (void *)(i *)this; AddRef(); return S_OK; }

+#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; }

 

 class CFilterCoder:

   public ICompressCoder,

@@ -21,6 +21,7 @@
 

   #ifndef _NO_CRYPTO

   public ICryptoSetPassword,

+  public ICryptoProperties,

   #endif

   #ifndef EXTRACT_ONLY

   public ICompressSetCoderProperties,

@@ -42,14 +43,20 @@
   UInt64 _outSize;

   UInt64 _nowPos64;

 

-  HRESULT Init()

+  void Init2()

   {

     _nowPos64 = 0;

     _outSizeIsDefined = false;

+  }

+

+  HRESULT Init()

+  {

+    Init2();

     return Filter->Init();

   }

 

   CMyComPtr<ICryptoSetPassword> _setPassword;

+  CMyComPtr<ICryptoProperties> _cryptoProperties;

   #ifndef EXTRACT_ONLY

   CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;

   CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;

@@ -74,6 +81,7 @@
 

     #ifndef _NO_CRYPTO

     MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)

+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties)

     #endif

 

     #ifndef EXTRACT_ONLY

@@ -98,6 +106,9 @@
 

   #ifndef _NO_CRYPTO

   STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);

+

+  STDMETHOD(SetKey)(const Byte *data, UInt32 size);

+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);

   #endif

   #ifndef EXTRACT_ONLY

   STDMETHOD(SetCoderProperties)(const PROPID *propIDs,

@@ -107,6 +118,9 @@
   STDMETHOD(ResetInitVector)();

   #endif

   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+

+  void SetInStream_NoSubFilterInit(ISequentialInStream *inStream);

+

 };

 

 class CInStreamReleaser

diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
old mode 100755
new mode 100644
index 3f84f48..7765d1b
--- a/CPP/7zip/Common/InBuffer.cpp
+++ b/CPP/7zip/Common/InBuffer.cpp
@@ -6,50 +6,49 @@
 

 #include "InBuffer.h"

 

-CInBuffer::CInBuffer():

-  _buffer(0),

-  _bufferLimit(0),

-  _bufferBase(0),

+CInBufferBase::CInBufferBase() throw():

+  _buf(0),

+  _bufLim(0),

+  _bufBase(0),

   _stream(0),

-  _bufferSize(0)

+  _processedSize(0),

+  _bufSize(0),

+  _wasFinished(false),

+  NumExtraBytes(0)

 {}

 

-bool CInBuffer::Create(UInt32 bufferSize)

+bool CInBuffer::Create(size_t bufSize) throw()

 {

-  const UInt32 kMinBlockSize = 1;

-  if (bufferSize < kMinBlockSize)

-    bufferSize = kMinBlockSize;

-  if (_bufferBase != 0 && _bufferSize == bufferSize)

+  const unsigned kMinBlockSize = 1;

+  if (bufSize < kMinBlockSize)

+    bufSize = kMinBlockSize;

+  if (_bufBase != 0 && _bufSize == bufSize)

     return true;

   Free();

-  _bufferSize = bufferSize;

-  _bufferBase = (Byte *)::MidAlloc(bufferSize);

-  return (_bufferBase != 0);

+  _bufSize = bufSize;

+  _bufBase = (Byte *)::MidAlloc(bufSize);

+  return (_bufBase != 0);

 }

 

-void CInBuffer::Free()

+void CInBuffer::Free() throw()

 {

-  ::MidFree(_bufferBase);

-  _bufferBase = 0;

+  ::MidFree(_bufBase);

+  _bufBase = 0;

 }

 

-void CInBuffer::SetStream(ISequentialInStream *stream)

-{

-  _stream = stream;

-}

-

-void CInBuffer::Init()

+void CInBufferBase::Init() throw()

 {

   _processedSize = 0;

-  _buffer = _bufferBase;

-  _bufferLimit = _buffer;

+  _buf = _bufBase;

+  _bufLim = _buf;

   _wasFinished = false;

   #ifdef _NO_EXCEPTIONS

   ErrorCode = S_OK;

   #endif

+  NumExtraBytes = 0;

 }

 

-bool CInBuffer::ReadBlock()

+bool CInBufferBase::ReadBlock()

 {

   #ifdef _NO_EXCEPTIONS

   if (ErrorCode != S_OK)

@@ -57,27 +56,80 @@
   #endif

   if (_wasFinished)

     return false;

-  _processedSize += (_buffer - _bufferBase);

-  UInt32 numProcessedBytes;

-  HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);

+  _processedSize += (_buf - _bufBase);

+  _buf = _bufBase;

+  _bufLim = _bufBase;

+  UInt32 processed;

+  // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))

+  HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);

   #ifdef _NO_EXCEPTIONS

   ErrorCode = result;

   #else

   if (result != S_OK)

     throw CInBufferException(result);

   #endif

-  _buffer = _bufferBase;

-  _bufferLimit = _buffer + numProcessedBytes;

-  _wasFinished = (numProcessedBytes == 0);

-  return (!_wasFinished);

+  _bufLim = _buf + processed;

+  _wasFinished = (processed == 0);

+  return !_wasFinished;

 }

 

-Byte CInBuffer::ReadBlock2()

+bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)

 {

   if (!ReadBlock())

   {

-    _processedSize++;

+    NumExtraBytes++;

+    b = 0xFF;

+    return false;

+  }

+  b = *_buf++;

+  return true;

+}

+

+Byte CInBufferBase::ReadByte_FromNewBlock()

+{

+  if (!ReadBlock())

+  {

+    NumExtraBytes++;

     return 0xFF;

   }

-  return *_buffer++;

+  return *_buf++;

+}

+

+size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)

+{

+  if ((size_t)(_bufLim - _buf) >= size)

+  {

+    const Byte *src = _buf;

+    for (size_t i = 0; i < size; i++)

+      buf[i] = src[i];

+    _buf += size;

+    return size;

+  }

+  for (size_t i = 0; i < size; i++)

+  {

+    if (_buf >= _bufLim)

+      if (!ReadBlock())

+        return i;

+    buf[i] = *_buf++;

+  }

+  return size;

+}

+

+size_t CInBufferBase::Skip(size_t size)

+{

+  size_t processed = 0;

+  for (;;)

+  {

+    size_t rem = (_bufLim - _buf);

+    if (rem >= size)

+    {

+      _buf += size;

+      return processed + size;

+    }

+    _buf += rem;

+    processed += rem;

+    size -= rem;

+    if (!ReadBlock())

+      return processed;

+  }

 }

diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h
old mode 100755
new mode 100644
index cdd50f1..f353b37
--- a/CPP/7zip/Common/InBuffer.h
+++ b/CPP/7zip/Common/InBuffer.h
@@ -1,11 +1,10 @@
 // InBuffer.h

 

-#ifndef __INBUFFER_H

-#define __INBUFFER_H

+#ifndef __IN_BUFFER_H

+#define __IN_BUFFER_H

 

-#include "../IStream.h"

-#include "../../Common/MyCom.h"

 #include "../../Common/MyException.h"

+#include "../IStream.h"

 

 #ifndef _NO_EXCEPTIONS

 struct CInBufferException: public CSystemException

@@ -14,68 +13,78 @@
 };

 #endif

 

-class CInBuffer

+class CInBufferBase

 {

-  Byte *_buffer;

-  Byte *_bufferLimit;

-  Byte *_bufferBase;

-  CMyComPtr<ISequentialInStream> _stream;

+protected:

+  Byte *_buf;

+  Byte *_bufLim;

+  Byte *_bufBase;

+

+  ISequentialInStream *_stream;

   UInt64 _processedSize;

-  UInt32 _bufferSize;

+  size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger

+                   // only up to 32-bits values now are supported!

   bool _wasFinished;

 

   bool ReadBlock();

-  Byte ReadBlock2();

+  bool ReadByte_FromNewBlock(Byte &b);

+  Byte ReadByte_FromNewBlock();

 

 public:

   #ifdef _NO_EXCEPTIONS

   HRESULT ErrorCode;

   #endif

+  UInt32 NumExtraBytes;

 

-  CInBuffer();

-  ~CInBuffer() { Free(); }

+  CInBufferBase() throw();

 

-  bool Create(UInt32 bufferSize);

-  void Free();

+  UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); }

+  UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); }

+  bool WasFinished() const { return _wasFinished; }

+

+  void SetStream(ISequentialInStream *stream) { _stream = stream; }

   

-  void SetStream(ISequentialInStream *stream);

-  void Init();

-  void ReleaseStream() { _stream.Release(); }

+  void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)

+  {

+    _bufBase = buf;

+    _bufSize = bufSize;

+    _processedSize = 0;

+    _buf = buf + pos;

+    _bufLim = buf + end;

+    _wasFinished = false;

+    #ifdef _NO_EXCEPTIONS

+    ErrorCode = S_OK;

+    #endif

+    NumExtraBytes = 0;

+  }

+

+  void Init() throw();

 

   bool ReadByte(Byte &b)

   {

-    if (_buffer >= _bufferLimit)

-      if (!ReadBlock())

-        return false;

-    b = *_buffer++;

+    if (_buf >= _bufLim)

+      return ReadByte_FromNewBlock(b);

+    b = *_buf++;

     return true;

   }

+  

   Byte ReadByte()

   {

-    if (_buffer >= _bufferLimit)

-      return ReadBlock2();

-    return *_buffer++;

+    if (_buf >= _bufLim)

+      return ReadByte_FromNewBlock();

+    return *_buf++;

   }

-  UInt32 ReadBytes(Byte *buf, UInt32 size)

-  {

-    if ((UInt32)(_bufferLimit - _buffer) >= size)

-    {

-      for (UInt32 i = 0; i < size; i++)

-        buf[i] = _buffer[i];

-      _buffer += size;

-      return size;

-    }

-    for (UInt32 i = 0; i < size; i++)

-    {

-      if (_buffer >= _bufferLimit)

-        if (!ReadBlock())

-          return i;

-      buf[i] = *_buffer++;

-    }

-    return size;

-  }

-  UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }

-  bool WasFinished() const { return _wasFinished; }

+  

+  size_t ReadBytes(Byte *buf, size_t size);

+  size_t Skip(size_t size);

+};

+

+class CInBuffer: public CInBufferBase

+{

+public:

+  ~CInBuffer() { Free(); }

+  bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported!

+  void Free() throw();

 };

 

 #endif

diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
old mode 100755
new mode 100644
index 13a7696..591d01e
--- a/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -4,16 +4,18 @@
 

 #include "../../../C/7zCrc.h"

 

+#include "../../Common/Defs.h"

+

 #include "InOutTempBuffer.h"

 #include "StreamUtils.h"

 

 using namespace NWindows;

 using namespace NFile;

-using namespace NDirectory;

+using namespace NDir;

 

 static const UInt32 kTempBufSize = (1 << 20);

 

-static LPCTSTR kTempFilePrefixString = TEXT("7zt");

+static CFSTR kTempFilePrefixString = FTEXT("7zt");

 

 CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }

 

@@ -42,12 +44,7 @@
     return true;

   if (!_tempFileCreated)

   {

-    CSysString tempDirPath;

-    if (!MyGetTempPath(tempDirPath))

-      return false;

-    if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0)

-      return false;

-    if (!_outFile.Create(_tempFileName, true))

+    if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))

       return false;

     _tempFileCreated = true;

   }

@@ -91,7 +88,7 @@
   if (_tempFileCreated)

   {

     NIO::CInFile inFile;

-    if (!inFile.Open(_tempFileName))

+    if (!inFile.Open(_tempFile.GetPath()))

       return E_FAIL;

     while (size < _size)

     {

diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h
old mode 100755
new mode 100644
index a69bc85..710e474
--- a/CPP/7zip/Common/InOutTempBuffer.h
+++ b/CPP/7zip/Common/InOutTempBuffer.h
@@ -5,17 +5,15 @@
 

 #include "../../Common/MyCom.h"

 #include "../../Windows/FileDir.h"

-#include "../../Windows/FileIO.h"

 

 #include "../IStream.h"

 

 class CInOutTempBuffer

 {

-  NWindows::NFile::NDirectory::CTempFile _tempFile;

+  NWindows::NFile::NDir::CTempFile _tempFile;

   NWindows::NFile::NIO::COutFile _outFile;

   Byte *_buf;

   UInt32 _bufPos;

-  CSysString _tempFileName;

   bool _tempFileCreated;

   UInt64 _size;

   UInt32 _crc;

diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
old mode 100755
new mode 100644
index dd2d2d5..174cac1
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -17,17 +17,21 @@
     if (realProcessedSize == 0)

       _wasFinished = true;

   }

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = realProcessedSize;

   return result;

 }

 

 STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   if (_virtPos >= _size)

-    return (_virtPos == _size) ? S_OK: E_FAIL;

+  {

+    // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.

+    return S_OK;

+    // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF

+  }

   UInt64 rem = _size - _virtPos;

   if (rem < size)

     size = (UInt32)rem;

@@ -38,7 +42,7 @@
     RINOK(SeekToPhys());

   }

   HRESULT res = _stream->Read(data, size, &size);

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = size;

   _physPos += size;

   _virtPos += size;

@@ -47,24 +51,39 @@
 

 STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET: _virtPos = offset; break;

-    case STREAM_SEEK_CUR: _virtPos += offset; break;

-    case STREAM_SEEK_END: _virtPos = _size + offset; break;

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END: offset += _size; break;

     default: return STG_E_INVALIDFUNCTION;

   }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _virtPos = offset;

   if (newPosition)

     *newPosition = _virtPos;

   return S_OK;

 }

 

+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)

+{

+  *resStream = 0;

+  CLimitedInStream *streamSpec = new CLimitedInStream;

+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;

+  streamSpec->SetStream(inStream);

+  RINOK(streamSpec->InitAndSeek(pos, size));

+  streamSpec->SeekToStart();

+  *resStream = streamTemp.Detach();

+  return S_OK;

+}

+

 STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   if (_virtPos >= Size)

-    return (_virtPos == Size) ? S_OK: E_FAIL;

+    return S_OK;

 

   if (_curRem == 0)

   {

@@ -88,7 +107,7 @@
   if (size > _curRem)

     size = _curRem;

   HRESULT res = Stream->Read(data, size, &size);

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = size;

   _physPos += size;

   _virtPos += size;

@@ -98,39 +117,88 @@
  

 STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  UInt64 newVirtPos = offset;

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

     case STREAM_SEEK_SET: break;

-    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;

-    case STREAM_SEEK_END: newVirtPos += Size; break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END: offset += Size; break;

     default: return STG_E_INVALIDFUNCTION;

   }

-  if (_virtPos != newVirtPos)

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  if (_virtPos != (UInt64)offset)

     _curRem = 0;

-  _virtPos = newVirtPos;

+  _virtPos = offset;

   if (newPosition)

-    *newPosition = newVirtPos;

+    *newPosition = offset;

   return S_OK;

 }

 

 

-HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)

+STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  *resStream = 0;

-  CLimitedInStream *streamSpec = new CLimitedInStream;

-  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;

-  streamSpec->SetStream(inStream);

-  RINOK(streamSpec->InitAndSeek(pos, size));

-  streamSpec->SeekToStart();

-  *resStream = streamTemp.Detach();

+  if (processedSize)

+    *processedSize = 0;

+  if (_virtPos >= Extents.Back().Virt)

+    return S_OK;

+  if (size == 0)

+    return S_OK;

+  

+  unsigned left = 0, right = Extents.Size() - 1;

+  for (;;)

+  {

+    unsigned mid = (left + right) / 2;

+    if (mid == left)

+      break;

+    if (_virtPos < Extents[mid].Virt)

+      right = mid;

+    else

+      left = mid;

+  }

+  

+  const CSeekExtent &extent = Extents[left];

+  UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);

+  if (_needStartSeek || _phyPos != phyPos)

+  {

+    _needStartSeek = false;

+    _phyPos = phyPos;

+    RINOK(SeekToPhys());

+  }

+  

+  UInt64 rem = Extents[left + 1].Virt - _virtPos;

+  if (size > rem)

+    size = (UInt32)rem;

+  

+  HRESULT res = Stream->Read(data, size, &size);

+  _phyPos += size;

+  _virtPos += size;

+  if (processedSize)

+    *processedSize = size;

+  return res;

+}

+

+STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch (seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END: offset += Extents.Back().Virt; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _virtPos = offset;

+  if (newPosition)

+    *newPosition = _virtPos;

   return S_OK;

 }

 

+

 STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

   HRESULT result = S_OK;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = 0;

   if (size > _size)

   {

@@ -139,7 +207,7 @@
       _overflow = true;

       if (!_overflowIsAllowed)

         return E_FAIL;

-      if (processedSize != NULL)

+      if (processedSize)

         *processedSize = size;

       return S_OK;

     }

@@ -148,7 +216,134 @@
   if (_stream)

     result = _stream->Write(data, size, &size);

   _size -= size;

-  if (processedSize != NULL)

+  if (processedSize)

     *processedSize = size;

   return result;

 }

+

+

+STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 cur;

+  HRESULT res = Stream->Read(data, size, &cur);

+  if (processedSize)

+    *processedSize = cur;

+  _virtPos += cur;

+  return res;

+}

+  

+STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch (seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END:

+    {

+      UInt64 pos = 0;

+      RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos));

+      if (pos < Offset)

+        return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+      _virtPos = pos - Offset;

+      if (newPosition)

+        *newPosition = _virtPos;

+      return S_OK;

+    }

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _virtPos = offset;

+  if (newPosition)

+    *newPosition = _virtPos;

+  return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);

+}

+

+STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (_virtPos >= _size)

+  {

+    // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.

+    return S_OK;

+    // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF

+  }

+  UInt64 rem = _size - _virtPos;

+  if (rem < size)

+    size = (UInt32)rem;

+

+  UInt64 newPos = _startOffset + _virtPos;

+  UInt64 offsetInCache = newPos - _cachePhyPos;

+  HRESULT res = S_OK;

+  if (newPos >= _cachePhyPos &&

+      offsetInCache <= _cacheSize &&

+      size <= _cacheSize - (size_t)offsetInCache)

+    memcpy(data, _cache + (size_t)offsetInCache, size);

+  else

+  {

+    if (newPos != _physPos)

+    {

+      _physPos = newPos;

+      RINOK(SeekToPhys());

+    }

+    res = _stream->Read(data, size, &size);

+    _physPos += size;

+  }

+  if (processedSize)

+    *processedSize = size;

+  _virtPos += size;

+  return res;

+}

+

+STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch (seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END: offset += _size; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _virtPos = offset;

+  if (newPosition)

+    *newPosition = _virtPos;

+  return S_OK;

+}

+

+STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 cur;

+  HRESULT res = Stream->Write(data, size, &cur);

+  if (processedSize)

+    *processedSize = cur;

+  _virtPos += cur;

+  if (_virtSize < _virtPos)

+    _virtSize = _virtPos;

+  return res;

+}

+  

+STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch (seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _virtPos; break;

+    case STREAM_SEEK_END: offset += _virtSize; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _virtPos = offset;

+  if (newPosition)

+    *newPosition = _virtPos;

+  return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);

+}

+

+STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize)

+{

+  _virtSize = newSize;

+  return Stream->SetSize(Offset + newSize);

+}

diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
old mode 100755
new mode 100644
index caec98f..8c89502
--- a/CPP/7zip/Common/LimitedStreams.h
+++ b/CPP/7zip/Common/LimitedStreams.h
@@ -3,6 +3,7 @@
 #ifndef __LIMITED_STREAMS_H

 #define __LIMITED_STREAMS_H

 

+#include "../../Common/MyBuffer.h"

 #include "../../Common/MyCom.h"

 #include "../../Common/MyVector.h"

 #include "../IStream.h"

@@ -25,7 +26,7 @@
     _wasFinished = false;

   }

  

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialInStream)

 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   UInt64 GetSize() const { return _pos; }

@@ -54,7 +55,7 @@
     return SeekToPhys();

   }

  

-  MY_UNKNOWN_IMP1(IInStream)

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

@@ -62,6 +63,8 @@
   HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }

 };

 

+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);

+

 class CClusterInStream:

   public IInStream,

   public CMyUnknownImp

@@ -73,7 +76,7 @@
   CMyComPtr<IInStream> Stream;

   UInt64 StartOffset;

   UInt64 Size;

-  int BlockSizeLog;

+  unsigned BlockSizeLog;

   CRecordVector<UInt32> Vector;

 

   HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

@@ -91,13 +94,44 @@
     return S_OK;

   }

 

-  MY_UNKNOWN_IMP1(IInStream)

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

 

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

 };

 

-HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);

+struct CSeekExtent

+{

+  UInt64 Phy;

+  UInt64 Virt;

+};

+

+class CExtentsStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 _phyPos;

+  UInt64 _virtPos;

+  bool _needStartSeek;

+

+  HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }

+

+public:

+  CMyComPtr<IInStream> Stream;

+  CRecordVector<CSeekExtent> Extents;

+

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+  void ReleaseStream() { Stream.Release(); }

+

+  void Init()

+  {

+    _virtPos = 0;

+    _phyPos = 0;

+    _needStartSeek = true;

+  }

+};

 

 class CLimitedSequentialOutStream:

   public ISequentialOutStream,

@@ -108,7 +142,7 @@
   bool _overflow;

   bool _overflowIsAllowed;

 public:

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

   void SetStream(ISequentialOutStream *stream) { _stream = stream; }

   void ReleaseStream() { _stream.Release(); }

@@ -122,4 +156,96 @@
   UInt64 GetRem() const { return _size; }

 };

 

+

+class CTailInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 _virtPos;

+public:

+  CMyComPtr<IInStream> Stream;

+  UInt64 Offset;

+

+  void Init()

+  {

+    _virtPos = 0;

+  }

+ 

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+

+  HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }

+};

+

+class CLimitedCachedInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<IInStream> _stream;

+  UInt64 _virtPos;

+  UInt64 _physPos;

+  UInt64 _size;

+  UInt64 _startOffset;

+  

+  const Byte *_cache;

+  size_t _cacheSize;

+  size_t _cachePhyPos;

+

+

+  HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

+public:

+  CByteBuffer Buffer;

+

+  void SetStream(IInStream *stream) { _stream = stream; }

+  void SetCache(size_t cacheSize, size_t cachePos)

+  {

+    _cache = Buffer;

+    _cacheSize = cacheSize;

+    _cachePhyPos = cachePos;

+  }

+

+  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)

+  {

+    _startOffset = startOffset;

+    _physPos = startOffset;

+    _virtPos = 0;

+    _size = size;

+    return SeekToPhys();

+  }

+ 

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+

+  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }

+};

+

+class CTailOutStream:

+  public IOutStream,

+  public CMyUnknownImp

+{

+  UInt64 _virtPos;

+  UInt64 _virtSize;

+public:

+  CMyComPtr<IOutStream> Stream;

+  UInt64 Offset;

+  

+  virtual ~CTailOutStream() {}

+

+  MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)

+

+  void Init()

+  {

+    _virtPos = 0;

+    _virtSize = 0;

+  }

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+  STDMETHOD(SetSize)(UInt64 newSize);

+};

+

 #endif

diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp
old mode 100755
new mode 100644
index 705cc4d..9a07e4c
--- a/CPP/7zip/Common/MethodId.cpp
+++ b/CPP/7zip/Common/MethodId.cpp
@@ -1,27 +1,3 @@
 // MethodId.cpp

 

 #include "StdAfx.h"

-

-#include "MethodId.h"

-#include "../../Common/MyString.h"

-

-static inline wchar_t GetHex(Byte value)

-{

-  return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

-}

-

-UString ConvertMethodIdToString(UInt64 id)

-{

-  wchar_t s[32];

-  int len = 32;

-  s[--len] = 0;

-  do

-  {

-    s[--len] = GetHex((Byte)id & 0xF);

-    id >>= 4;

-    s[--len] = GetHex((Byte)id & 0xF);

-    id >>= 4;

-  }

-  while (id != 0);

-  return s + len;

-}

diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h
old mode 100755
new mode 100644
index 9551723..1ba9f49
--- a/CPP/7zip/Common/MethodId.h
+++ b/CPP/7zip/Common/MethodId.h
@@ -3,7 +3,7 @@
 #ifndef __7Z_METHOD_ID_H

 #define __7Z_METHOD_ID_H

 

-#include "../../Common/Types.h"

+#include "../../Common/MyTypes.h"

 

 typedef UInt64 CMethodId;

 

diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
old mode 100755
new mode 100644
index 937708e..0773511
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -2,98 +2,440 @@
 

 #include "StdAfx.h"

 

-#include "../../Common/MyCom.h"

-

-#include "../ICoder.h"

+#include "../../Common/StringToInt.h"

 

 #include "MethodProps.h"

 

-static const UInt64 k_LZMA = 0x030101;

-static const UInt64 k_LZMA2 = 0x21;

+using namespace NWindows;

 

-HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)

+bool StringToBool(const UString &s, bool &res)

 {

-  bool tryReduce = false;

-  UInt32 reducedDictionarySize = 1 << 10;

-  if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2))

+  if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON"))

   {

-    for (;;)

-    {

-      const UInt32 step = (reducedDictionarySize >> 1);

-      if (reducedDictionarySize >= *inSizeForReduce)

-      {

-        tryReduce = true;

-        break;

-      }

-      reducedDictionarySize += step;

-      if (reducedDictionarySize >= *inSizeForReduce)

-      {

-        tryReduce = true;

-        break;

-      }

-      if (reducedDictionarySize >= ((UInt32)3 << 30))

-        break;

-      reducedDictionarySize += step;

-    }

+    res = true;

+    return true;

   }

+  if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF"))

+  {

+    res = false;

+    return true;

+  }

+  return false;

+}

 

+HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)

+{

+  switch (prop.vt)

   {

-    int numProps = method.Props.Size();

-    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

-    coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);

-    if (setCoderProperties == NULL)

-    {

-      if (numProps != 0)

-        return E_INVALIDARG;

-    }

-    else

-    {

-      CRecordVector<PROPID> propIDs;

-      NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps];

-      HRESULT res = S_OK;

-      try

-      {

-        for (int i = 0; i < numProps; i++)

-        {

-          const CProp &prop = method.Props[i];

-          propIDs.Add(prop.Id);

-          NWindows::NCOM::CPropVariant &value = values[i];

-          value = prop.Value;

-          // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)

-          if (tryReduce)

-            if (prop.Id == NCoderPropID::kDictionarySize)

-              if (value.vt == VT_UI4)

-                if (reducedDictionarySize < value.ulVal)

-            value.ulVal = reducedDictionarySize;

-        }

-        CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

-        coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);

-        res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps);

-      }

-      catch(...)

-      {

-        delete []values;

-        throw;

-      }

-      delete []values;

-      RINOK(res);

-    }

+    case VT_EMPTY: dest = true; return S_OK;

+    case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;

+    case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;

   }

- 

-  /*

-  CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

-  coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

-  if (writeCoderProperties != NULL)

+  return E_INVALIDARG;

+}

+

+unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)

+{

+  const wchar_t *start = srcString;

+  const wchar_t *end;

+  number = ConvertStringToUInt32(start, &end);

+  return (unsigned)(end - start);

+}

+

+HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)

+{

+  // =VT_UI4

+  // =VT_EMPTY

+  // {stringUInt32}=VT_EMPTY

+

+  if (prop.vt == VT_UI4)

   {

-    CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;

-    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

-    outStreamSpec->Init();

-    RINOK(writeCoderProperties->WriteCoderProperties(outStream));

-    size_t size = outStreamSpec->GetSize();

-    filterProps.SetCapacity(size);

-    memmove(filterProps, outStreamSpec->GetBuffer(), size);

+    if (!name.IsEmpty())

+      return E_INVALIDARG;

+    resValue = prop.ulVal;

+    return S_OK;

   }

-  */

+  if (prop.vt != VT_EMPTY)

+    return E_INVALIDARG;

+  if (name.IsEmpty())

+    return S_OK;

+  UInt32 v;

+  if (ParseStringToUInt32(name, v) != name.Len())

+    return E_INVALIDARG;

+  resValue = v;

   return S_OK;

 }

 

+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)

+{

+  if (name.IsEmpty())

+  {

+    switch (prop.vt)

+    {

+      case VT_UI4:

+        numThreads = prop.ulVal;

+        break;

+      default:

+      {

+        bool val;

+        RINOK(PROPVARIANT_to_bool(prop, val));

+        numThreads = (val ? defaultNumThreads : 1);

+        break;

+      }

+    }

+    return S_OK;

+  }

+  if (prop.vt != VT_EMPTY)

+    return E_INVALIDARG;

+  return ParsePropToUInt32(name, prop, numThreads);

+}

+

+static HRESULT StringToDictSize(const UString &s, UInt32 &dicSize)

+{

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

+      return E_INVALIDARG;

+    dicSize = (UInt32)1 << (unsigned)number;

+    return S_OK;

+  }

+  unsigned numBits;

+  switch (MyCharLower_Ascii(s[numDigits]))

+  {

+    case 'b': dicSize = 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;

+  return S_OK;

+}

+

+static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue)

+{

+  if (prop.vt == VT_UI4)

+  {

+    UInt32 v = prop.ulVal;

+    if (v >= 32)

+      return E_INVALIDARG;

+    resValue = (UInt32)1 << v;

+    return S_OK;

+  }

+  if (prop.vt == VT_BSTR)

+    return StringToDictSize(prop.bstrVal, resValue);

+  return E_INVALIDARG;

+}

+

+void CProps::AddProp32(PROPID propid, UInt32 level)

+{

+  CProp prop;

+  prop.IsOptional = true;

+  prop.Id = propid;

+  prop.Value = (UInt32)level;

+  Props.Add(prop);

+}

+

+class CCoderProps

+{

+  PROPID *_propIDs;

+  NCOM::CPropVariant *_props;

+  unsigned _numProps;

+  unsigned _numPropsMax;

+public:

+  CCoderProps(unsigned numPropsMax)

+  {

+    _numPropsMax = numPropsMax;

+    _numProps = 0;

+    _propIDs = new PROPID[numPropsMax];

+    _props = new NCOM::CPropVariant[numPropsMax];

+  }

+  ~CCoderProps()

+  {

+    delete []_propIDs;

+    delete []_props;

+  }

+  void AddProp(const CProp &prop);

+  HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)

+  {

+    return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);

+  }

+};

+

+void CCoderProps::AddProp(const CProp &prop)

+{

+  if (_numProps >= _numPropsMax)

+    throw 1;

+  _propIDs[_numProps] = prop.Id;

+  _props[_numProps] = prop.Value;

+  _numProps++;

+}

+

+HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const

+{

+  CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0));

+  FOR_VECTOR (i, Props)

+    coderProps.AddProp(Props[i]);

+  if (dataSizeReduce)

+  {

+    CProp prop;

+    prop.Id = NCoderPropID::kReduceSize;

+    prop.Value = *dataSizeReduce;

+    coderProps.AddProp(prop);

+  }

+  return coderProps.SetProps(scp);

+}

+

+

+int CMethodProps::FindProp(PROPID id) const

+{

+  for (int i = Props.Size() - 1; i >= 0; i--)

+    if (Props[i].Id == id)

+      return i;

+  return -1;

+}

+

+int CMethodProps::GetLevel() const

+{

+  int i = FindProp(NCoderPropID::kLevel);

+  if (i < 0)

+    return 5;

+  if (Props[i].Value.vt != VT_UI4)

+    return 9;

+  UInt32 level = Props[i].Value.ulVal;

+  return level > 9 ? 9 : (int)level;

+}

+

+struct CNameToPropID

+{

+  VARTYPE VarType;

+  const char *Name;

+};

+

+static const CNameToPropID g_NameToPropID[] =

+{

+  { VT_UI4, "" },

+  { VT_UI4, "d" },

+  { VT_UI4, "mem" },

+  { VT_UI4, "o" },

+  { VT_UI4, "c" },

+  { VT_UI4, "pb" },

+  { VT_UI4, "lc" },

+  { VT_UI4, "lp" },

+  { VT_UI4, "fb" },

+  { VT_BSTR, "mf" },

+  { VT_UI4, "mc" },

+  { VT_UI4, "pass" },

+  { VT_UI4, "a" },

+  { VT_UI4, "mt" },

+  { VT_BOOL, "eos" },

+  { VT_UI4, "x" },

+  { VT_UI4, "reduceSize" }

+};

+

+static int FindPropIdExact(const UString &name)

+{

+  for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++)

+    if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))

+      return i;

+  return -1;

+}

+

+static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)

+{

+  if (varType == srcProp.vt)

+  {

+    destProp = srcProp;

+    return true;

+  }

+  if (varType == VT_BOOL)

+  {

+    bool res;

+    if (PROPVARIANT_to_bool(srcProp, res) != S_OK)

+      return false;

+    destProp = res;

+    return true;

+  }

+  if (srcProp.vt == VT_EMPTY)

+  {

+    destProp = srcProp;

+    return true;

+  }

+  return false;

+}

+    

+static void SplitParams(const UString &srcString, UStringVector &subStrings)

+{

+  subStrings.Clear();

+  UString s;

+  int len = srcString.Len();

+  if (len == 0)

+    return;

+  for (int i = 0; i < len; i++)

+  {

+    wchar_t c = srcString[i];

+    if (c == L':')

+    {

+      subStrings.Add(s);

+      s.Empty();

+    }

+    else

+      s += c;

+  }

+  subStrings.Add(s);

+}

+

+static void SplitParam(const UString &param, UString &name, UString &value)

+{

+  int eqPos = param.Find(L'=');

+  if (eqPos >= 0)

+  {

+    name.SetFrom(param, eqPos);

+    value = param.Ptr(eqPos + 1);

+    return;

+  }

+  unsigned i;

+  for (i = 0; i < param.Len(); i++)

+  {

+    wchar_t c = param[i];

+    if (c >= L'0' && c <= L'9')

+      break;

+  }

+  name.SetFrom(param, i);

+  value = param.Ptr(i);

+}

+

+static bool IsLogSizeProp(PROPID propid)

+{

+  switch (propid)

+  {

+    case NCoderPropID::kDictionarySize:

+    case NCoderPropID::kUsedMemorySize:

+    case NCoderPropID::kBlockSize:

+    case NCoderPropID::kReduceSize:

+      return true;

+  }

+  return false;

+}

+

+HRESULT CMethodProps::SetParam(const UString &name, const UString &value)

+{

+  int index = FindPropIdExact(name);

+  if (index < 0)

+    return E_INVALIDARG;

+  const CNameToPropID &nameToPropID = g_NameToPropID[index];

+  CProp prop;

+  prop.Id = index;

+

+  if (IsLogSizeProp(prop.Id))

+  {

+    UInt32 dicSize;

+    RINOK(StringToDictSize(value, dicSize));

+    prop.Value = dicSize;

+  }

+  else

+  {

+    NCOM::CPropVariant propValue;

+    if (nameToPropID.VarType == VT_BSTR)

+      propValue = value;

+    else if (nameToPropID.VarType == VT_BOOL)

+    {

+      bool res;

+      if (!StringToBool(value, res))

+        return E_INVALIDARG;

+      propValue = res;

+    }

+    else if (!value.IsEmpty())

+    {

+      UInt32 number;

+      if (ParseStringToUInt32(value, number) == value.Len())

+        propValue = number;

+      else

+        propValue = value;

+    }

+    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))

+      return E_INVALIDARG;

+  }

+  Props.Add(prop);

+  return S_OK;

+}

+

+HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)

+{

+  UStringVector params;

+  SplitParams(srcString, params);

+  FOR_VECTOR (i, params)

+  {

+    const UString &param = params[i];

+    UString name, value;

+    SplitParam(param, name, value);

+    RINOK(SetParam(name, value));

+  }

+  return S_OK;

+}

+

+HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)

+{

+  if (realName.Len() == 0)

+  {

+    // [empty]=method

+    return E_INVALIDARG;

+  }

+  if (value.vt == VT_EMPTY)

+  {

+    // {realName}=[empty]

+    UString name, value;

+    SplitParam(realName, name, value);

+    return SetParam(name, value);

+  }

+  

+  // {realName}=value

+  int index = FindPropIdExact(realName);

+  if (index < 0)

+    return E_INVALIDARG;

+  const CNameToPropID &nameToPropID = g_NameToPropID[index];

+  CProp prop;

+  prop.Id = index;

+  

+  if (IsLogSizeProp(prop.Id))

+  {

+    UInt32 dicSize;

+    RINOK(PROPVARIANT_to_DictSize(value, dicSize));

+    prop.Value = dicSize;

+  }

+  else

+  {

+    if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))

+      return E_INVALIDARG;

+  }

+  Props.Add(prop);

+  return S_OK;

+}

+

+HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)

+{

+  int splitPos = s.Find(':');

+  MethodName = s;

+  if (splitPos < 0)

+    return S_OK;

+  MethodName.DeleteFrom(splitPos);

+  return ParseParamsFromString(s.Ptr(splitPos + 1));

+}

+

+HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)

+{

+  if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m"))

+    return ParseParamsFromPROPVARIANT(realName, value);

+  // -m{N}=method

+  if (value.vt != VT_BSTR)

+    return E_INVALIDARG;

+  return ParseMethodFromString(value.bstrVal);

+}

diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
old mode 100755
new mode 100644
index 75b87f1..cc2b276
--- a/CPP/7zip/Common/MethodProps.h
+++ b/CPP/7zip/Common/MethodProps.h
@@ -3,39 +3,183 @@
 #ifndef __7Z_METHOD_PROPS_H

 #define __7Z_METHOD_PROPS_H

 

-#include "../../Common/MyVector.h"

+#include "../../Common/MyString.h"

 

 #include "../../Windows/PropVariant.h"

 

-#include "MethodId.h"

+#include "../ICoder.h"

+

+bool StringToBool(const UString &s, bool &res);

+HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);

+unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);

+HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);

+

+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);

 

 struct CProp

 {

   PROPID Id;

+  bool IsOptional;

   NWindows::NCOM::CPropVariant Value;

+  CProp(): IsOptional(false) {}

 };

 

-struct CMethod

+struct CProps

 {

-  CMethodId Id;

   CObjectVector<CProp> Props;

+

+  void Clear() { Props.Clear(); }

+

+  bool AreThereNonOptionalProps() const

+  {

+    FOR_VECTOR (i, Props)

+      if (!Props[i].IsOptional)

+        return true;

+    return false;

+  }

+

+  void AddProp32(PROPID propid, UInt32 level);

+

+  void AddPropString(PROPID propid, const wchar_t *s)

+  {

+    CProp prop;

+    prop.IsOptional = true;

+    prop.Id = propid;

+    prop.Value = s;

+    Props.Add(prop);

+  }

+

+  HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;

 };

 

-struct CMethodsMode

+class CMethodProps: public CProps

 {

-  CObjectVector<CMethod> Methods;

-  #ifndef _7ZIP_ST

-  UInt32 NumThreads;

-  #endif

+  HRESULT SetParam(const UString &name, const UString &value);

+public:

+  int GetLevel() const;

+  int Get_NumThreads() const

+  {

+    int i = FindProp(NCoderPropID::kNumThreads);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+        return (int)Props[i].Value.ulVal;

+    return -1;

+  }

 

-  CMethodsMode()

-      #ifndef _7ZIP_ST

-      : NumThreads(1)

-      #endif

-  {}

-  bool IsEmpty() const { return Methods.IsEmpty() ; }

+  bool Get_DicSize(UInt32 &res) const

+  {

+    res = 0;

+    int i = FindProp(NCoderPropID::kDictionarySize);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+      {

+        res = Props[i].Value.ulVal;

+        return true;

+      }

+    return false;

+  }

+

+  int FindProp(PROPID id) const;

+

+  UInt32 Get_Lzma_Algo() const

+  {

+    int i = FindProp(NCoderPropID::kAlgorithm);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+        return Props[i].Value.ulVal;

+    return GetLevel() >= 5 ? 1 : 0;

+  }

+

+  UInt32 Get_Lzma_DicSize() const

+  {

+    int i = FindProp(NCoderPropID::kDictionarySize);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+        return Props[i].Value.ulVal;

+    int level = GetLevel();

+    return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));

+  }

+

+  UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const

+  {

+    fixedNumber = false;

+    int numThreads = Get_NumThreads();

+    if (numThreads >= 0)

+    {

+      fixedNumber = true;

+      return numThreads < 2 ? 1 : 2;

+    }

+    return Get_Lzma_Algo() == 0 ? 1 : 2;

+  }

+

+  UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const

+  {

+    fixedNumber = false;

+    int numThreads = Get_NumThreads();

+    if (numThreads >= 0)

+    {

+      fixedNumber = true;

+      if (numThreads < 1) return 1;

+      if (numThreads > 64) return 64;

+      return numThreads;

+    }

+    return 1;

+  }

+

+  UInt32 Get_BZip2_BlockSize() const

+  {

+    int i = FindProp(NCoderPropID::kDictionarySize);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+      {

+        UInt32 blockSize = Props[i].Value.ulVal;

+        const UInt32 kDicSizeMin = 100000;

+        const UInt32 kDicSizeMax = 900000;

+        if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;

+        if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;

+        return blockSize;

+      }

+    int level = GetLevel();

+    return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));

+  }

+

+  UInt32 Get_Ppmd_MemSize() const

+  {

+    int i = FindProp(NCoderPropID::kUsedMemorySize);

+    if (i >= 0)

+      if (Props[i].Value.vt == VT_UI4)

+        return Props[i].Value.ulVal;

+    int level = GetLevel();

+    return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));

+  }

+

+  void AddLevelProp(UInt32 level)

+  {

+    AddProp32(NCoderPropID::kLevel, level);

+  }

+

+  void AddNumThreadsProp(UInt32 numThreads)

+  {

+    AddProp32(NCoderPropID::kNumThreads, numThreads);

+  }

+

+  HRESULT ParseParamsFromString(const UString &srcString);

+  HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);

 };

 

-HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);

+class COneMethodInfo: public CMethodProps

+{

+public:

+  UString MethodName;

+  

+  void Clear()

+  {

+    CMethodProps::Clear();

+    MethodName.Empty();

+  }

+  bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }

+  HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);

+  HRESULT ParseMethodFromString(const UString &s);

+};

 

 #endif

diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp
old mode 100755
new mode 100644
index f10f54c..3b01c7f
--- a/CPP/7zip/Common/OffsetStream.cpp
+++ b/CPP/7zip/Common/OffsetStream.cpp
@@ -2,7 +2,8 @@
 

 #include "StdAfx.h"

 

-#include "Common/Defs.h"

+#include "../../Common/Defs.h"

+

 #include "OffsetStream.h"

 

 HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)

@@ -17,14 +18,17 @@
   return _stream->Write(data, size, processedSize);

 }

 

-STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin,

-    UInt64 *newPosition)

+STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

   UInt64 absoluteNewPosition;

   if (seekOrigin == STREAM_SEEK_SET)

+  {

+    if (offset < 0)

+      return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

     offset += _offset;

+  }

   HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);

-  if (newPosition != NULL)

+  if (newPosition)

     *newPosition = absoluteNewPosition - _offset;

   return result;

 }

diff --git a/CPP/7zip/Common/OffsetStream.h b/CPP/7zip/Common/OffsetStream.h
old mode 100755
new mode 100644
index 972a8ce..ad835f2
--- a/CPP/7zip/Common/OffsetStream.h
+++ b/CPP/7zip/Common/OffsetStream.h
@@ -1,9 +1,10 @@
 // OffsetStream.h

 

-#ifndef __OFFSETSTREAM_H

-#define __OFFSETSTREAM_H

+#ifndef __OFFSET_STREAM_H

+#define __OFFSET_STREAM_H

 

-#include "Common/MyCom.h"

+#include "../../Common/MyCom.h"

+

 #include "../IStream.h"

 

 class COffsetOutStream:

diff --git a/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp
old mode 100755
new mode 100644
index 4e55f55..fb8dc8d
--- a/CPP/7zip/Common/OutBuffer.cpp
+++ b/CPP/7zip/Common/OutBuffer.cpp
@@ -6,34 +6,29 @@
 

 #include "OutBuffer.h"

 

-bool COutBuffer::Create(UInt32 bufferSize)

+bool COutBuffer::Create(UInt32 bufSize) throw()

 {

   const UInt32 kMinBlockSize = 1;

-  if (bufferSize < kMinBlockSize)

-    bufferSize = kMinBlockSize;

-  if (_buffer != 0 && _bufferSize == bufferSize)

+  if (bufSize < kMinBlockSize)

+    bufSize = kMinBlockSize;

+  if (_buf != 0 && _bufSize == bufSize)

     return true;

   Free();

-  _bufferSize = bufferSize;

-  _buffer = (Byte *)::MidAlloc(bufferSize);

-  return (_buffer != 0);

+  _bufSize = bufSize;

+  _buf = (Byte *)::MidAlloc(bufSize);

+  return (_buf != 0);

 }

 

-void COutBuffer::Free()

+void COutBuffer::Free() throw()

 {

-  ::MidFree(_buffer);

-  _buffer = 0;

+  ::MidFree(_buf);

+  _buf = 0;

 }

 

-void COutBuffer::SetStream(ISequentialOutStream *stream)

-{

-  _stream = stream;

-}

-

-void COutBuffer::Init()

+void COutBuffer::Init() throw()

 {

   _streamPos = 0;

-  _limitPos = _bufferSize;

+  _limitPos = _bufSize;

   _pos = 0;

   _processedSize = 0;

   _overDict = false;

@@ -42,27 +37,27 @@
   #endif

 }

 

-UInt64 COutBuffer::GetProcessedSize() const

+UInt64 COutBuffer::GetProcessedSize() const throw()

 {

   UInt64 res = _processedSize + _pos - _streamPos;

   if (_streamPos > _pos)

-    res += _bufferSize;

+    res += _bufSize;

   return res;

 }

 

 

-HRESULT COutBuffer::FlushPart()

+HRESULT COutBuffer::FlushPart() throw()

 {

-  // _streamPos < _bufferSize

-  UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);

+  // _streamPos < _bufSize

+  UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);

   HRESULT result = S_OK;

   #ifdef _NO_EXCEPTIONS

   result = ErrorCode;

   #endif

-  if (_buffer2 != 0)

+  if (_buf2 != 0)

   {

-    memmove(_buffer2, _buffer + _streamPos, size);

-    _buffer2 += size;

+    memcpy(_buf2, _buf + _streamPos, size);

+    _buf2 += size;

   }

 

   if (_stream != 0

@@ -72,30 +67,30 @@
      )

   {

     UInt32 processedSize = 0;

-    result = _stream->Write(_buffer + _streamPos, size, &processedSize);

+    result = _stream->Write(_buf + _streamPos, size, &processedSize);

     size = processedSize;

   }

   _streamPos += size;

-  if (_streamPos == _bufferSize)

+  if (_streamPos == _bufSize)

     _streamPos = 0;

-  if (_pos == _bufferSize)

+  if (_pos == _bufSize)

   {

     _overDict = true;

     _pos = 0;

   }

-  _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;

+  _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize;

   _processedSize += size;

   return result;

 }

 

-HRESULT COutBuffer::Flush()

+HRESULT COutBuffer::Flush() throw()

 {

   #ifdef _NO_EXCEPTIONS

   if (ErrorCode != S_OK)

     return ErrorCode;

   #endif

 

-  while(_streamPos != _pos)

+  while (_streamPos != _pos)

   {

     HRESULT result = FlushPart();

     if (result != S_OK)

diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h
old mode 100755
new mode 100644
index e2e76ad..90ce25d
--- a/CPP/7zip/Common/OutBuffer.h
+++ b/CPP/7zip/Common/OutBuffer.h
@@ -1,7 +1,7 @@
 // OutBuffer.h

 

-#ifndef __OUTBUFFER_H

-#define __OUTBUFFER_H

+#ifndef __OUT_BUFFER_H

+#define __OUT_BUFFER_H

 

 #include "../IStream.h"

 #include "../../Common/MyCom.h"

@@ -17,39 +17,38 @@
 class COutBuffer

 {

 protected:

-  Byte *_buffer;

+  Byte *_buf;

   UInt32 _pos;

   UInt32 _limitPos;

   UInt32 _streamPos;

-  UInt32 _bufferSize;

-  CMyComPtr<ISequentialOutStream> _stream;

+  UInt32 _bufSize;

+  ISequentialOutStream *_stream;

   UInt64 _processedSize;

-  Byte  *_buffer2;

+  Byte  *_buf2;

   bool _overDict;

 

-  HRESULT FlushPart();

+  HRESULT FlushPart() throw();

 public:

   #ifdef _NO_EXCEPTIONS

   HRESULT ErrorCode;

   #endif

 

-  COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}

+  COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {}

   ~COutBuffer() { Free(); }

   

-  bool Create(UInt32 bufferSize);

-  void Free();

+  bool Create(UInt32 bufSize) throw();

+  void Free() throw();

 

-  void SetMemStream(Byte *buffer) { _buffer2 = buffer; }

-  void SetStream(ISequentialOutStream *stream);

-  void Init();

-  HRESULT Flush();

+  void SetMemStream(Byte *buf) { _buf2 = buf; }

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void Init() throw();

+  HRESULT Flush() throw();

   void FlushWithCheck();

-  void ReleaseStream() {  _stream.Release(); }

 

   void WriteByte(Byte b)

   {

-    _buffer[_pos++] = b;

-    if(_pos == _limitPos)

+    _buf[_pos++] = b;

+    if (_pos == _limitPos)

       FlushWithCheck();

   }

   void WriteBytes(const void *data, size_t size)

@@ -58,7 +57,7 @@
       WriteByte(((const Byte *)data)[i]);

   }

 

-  UInt64 GetProcessedSize() const;

+  UInt64 GetProcessedSize() const throw();

 };

 

 #endif

diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
old mode 100755
new mode 100644
index 84a3eaf..cfe504a
--- a/CPP/7zip/Common/ProgressUtils.cpp
+++ b/CPP/7zip/Common/ProgressUtils.cpp
@@ -1,4 +1,4 @@
-// ProgressUtils.h

+// ProgressUtils.cpp

 

 #include "StdAfx.h"

 

diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp
new file mode 100644
index 0000000..b82b944
--- /dev/null
+++ b/CPP/7zip/Common/PropId.cpp
@@ -0,0 +1,99 @@
+// PropId.cpp

+

+#include "StdAfx.h"

+

+#include "../PropID.h"

+

+// VARTYPE

+Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =

+{

+  VT_EMPTY,

+  VT_UI4,

+  VT_UI4,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BOOL,

+  VT_UI8,

+  VT_UI8,

+  VT_UI4,

+  VT_FILETIME,

+  VT_FILETIME,

+  VT_FILETIME,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_UI4,

+  VT_UI4,

+  VT_BSTR,

+  VT_BOOL,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_UI8,

+  VT_BSTR,

+  VT_UI8,

+  VT_BSTR,

+  VT_UI8,

+  VT_UI8,

+  VT_BSTR, // or VT_UI8 kpidUnpackVer

+  VT_UI4, // or VT_UI8 kpidVolume

+  VT_BOOL,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI4,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BSTR,

+  VT_UI8,

+  VT_UI8,

+  VT_UI4, // kpidChecksum

+  VT_BSTR,

+  VT_UI8,

+  VT_BSTR, // or VT_UI8 kpidId

+  VT_BSTR,

+  VT_BSTR,

+  VT_UI4,

+  VT_UI4,

+  VT_BSTR,

+  VT_BSTR,

+  VT_UI8,

+  VT_UI8,

+  VT_UI4,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR, // kpidNtSecure

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BSTR, // SHA-1

+  VT_BSTR, // SHA-256

+  VT_BSTR,

+  VT_UI8,

+  VT_UI4,

+  VT_UI4,

+  VT_BSTR,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_UI8,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BSTR,

+  VT_BOOL,

+  VT_BOOL,

+  VT_BOOL,

+  VT_UI8,

+  VT_UI8

+};

diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h
old mode 100755
new mode 100644
index 7066325..b4cf1bf
--- a/CPP/7zip/Common/RegisterArc.h
+++ b/CPP/7zip/Common/RegisterArc.h
@@ -5,23 +5,28 @@
 

 #include "../Archive/IArchive.h"

 

-typedef IInArchive * (*CreateInArchiveP)();

-typedef IOutArchive * (*CreateOutArchiveP)();

-

 struct CArcInfo

 {

-  const wchar_t *Name;

-  const wchar_t *Ext;

-  const wchar_t *AddExt;

+  const char *Name;

+  const char *Ext;

+  const char *AddExt;

+  

   Byte ClassId;

-  Byte Signature[16];

-  int SignatureSize;

-  bool KeepName;

-  CreateInArchiveP CreateInArchive;

-  CreateOutArchiveP CreateOutArchive;

+  

+  Byte SignatureSize;

+  Byte Signature[20];

+  UInt16 SignatureOffset;

+  

+  UInt16 Flags;

+

+  Func_CreateInArchive CreateInArchive;

+  Func_CreateOutArchive CreateOutArchive;

+  Func_IsArc IsArc;

+

+  bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }

 };

 

-void RegisterArc(const CArcInfo *arcInfo);

+void RegisterArc(const CArcInfo *arcInfo) throw();

 

 #define REGISTER_ARC_NAME(x) CRegister ## x

 

@@ -29,4 +34,22 @@
     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)

+

+#ifdef EXTRACT_ONLY

+  #define IMP_CreateArcOut

+  #define REF_CreateArc_Pair CreateArc, NULL

+#else

+  #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; }

+  #define REF_CreateArc_Pair CreateArc, CreateArcOut

+#endif

+

 #endif

diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h
old mode 100755
new mode 100644
index c59ab66..d51dccb
--- a/CPP/7zip/Common/RegisterCodec.h
+++ b/CPP/7zip/Common/RegisterCodec.h
@@ -1,9 +1,10 @@
 // RegisterCodec.h

 

-#ifndef __REGISTERCODEC_H

-#define __REGISTERCODEC_H

+#ifndef __REGISTER_CODEC_H

+#define __REGISTER_CODEC_H

 

 #include "../Common/MethodId.h"

+#include "../ICoder.h"

 

 typedef void * (*CreateCodecP)();

 struct CCodecInfo

@@ -16,7 +17,7 @@
   bool IsFilter;

 };

 

-void RegisterCodec(const CCodecInfo *codecInfo);

+void RegisterCodec(const CCodecInfo *codecInfo) throw();

 

 #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x

 

@@ -26,8 +27,25 @@
 

 #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x

 #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \

-    REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \

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

 

+

+struct CHasherInfo

+{

+  IHasher * (*CreateHasher)();

+  CMethodId Id;

+  const wchar_t *Name;

+  UInt32 DigestSize;

+};

+

+void RegisterHasher(const CHasherInfo *hasher) throw();

+

+#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x

+

+#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \

+    REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \

+    static REGISTER_HASHER_NAME(x) g_RegisterHasher;

+

 #endif

diff --git a/CPP/7zip/Common/StdAfx.h b/CPP/7zip/Common/StdAfx.h
old mode 100755
new mode 100644
index f56e92f..42a088f
--- a/CPP/7zip/Common/StdAfx.h
+++ b/CPP/7zip/Common/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../Common/MyWindows.h"

-#include "../../Common/NewHandler.h"

+#include "../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp
old mode 100755
new mode 100644
index cb3bf99..b3d056d
--- a/CPP/7zip/Common/StreamBinder.cpp
+++ b/CPP/7zip/Common/StreamBinder.cpp
@@ -2,149 +2,125 @@
 

 #include "StdAfx.h"

 

-#include "StreamBinder.h"

-#include "../../Common/Defs.h"

 #include "../../Common/MyCom.h"

 

-using namespace NWindows;

-using namespace NSynchronization;

+#include "StreamBinder.h"

 

-class CSequentialInStreamForBinder:

+class CBinderInStream:

   public ISequentialInStream,

   public CMyUnknownImp

 {

+  CStreamBinder *_binder;

 public:

   MY_UNKNOWN_IMP

-

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

-private:

-  CStreamBinder *m_StreamBinder;

-public:

-  ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }

-  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }

+  ~CBinderInStream() { _binder->CloseRead(); }

+  CBinderInStream(CStreamBinder *binder): _binder(binder) {}

 };

 

-STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)

-  { return m_StreamBinder->Read(data, size, processedSize); }

+STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+  { return _binder->Read(data, size, processedSize); }

 

-class CSequentialOutStreamForBinder:

+class CBinderOutStream:

   public ISequentialOutStream,

   public CMyUnknownImp

 {

+  CStreamBinder *_binder;

 public:

   MY_UNKNOWN_IMP

-

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

-

-private:

-  CStreamBinder *m_StreamBinder;

-public:

-  ~CSequentialOutStreamForBinder() {  m_StreamBinder->CloseWrite(); }

-  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }

+  ~CBinderOutStream() { _binder->CloseWrite(); }

+  CBinderOutStream(CStreamBinder *binder): _binder(binder) {}

 };

 

-STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)

-  { return m_StreamBinder->Write(data, size, processedSize); }

+STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+  { return _binder->Write(data, size, processedSize); }

 

 

-//////////////////////////

-// CStreamBinder

-// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.

 

-HRes CStreamBinder::CreateEvents()

+WRes CStreamBinder::CreateEvents()

 {

-  RINOK(_allBytesAreWritenEvent.Create(true));

-  RINOK(_thereAreBytesToReadEvent.Create());

-  return _readStreamIsClosedEvent.Create();

+  RINOK(_canWrite_Event.Create(true));

+  RINOK(_canRead_Event.Create());

+  return _readingWasClosed_Event.Create();

 }

 

 void CStreamBinder::ReInit()

 {

-  _thereAreBytesToReadEvent.Reset();

-  _readStreamIsClosedEvent.Reset();

+  _waitWrite = true;

+  _canRead_Event.Reset();

+  _readingWasClosed_Event.Reset();

   ProcessedSize = 0;

 }

 

 

-  

-void CStreamBinder::CreateStreams(ISequentialInStream **inStream,

-      ISequentialOutStream **outStream)

+void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)

 {

-  CSequentialInStreamForBinder *inStreamSpec = new

-      CSequentialInStreamForBinder;

+  _waitWrite = true;

+  _bufSize = 0;

+  _buf = NULL;

+  ProcessedSize = 0;

+

+  CBinderInStream *inStreamSpec = new CBinderInStream(this);

   CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

-  inStreamSpec->SetBinder(this);

   *inStream = inStreamLoc.Detach();

 

-  CSequentialOutStreamForBinder *outStreamSpec = new

-      CSequentialOutStreamForBinder;

+  CBinderOutStream *outStreamSpec = new CBinderOutStream(this);

   CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);

-  outStreamSpec->SetBinder(this);

   *outStream = outStreamLoc.Detach();

-

-  _buffer = NULL;

-  _bufferSize= 0;

-  ProcessedSize = 0;

 }

 

+// (_canRead_Event && _bufSize == 0) means that stream is finished.

+

 HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)

 {

-  UInt32 sizeToRead = size;

-  if (size > 0)

+  if (processedSize)

+    *processedSize = 0;

+  if (size != 0)

   {

-    RINOK(_thereAreBytesToReadEvent.Lock());

-    sizeToRead = MyMin(_bufferSize, size);

-    if (_bufferSize > 0)

+    if (_waitWrite)

     {

-      memcpy(data, _buffer, sizeToRead);

-      _buffer = ((const Byte *)_buffer) + sizeToRead;

-      _bufferSize -= sizeToRead;

-      if (_bufferSize == 0)

+      RINOK(_canRead_Event.Lock());

+      _waitWrite = false;

+    }

+    if (size > _bufSize)

+      size = _bufSize;

+    if (size != 0)

+    {

+      memcpy(data, _buf, size);

+      _buf = ((const Byte *)_buf) + size;

+      ProcessedSize += size;

+      if (processedSize)

+        *processedSize = size;

+      _bufSize -= size;

+      if (_bufSize == 0)

       {

-        _thereAreBytesToReadEvent.Reset();

-        _allBytesAreWritenEvent.Set();

+        _waitWrite = true;

+        _canRead_Event.Reset();

+        _canWrite_Event.Set();

       }

     }

   }

-  if (processedSize != NULL)

-    *processedSize = sizeToRead;

-  ProcessedSize += sizeToRead;

   return S_OK;

 }

 

-void CStreamBinder::CloseRead()

-{

-  _readStreamIsClosedEvent.Set();

-}

-

 HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  if (size > 0)

+  if (processedSize)

+    *processedSize = 0;

+  if (size != 0)

   {

-    _buffer = data;

-    _bufferSize = size;

-    _allBytesAreWritenEvent.Reset();

-    _thereAreBytesToReadEvent.Set();

+    _buf = data;

+    _bufSize = size;

+    _canWrite_Event.Reset();

+    _canRead_Event.Set();

 

-    HANDLE events[2];

-    events[0] = _allBytesAreWritenEvent;

-    events[1] = _readStreamIsClosedEvent;

+    HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };

     DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);

     if (waitResult != WAIT_OBJECT_0 + 0)

-    {

-      // ReadingWasClosed = true;

       return S_FALSE;

-    }

-    // if(!_allBytesAreWritenEvent.Lock())

-    //   return E_FAIL;

+    if (processedSize)

+      *processedSize = size;

   }

-  if (processedSize != NULL)

-    *processedSize = size;

   return S_OK;

 }

-

-void CStreamBinder::CloseWrite()

-{

-  // _bufferSize must be = 0

-  _thereAreBytesToReadEvent.Set();

-}

diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
old mode 100755
new mode 100644
index b5d6c0d..52733f9
--- a/CPP/7zip/Common/StreamBinder.h
+++ b/CPP/7zip/Common/StreamBinder.h
@@ -1,32 +1,34 @@
 // StreamBinder.h

 

-#ifndef __STREAMBINDER_H

-#define __STREAMBINDER_H

+#ifndef __STREAM_BINDER_H

+#define __STREAM_BINDER_H

+

+#include "../../Windows/Synchronization.h"

 

 #include "../IStream.h"

-#include "../../Windows/Synchronization.h"

 

 class CStreamBinder

 {

-  NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent;

-  NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent;

-  NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent;

-  UInt32 _bufferSize;

-  const void *_buffer;

+  NWindows::NSynchronization::CManualResetEvent _canWrite_Event;

+  NWindows::NSynchronization::CManualResetEvent _canRead_Event;

+  NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;

+  bool _waitWrite;

+  UInt32 _bufSize;

+  const void *_buf;

 public:

-  // bool ReadingWasClosed;

   UInt64 ProcessedSize;

-  CStreamBinder() {}

-  HRes CreateEvents();

 

-  void CreateStreams(ISequentialInStream **inStream,

-      ISequentialOutStream **outStream);

-  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);

-  void CloseRead();

-

-  HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);

-  void CloseWrite();

+  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 CloseWrite()

+  {

+    // _bufSize must be = 0

+    _canRead_Event.Set();

+  }

 };

 

 #endif

diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
old mode 100755
new mode 100644
index a18f1bc..6709842
--- a/CPP/7zip/Common/StreamObjects.cpp
+++ b/CPP/7zip/Common/StreamObjects.cpp
@@ -2,6 +2,8 @@
 

 #include "StdAfx.h"

 

+#include <stdlib.h>

+

 #include "../../../C/Alloc.h"

 

 #include "StreamObjects.h"

@@ -12,8 +14,8 @@
     *processedSize = 0;

   if (size == 0)

     return S_OK;

-  if (_pos > _size)

-    return E_FAIL;

+  if (_pos >= _size)

+    return S_OK;

   size_t rem = _size - (size_t)_pos;

   if (rem > size)

     rem = (size_t)size;

@@ -26,26 +28,51 @@
 

 STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET: _pos = offset; break;

-    case STREAM_SEEK_CUR: _pos += offset; break;

-    case STREAM_SEEK_END: _pos = _size + offset; break;

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _pos; break;

+    case STREAM_SEEK_END: offset += _size; break;

     default: return STG_E_INVALIDFUNCTION;

   }

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _pos = offset;

   if (newPosition)

-    *newPosition = _pos;

+    *newPosition = offset;

   return S_OK;

 }

 

-void CByteDynBuffer::Free()

+/*

+void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream)

+{

+  CBufInStream *inStreamSpec = new CBufInStream;

+  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;

+  inStreamSpec->Init((const Byte *)data, size);

+  *stream = streamTemp.Detach();

+}

+*/

+

+void Create_BufInStream_WithNewBuf(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;

+  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;

+  inStreamSpec->Init(referenceBuf);

+  *stream = streamTemp.Detach();

+}

+

+void CByteDynBuffer::Free() throw()

 {

   free(_buf);

   _buf = 0;

   _capacity = 0;

 }

 

-bool CByteDynBuffer::EnsureCapacity(size_t cap)

+bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()

 {

   if (cap <= _capacity)

     return true;

@@ -77,8 +104,7 @@
 

 void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const

 {

-  dest.SetCapacity(_size);

-  memcpy(dest, _buffer, _size);

+  dest.CopyFrom((const Byte *)_buffer, _size);

 }

 

 STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

@@ -121,7 +147,7 @@
 

 static const UInt64 kEmptyTag = (UInt64)(Int64)-1;

 

-void CCachedInStream::Free()

+void CCachedInStream::Free() throw()

 {

   MyFree(_tags);

   _tags = 0;

@@ -129,7 +155,7 @@
   _data = 0;

 }

 

-bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog)

+bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()

 {

   unsigned sizeLog = blockSizeLog + numBlocksLog;

   if (sizeLog >= sizeof(size_t) * 8)

@@ -155,7 +181,7 @@
   return true;

 }

 

-void CCachedInStream::Init(UInt64 size)

+void CCachedInStream::Init(UInt64 size) throw()

 {

   _size = size;

   _pos = 0;

@@ -170,8 +196,8 @@
     *processedSize = 0;

   if (size == 0)

     return S_OK;

-  if (_pos > _size)

-    return E_FAIL;

+  if (_pos >= _size)

+    return S_OK;

 

   {

     UInt64 rem = _size - _pos;

@@ -208,14 +234,17 @@
  

 STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

 {

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET: _pos = offset; break;

-    case STREAM_SEEK_CUR: _pos = _pos + offset; break;

-    case STREAM_SEEK_END: _pos = _size + offset; break;

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: offset += _pos; break;

+    case STREAM_SEEK_END: offset += _size; break;

     default: return STG_E_INVALIDFUNCTION;

   }

-  if (newPosition != 0)

-    *newPosition = _pos;

+  if (offset < 0)

+    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;

+  _pos = offset;

+  if (newPosition)

+    *newPosition = offset;

   return S_OK;

 }

diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h
old mode 100755
new mode 100644
index ed1532c..16c35b8
--- a/CPP/7zip/Common/StreamObjects.h
+++ b/CPP/7zip/Common/StreamObjects.h
@@ -3,8 +3,10 @@
 #ifndef __STREAM_OBJECTS_H

 #define __STREAM_OBJECTS_H

 

-#include "../../Common/Buffer.h"

+#include "../../Common/MyBuffer.h"

 #include "../../Common/MyCom.h"

+#include "../../Common/MyVector.h"

+

 #include "../IStream.h"

 

 struct CReferenceBuf:

@@ -31,13 +33,16 @@
     _pos = 0;

     _ref = ref;

   }

-  void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); }

+  void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }

 

-  MY_UNKNOWN_IMP1(IInStream)

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

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

+

 class CByteDynBuffer

 {

   size_t _capacity;

@@ -46,11 +51,11 @@
   CByteDynBuffer(): _capacity(0), _buf(0) {};

   // there is no copy constructor. So don't copy this object.

   ~CByteDynBuffer() { Free(); }

-  void Free();

-  size_t GetCapacity() const { return  _capacity; }

+  void Free() throw();

+  size_t GetCapacity() const { return _capacity; }

   operator Byte*() const { return _buf; };

   operator const Byte*() const { return _buf; };

-  bool EnsureCapacity(size_t capacity);

+  bool EnsureCapacity(size_t capacity) throw();

 };

 

 class CDynBufSeqOutStream:

@@ -68,7 +73,7 @@
   Byte *GetBufPtrForWriting(size_t addSize);

   void UpdateSize(size_t addSize) { _size += addSize; }

 

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

@@ -88,7 +93,7 @@
   }

   size_t GetPos() const { return _pos; }

 

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

@@ -103,7 +108,7 @@
   void Init() { _size = 0; }

   UInt64 GetSize() const { return _size; }

 

-  MY_UNKNOWN_IMP

+  MY_UNKNOWN_IMP1(ISequentialOutStream)

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

@@ -123,9 +128,9 @@
 public:

   CCachedInStream(): _tags(0), _data(0) {}

   virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!

-  void Free();

-  bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog);

-  void Init(UInt64 size);

+  void Free() throw();

+  bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();

+  void Init(UInt64 size) throw();

 

   MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

diff --git a/CPP/7zip/Common/StreamUtils.cpp b/CPP/7zip/Common/StreamUtils.cpp
old mode 100755
new mode 100644
index 57ff4ee..a79de23
--- a/CPP/7zip/Common/StreamUtils.cpp
+++ b/CPP/7zip/Common/StreamUtils.cpp
@@ -6,7 +6,7 @@
 

 static const UInt32 kBlockSize = ((UInt32)1 << 31);

 

-HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize)

+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()

 {

   size_t size = *processedSize;

   *processedSize = 0;

@@ -25,21 +25,21 @@
   return S_OK;

 }

 

-HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size)

+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()

 {

   size_t processedSize = size;

   RINOK(ReadStream(stream, data, &processedSize));

   return (size == processedSize) ? S_OK : S_FALSE;

 }

 

-HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size)

+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()

 {

   size_t processedSize = size;

   RINOK(ReadStream(stream, data, &processedSize));

   return (size == processedSize) ? S_OK : E_FAIL;

 }

 

-HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size)

+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw()

 {

   while (size != 0)

   {

diff --git a/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h
old mode 100755
new mode 100644
index 30535ab..799a8b9
--- a/CPP/7zip/Common/StreamUtils.h
+++ b/CPP/7zip/Common/StreamUtils.h
@@ -1,13 +1,13 @@
 // StreamUtils.h

 

-#ifndef __STREAMUTILS_H

-#define __STREAMUTILS_H

+#ifndef __STREAM_UTILS_H

+#define __STREAM_UTILS_H

 

 #include "../IStream.h"

 

-HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size);

-HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size);

-HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size);

-HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size);

+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();

+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();

+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();

+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw();

 

 #endif

diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp
new file mode 100644
index 0000000..8808f96
--- /dev/null
+++ b/CPP/7zip/Common/UniqBlocks.cpp
@@ -0,0 +1,56 @@
+// UniqBlocks.cpp

+

+#include "StdAfx.h"

+

+#include "UniqBlocks.h"

+

+int 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];

+    const CByteBuffer &buf = Bufs[index];

+    size_t sizeMid = buf.Size();

+    if (size < sizeMid)

+      right = mid;

+    else if (size > sizeMid)

+      left = mid + 1;

+    else

+    {

+      int cmp = memcmp(data, buf, size);

+      if (cmp == 0)

+        return index;

+      if (cmp < 0)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+  }

+  int index = Bufs.Size();

+  Sorted.Insert(left, index);

+  CByteBuffer &buf = Bufs.AddNew();

+  buf.CopyFrom(data, size);

+  return index;

+}

+

+UInt64 CUniqBlocks::GetTotalSizeInBytes() const

+{

+  UInt64 size = 0;

+  FOR_VECTOR (i, Bufs)

+    size += Bufs[i].Size();

+  return size;

+}

+

+void CUniqBlocks::GetReverseMap()

+{

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

+}

diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h
new file mode 100644
index 0000000..5b0dfb8
--- /dev/null
+++ b/CPP/7zip/Common/UniqBlocks.h
@@ -0,0 +1,30 @@
+// UniqBlocks.h

+

+#ifndef __UNIQ_BLOCKS_H

+#define __UNIQ_BLOCKS_H

+

+#include "../../Common/MyTypes.h"

+#include "../../Common/MyBuffer.h"

+#include "../../Common/MyVector.h"

+

+struct CUniqBlocks

+{

+  CObjectVector<CByteBuffer> Bufs;

+  CIntVector Sorted;

+  CIntVector BufIndexToSortedIndex;

+

+  int 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;

+  }

+};

+

+#endif

diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp
old mode 100755
new mode 100644
index c07caba..3cf9acd
--- a/CPP/7zip/Common/VirtThread.cpp
+++ b/CPP/7zip/Common/VirtThread.cpp
@@ -10,7 +10,7 @@
   {

     CVirtThread *t = (CVirtThread *)p;

     t->StartEvent.Lock();

-    if (t->ExitEvent)

+    if (t->Exit)

       return 0;

     t->Execute();

     t->FinishedEvent.Set();

@@ -23,7 +23,7 @@
   RINOK(FinishedEvent.CreateIfNotCreated());

   StartEvent.Reset();

   FinishedEvent.Reset();

-  ExitEvent = false;

+  Exit = false;

   if (Thread.IsCreated())

     return S_OK;

   return Thread.Create(CoderThread, this);

@@ -31,16 +31,18 @@
 

 void CVirtThread::Start()

 {

-  ExitEvent = false;

+  Exit = false;

   StartEvent.Set();

 }

 

-CVirtThread::~CVirtThread()

+void CVirtThread::WaitThreadFinish()

 {

-  ExitEvent = true;

+  Exit = true;

   if (StartEvent.IsCreated())

     StartEvent.Set();

   if (Thread.IsCreated())

+  {

     Thread.Wait();

+    Thread.Close();

+  }

 }

-

diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h
old mode 100755
new mode 100644
index bfc10dc..a271103
--- a/CPP/7zip/Common/VirtThread.h
+++ b/CPP/7zip/Common/VirtThread.h
@@ -1,7 +1,7 @@
 // VirtThread.h

 

-#ifndef __VIRTTHREAD_H

-#define __VIRTTHREAD_H

+#ifndef __VIRT_THREAD_H

+#define __VIRT_THREAD_H

 

 #include "../../Windows/Synchronization.h"

 #include "../../Windows/Thread.h"

@@ -11,13 +11,14 @@
   NWindows::NSynchronization::CAutoResetEvent StartEvent;

   NWindows::NSynchronization::CAutoResetEvent FinishedEvent;

   NWindows::CThread Thread;

-  bool ExitEvent;

+  bool Exit;

 

-  ~CVirtThread();

+  ~CVirtThread() { WaitThreadFinish(); }

+  void WaitThreadFinish(); // call it in destructor of child class !

   WRes Create();

   void Start();

-  void WaitFinish() { FinishedEvent.Lock(); }

   virtual void Execute() = 0;

+  void WaitExecuteFinish() { FinishedEvent.Lock(); }

 };

 

 #endif

diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
old mode 100755
new mode 100644
index 05590e7..636994c
--- a/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -15,35 +15,22 @@
 

 #ifndef EXTRACT_ONLY

 

-static const int kBufferSize = 1 << 17;

+static const unsigned kBufSize = 1 << 17;

+

+#define NUM_BITS 2

+#define SIGN_BIT (1 << NUM_BITS)

+#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1)))

+

+static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS));

 

 static bool inline Test86MSByte(Byte b)

 {

-  return (b == 0 || b == 0xFF);

-}

-

-bool CEncoder::Create()

-{

-  if (!_mainStream.Create(1 << 18))

-    return false;

-  if (!_callStream.Create(1 << 18))

-    return false;

-  if (!_jumpStream.Create(1 << 18))

-    return false;

-  if (!_rangeEncoder.Create(1 << 20))

-    return false;

-  if (_buffer == 0)

-  {

-    _buffer = (Byte *)MidAlloc(kBufferSize);

-    if (_buffer == 0)

-      return false;

-  }

-  return true;

+  return (((b) + SIGN_BIT) & MASK_HIGH) == 0;

 }

 

 CEncoder::~CEncoder()

 {

-  ::MidFree(_buffer);

+  ::MidFree(_buf);

 }

 

 HRESULT CEncoder::Flush()

@@ -51,12 +38,10 @@
   RINOK(_mainStream.Flush());

   RINOK(_callStream.Flush());

   RINOK(_jumpStream.Flush());

-  _rangeEncoder.FlushData();

-  return _rangeEncoder.FlushStream();

+  _rc.FlushData();

+  return _rc.FlushStream();

 }

 

-const UInt32 kDefaultLimit = (1 << 24);

-

 HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

     ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,

     ICompressProgressInfo *progress)

@@ -64,32 +49,34 @@
   if (numInStreams != 1 || numOutStreams != 4)

     return E_INVALIDARG;

 

-  if (!Create())

-    return E_OUTOFMEMORY;

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

+  {

+    _buf = (Byte *)MidAlloc(kBufSize);

+    if (_buf == 0)

+      return E_OUTOFMEMORY;

+  }

 

   bool sizeIsDefined = false;

   UInt64 inSize = 0;

-  if (inSizes != NULL)

-    if (inSizes[0] != NULL)

+  if (inSizes)

+    if (inSizes[0])

     {

       inSize = *inSizes[0];

       if (inSize <= kDefaultLimit)

         sizeIsDefined = true;

     }

 

-  CCoderReleaser releaser(this);

-

   ISequentialInStream *inStream = inStreams[0];

 

-  _mainStream.SetStream(outStreams[0]);

-  _mainStream.Init();

-  _callStream.SetStream(outStreams[1]);

-  _callStream.Init();

-  _jumpStream.SetStream(outStreams[2]);

-  _jumpStream.Init();

-  _rangeEncoder.SetStream(outStreams[3]);

-  _rangeEncoder.Init();

-  for (int i = 0; i < 256 + 2; i++)

+  _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;

@@ -99,12 +86,12 @@
 

   UInt32 nowPos = 0;

   UInt64 nowPos64 = 0;

-  UInt32 bufferPos = 0;

+  UInt32 bufPos = 0;

 

   Byte prevByte = 0;

 

   UInt64 subStreamIndex = 0;

-  UInt64 subStreamStartPos  = 0;

+  UInt64 subStreamStartPos = 0;

   UInt64 subStreamEndPos = 0;

 

   for (;;)

@@ -112,23 +99,23 @@
     UInt32 processedSize = 0;

     for (;;)

     {

-      UInt32 size = kBufferSize - (bufferPos + processedSize);

+      UInt32 size = kBufSize - (bufPos + processedSize);

       UInt32 processedSizeLoc;

       if (size == 0)

         break;

-      RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));

+      RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc));

       if (processedSizeLoc == 0)

         break;

       processedSize += processedSizeLoc;

     }

-    UInt32 endPos = bufferPos + processedSize;

+    UInt32 endPos = bufPos + processedSize;

     

     if (endPos < 5)

     {

       // change it

-      for (bufferPos = 0; bufferPos < endPos; bufferPos++)

+      for (bufPos = 0; bufPos < endPos; bufPos++)

       {

-        Byte b = _buffer[bufferPos];

+        Byte b = _buf[bufPos];

         _mainStream.WriteByte(b);

         UInt32 index;

         if (b == 0xE8)

@@ -142,37 +129,37 @@
           prevByte = b;

           continue;

         }

-        _statusEncoder[index].Encode(&_rangeEncoder, 0);

+        _statusEncoder[index].Encode(&_rc, 0);

         prevByte = b;

       }

       return Flush();

     }

 

-    bufferPos = 0;

+    bufPos = 0;

 

     UInt32 limit = endPos - 5;

-    while(bufferPos <= limit)

+    while (bufPos <= limit)

     {

-      Byte b = _buffer[bufferPos];

+      Byte b = _buf[bufPos];

       _mainStream.WriteByte(b);

       if (!IsJ(prevByte, b))

       {

-        bufferPos++;

+        bufPos++;

         prevByte = b;

         continue;

       }

-      Byte nextByte = _buffer[bufferPos + 4];

+      Byte nextByte = _buf[bufPos + 4];

       UInt32 src =

         (UInt32(nextByte) << 24) |

-        (UInt32(_buffer[bufferPos + 3]) << 16) |

-        (UInt32(_buffer[bufferPos + 2]) << 8) |

-        (_buffer[bufferPos + 1]);

-      UInt32 dest = (nowPos + bufferPos + 5) + src;

+        (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 != NULL)

+      if (getSubStreamSize)

       {

-        UInt64 currentPos = (nowPos64 + bufferPos);

+        UInt64 currentPos = (nowPos64 + bufPos);

         while (subStreamEndPos < currentPos)

         {

           UInt64 subStreamSize;

@@ -214,8 +201,8 @@
       unsigned index = GetIndex(prevByte, b);

       if (convert)

       {

-        _statusEncoder[index].Encode(&_rangeEncoder, 1);

-        bufferPos += 5;

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

@@ -223,30 +210,30 @@
       }

       else

       {

-        _statusEncoder[index].Encode(&_rangeEncoder, 0);

-        bufferPos++;

+        _statusEncoder[index].Encode(&_rc, 0);

+        bufPos++;

         prevByte = b;

       }

     }

-    nowPos += bufferPos;

-    nowPos64 += bufferPos;

+    nowPos += bufPos;

+    nowPos64 += bufPos;

 

-    if (progress != NULL)

+    if (progress)

     {

       /*

       const UInt64 compressedSize =

         _mainStream.GetProcessedSize() +

         _callStream.GetProcessedSize() +

         _jumpStream.GetProcessedSize() +

-        _rangeEncoder.GetProcessedSize();

+        _rc.GetProcessedSize();

       */

       RINOK(progress->SetRatioInfo(&nowPos64, NULL));

     }

  

     UInt32 i = 0;

-    while(bufferPos < endPos)

-      _buffer[i++] = _buffer[bufferPos++];

-    bufferPos = i;

+    while (bufPos < endPos)

+      _buf[i++] = _buf[bufPos++];

+    bufPos = i;

   }

 }

 

@@ -284,46 +271,39 @@
   if (numInStreams != 4 || numOutStreams != 1)

     return E_INVALIDARG;

 

-  if (!_mainInStream.Create(_inBufSizes[0]))

-    return E_OUTOFMEMORY;

-  if (!_callStream.Create(_inBufSizes[1]))

-    return E_OUTOFMEMORY;

-  if (!_jumpStream.Create(_inBufSizes[2]))

-    return E_OUTOFMEMORY;

-  if (!_rangeDecoder.Create(_inBufSizes[3]))

-    return E_OUTOFMEMORY;

-  if (!_outStream.Create(_outBufSize))

-    return E_OUTOFMEMORY;

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

 

-  CCoderReleaser releaser(this);

-

-  _mainInStream.SetStream(inStreams[0]);

+  _mainStream.SetStream(inStreams[0]);

   _callStream.SetStream(inStreams[1]);

   _jumpStream.SetStream(inStreams[2]);

-  _rangeDecoder.SetStream(inStreams[3]);

+  _rc.SetStream(inStreams[3]);

   _outStream.SetStream(outStreams[0]);

 

-  _mainInStream.Init();

+  _mainStream.Init();

   _callStream.Init();

   _jumpStream.Init();

-  _rangeDecoder.Init();

+  _rc.Init();

   _outStream.Init();

 

-  for (int i = 0; i < 256 + 2; i++)

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

     _statusDecoder[i].Init();

 

   Byte prevByte = 0;

   UInt32 processedBytes = 0;

   for (;;)

   {

-    if (processedBytes >= (1 << 20) && progress != NULL)

+    if (processedBytes >= (1 << 20) && progress)

     {

       /*

       const UInt64 compressedSize =

-        _mainInStream.GetProcessedSize() +

+        _mainStream.GetProcessedSize() +

         _callStream.GetProcessedSize() +

         _jumpStream.GetProcessedSize() +

-        _rangeDecoder.GetProcessedSize();

+        _rc.GetProcessedSize();

       */

       const UInt64 nowPos64 = _outStream.GetProcessedSize();

       RINOK(progress->SetRatioInfo(NULL, &nowPos64));

@@ -334,8 +314,8 @@
     const UInt32 kBurstSize = (1 << 18);

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

     {

-      if (!_mainInStream.ReadByte(b))

-        return Flush();

+      if (!_mainStream.ReadByte(b))

+        return _outStream.Flush();

       _outStream.WriteByte(b);

       if (IsJ(prevByte, b))

         break;

@@ -345,14 +325,14 @@
     if (i == kBurstSize)

       continue;

     unsigned index = GetIndex(prevByte, b);

-    if (_statusDecoder[index].Decode(&_rangeDecoder) == 1)

+    if (_statusDecoder[index].Decode(&_rc) == 1)

     {

       UInt32 src = 0;

       CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;

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

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

       {

         Byte b0;

-        if(!s.ReadByte(b0))

+        if (!s.ReadByte(b0))

           return S_FALSE;

         src <<= 8;

         src |= ((UInt32)b0);

diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
old mode 100755
new mode 100644
index c8f0893..4d6994f
--- a/CPP/7zip/Compress/Bcj2Coder.h
+++ b/CPP/7zip/Compress/Bcj2Coder.h
@@ -12,7 +12,7 @@
 namespace NCompress {

 namespace NBcj2 {

 

-const int kNumMoveBits = 5;

+const unsigned kNumMoveBits = 5;

 

 #ifndef EXTRACT_ONLY

 

@@ -20,32 +20,15 @@
   public ICompressCoder2,

   public CMyUnknownImp

 {

-  Byte *_buffer;

-  bool Create();

+  Byte *_buf;

 

   COutBuffer _mainStream;

   COutBuffer _callStream;

   COutBuffer _jumpStream;

-  NCompress::NRangeCoder::CEncoder _rangeEncoder;

-  NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];

+  NRangeCoder::CEncoder _rc;

+  NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];

 

   HRESULT Flush();

-public:

-  void ReleaseStreams()

-  {

-    _mainStream.ReleaseStream();

-    _callStream.ReleaseStream();

-    _jumpStream.ReleaseStream();

-    _rangeEncoder.ReleaseStream();

-  }

-

-  class CCoderReleaser

-  {

-    CEncoder *_coder;

-  public:

-    CCoderReleaser(CEncoder *coder): _coder(coder) {}

-    ~CCoderReleaser() {  _coder->ReleaseStreams(); }

-  };

 

 public:

   MY_UNKNOWN_IMP

@@ -56,7 +39,8 @@
   STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

       ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

       ICompressProgressInfo *progress);

-  CEncoder(): _buffer(0) {};

+  

+  CEncoder(): _buf(0) {};

   ~CEncoder();

 };

 

@@ -67,37 +51,19 @@
   public ICompressSetBufSize,

   public CMyUnknownImp

 {

-  CInBuffer _mainInStream;

+  CInBuffer _mainStream;

   CInBuffer _callStream;

   CInBuffer _jumpStream;

-  NCompress::NRangeCoder::CDecoder _rangeDecoder;

-  NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];

+  NRangeCoder::CDecoder _rc;

+  NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];

 

   COutBuffer _outStream;

   UInt32 _inBufSizes[4];

   UInt32 _outBufSize;

 

 public:

-  void ReleaseStreams()

-  {

-    _mainInStream.ReleaseStream();

-    _callStream.ReleaseStream();

-    _jumpStream.ReleaseStream();

-    _rangeDecoder.ReleaseStream();

-    _outStream.ReleaseStream();

-  }

-

-  HRESULT Flush() { return _outStream.Flush(); }

-  class CCoderReleaser

-  {

-    CDecoder *_coder;

-  public:

-    CCoderReleaser(CDecoder *coder): _coder(coder) {}

-    ~CCoderReleaser()  { _coder->ReleaseStreams(); }

-  };

-

-public:

   MY_UNKNOWN_IMP1(ICompressSetBufSize);

+  

   HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

       ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

       ICompressProgressInfo *progress);

@@ -107,6 +73,7 @@
 

   STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

   STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

+

   CDecoder();

 };

 

diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
old mode 100755
new mode 100644
index 1a46bb1..1ac7949
--- a/CPP/7zip/Compress/BranchMisc.cpp
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -6,32 +6,16 @@
 

 #include "BranchMisc.h"

 

-UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); }

+#define SUB_FILTER_IMP2(name, coderStr, coderNum) \

+  UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \

+  { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); }

 

-UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); }

+#define SUB_FILTER_IMP(name) \

+  SUB_FILTER_IMP2(name, Encoder, 1) \

+  SUB_FILTER_IMP2(name, Decoder, 0) \

 

-UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); }

-

-UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); }

-

-UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); }

-

-UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); }

-

-UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); }

-

-UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); }

-

-UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)

-  { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); }

-

-UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)

-  {  return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); }

+SUB_FILTER_IMP(ARM_)

+SUB_FILTER_IMP(ARMT_)

+SUB_FILTER_IMP(PPC_)

+SUB_FILTER_IMP(SPARC_)

+SUB_FILTER_IMP(IA64_)

diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
old mode 100755
new mode 100644
index 84a27cf..8691d5d
--- a/CPP/7zip/Compress/CodecExports.cpp
+++ b/CPP/7zip/Compress/CodecExports.cpp
@@ -2,7 +2,10 @@
 

 #include "StdAfx.h"

 

+#include "../../../C/CpuArch.h"

+

 #include "../../Common/ComTry.h"

+#include "../../Common/MyCom.h"

 

 #include "../../Windows/PropVariant.h"

 

@@ -13,10 +16,15 @@
 extern unsigned int g_NumCodecs;

 extern const CCodecInfo *g_Codecs[];

 

+extern unsigned int 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

+0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);

 

 static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)

 {

@@ -30,13 +38,13 @@
   return SetPropString((const char *)&guid, sizeof(GUID), value);

 }

 

-static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)

+static HRESULT SetClassID(CMethodId id, UInt16 typeId, PROPVARIANT *value)

 {

-  GUID clsId = CLSID_CCodec;

-  for (int i = 0; i < sizeof(id); i++, id >>= 8)

-    clsId.Data4[i] = (Byte)(id & 0xFF);

-  if (encode)

-    clsId.Data3++;

+  GUID clsId;

+  clsId.Data1 = CLSID_CCodec.Data1;

+  clsId.Data2 = CLSID_CCodec.Data2;

+  clsId.Data3 = typeId;

+  SetUi64(clsId.Data4, id);

   return SetPropGUID(clsId, value);

 }

 

@@ -44,13 +52,14 @@
 {

   index = -1;

   if (clsID->Data1 != CLSID_CCodec.Data1 ||

-      clsID->Data2 != CLSID_CCodec.Data2 ||

-      (clsID->Data3 & ~1) != kDecodeId)

+      clsID->Data2 != CLSID_CCodec.Data2)

     return S_OK;

-  encode = (clsID->Data3 != kDecodeId);

-  UInt64 id = 0;

-  for (int j = 0; j < 8; j++)

-    id |= ((UInt64)clsID->Data4[j]) << (8 * j);

+  encode = true;

+  if (clsID->Data3 == kDecodeId)

+    encode = false;

+  else if (clsID->Data3 != kEncodeId)

+    return S_OK;

+  UInt64 id = GetUi64(clsID->Data4);

   for (unsigned i = 0; i < g_NumCodecs; i++)

   {

     const CCodecInfo &codec = *g_Codecs[i];

@@ -65,7 +74,7 @@
   return S_OK;

 }

 

-STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)

+STDAPI CreateCoder2(bool encode, int index, const GUID *iid, void **outObject)

 {

   COM_TRY_BEGIN

   *outObject = 0;

@@ -88,18 +97,22 @@
       return CLASS_E_CLASSNOTAVAILABLE;

     *outObject = codec.CreateDecoder();

   }

-  if (isCoder)

-    ((ICompressCoder *)*outObject)->AddRef();

-  else if (isCoder2)

-    ((ICompressCoder2 *)*outObject)->AddRef();

-  else

-    ((ICompressFilter *)*outObject)->AddRef();

+  if (*outObject)

+  {

+    if (isCoder)

+      ((ICompressCoder *)*outObject)->AddRef();

+    else if (isCoder2)

+      ((ICompressCoder2 *)*outObject)->AddRef();

+    else

+      ((ICompressFilter *)*outObject)->AddRef();

+  }

   return S_OK;

   COM_TRY_END

 }

 

 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)

 {

+  COM_TRY_BEGIN

   *outObject = 0;

   bool isCoder = (*iid == IID_ICompressCoder) != 0;

   bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;

@@ -113,42 +126,54 @@
     return res;

   if (codecIndex < 0)

     return CLASS_E_CLASSNOTAVAILABLE;

-  return CreateCoder2(encode, codecIndex, iid, outObject);

+

+  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

 }

 

 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)

 {

   ::VariantClear((VARIANTARG *)value);

   const CCodecInfo &codec = *g_Codecs[codecIndex];

-  switch(propID)

+  switch (propID)

   {

     case NMethodPropID::kID:

-    {

       value->uhVal.QuadPart = (UInt64)codec.Id;

       value->vt = VT_UI8;

       break;

-    }

     case NMethodPropID::kName:

       if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)

         value->vt = VT_BSTR;

       break;

     case NMethodPropID::kDecoder:

       if (codec.CreateDecoder)

-        return SetClassID(codec.Id, false, value);

+        return SetClassID(codec.Id, kDecodeId, value);

       break;

     case NMethodPropID::kEncoder:

       if (codec.CreateEncoder)

-        return SetClassID(codec.Id, true, value);

+        return SetClassID(codec.Id, kEncodeId, value);

       break;

     case NMethodPropID::kInStreams:

-    {

       if (codec.NumInStreams != 1)

       {

         value->vt = VT_UI4;

         value->ulVal = (ULONG)codec.NumInStreams;

       }

       break;

-    }

   }

   return S_OK;

 }

@@ -158,3 +183,101 @@
   *numCodecs = g_NumCodecs;

   return S_OK;

 }

+

+

+static int FindHasherClassId(const GUID *clsID)

+{

+  if (clsID->Data1 != CLSID_CCodec.Data1 ||

+      clsID->Data2 != CLSID_CCodec.Data2 ||

+      clsID->Data3 != kHasherId)

+    return -1;

+  UInt64 id = GetUi64(clsID->Data4);

+  for (unsigned i = 0; i < g_NumCodecs; i++)

+    if (id == g_Hashers[i]->Id)

+      return i;

+  return -1;

+}

+

+static HRESULT CreateHasher2(UInt32 index, IHasher **hasher)

+{

+  COM_TRY_BEGIN

+  *hasher = g_Hashers[index]->CreateHasher();

+  if (*hasher)

+    (*hasher)->AddRef();

+  return S_OK;

+  COM_TRY_END

+}

+

+STDAPI CreateHasher(const GUID *clsid, IHasher **outObject)

+{

+  COM_TRY_BEGIN

+  *outObject = 0;

+  int index = FindHasherClassId(clsid);

+  if (index < 0)

+    return CLASS_E_CLASSNOTAVAILABLE;

+  return CreateHasher2(index, outObject);

+  COM_TRY_END

+}

+

+STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)

+{

+  ::VariantClear((VARIANTARG *)value);

+  const CHasherInfo &codec = *g_Hashers[codecIndex];

+  switch (propID)

+  {

+    case NMethodPropID::kID:

+      value->uhVal.QuadPart = (UInt64)codec.Id;

+      value->vt = VT_UI8;

+      break;

+    case NMethodPropID::kName:

+      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)

+        value->vt = VT_BSTR;

+      break;

+    case NMethodPropID::kEncoder:

+      if (codec.CreateHasher)

+        return SetClassID(codec.Id, kHasherId, value);

+      break;

+    case NMethodPropID::kDigestSize:

+      value->ulVal = (ULONG)codec.DigestSize;

+      value->vt = VT_UI4;

+      break;

+  }

+  return S_OK;

+}

+

+class CHashers:

+  public IHashers,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP1(IHashers)

+

+  STDMETHOD_(UInt32, GetNumHashers)();

+  STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);

+};

+

+STDAPI GetHashers(IHashers **hashers)

+{

+  COM_TRY_BEGIN

+  *hashers = new CHashers;

+  if (*hashers)

+    (*hashers)->AddRef();

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP_(UInt32) CHashers::GetNumHashers()

+{

+  return g_NumHashers;

+}

+

+STDMETHODIMP CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  return ::GetHasherProp(index, propID, value);

+}

+

+STDMETHODIMP CHashers::CreateHasher(UInt32 index, IHasher **hasher)

+{

+  return ::CreateHasher2(index, hasher);

+}

diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
old mode 100755
new mode 100644
index da15d04..66ab85e
--- a/CPP/7zip/Compress/CopyCoder.cpp
+++ b/CPP/7zip/Compress/CopyCoder.cpp
@@ -22,10 +22,10 @@
     const UInt64 * /* inSize */, const UInt64 *outSize,

     ICompressProgressInfo *progress)

 {

-  if (_buffer == 0)

+  if (!_buffer)

   {

     _buffer = (Byte *)::MidAlloc(kBufferSize);

-    if (_buffer == 0)

+    if (!_buffer)

       return E_OUTOFMEMORY;

   }

 

@@ -33,9 +33,8 @@
   for (;;)

   {

     UInt32 size = kBufferSize;

-    if (outSize != 0)

-      if (size > *outSize - TotalSize)

-        size = (UInt32)(*outSize - TotalSize);

+    if (outSize && size > *outSize - TotalSize)

+      size = (UInt32)(*outSize - TotalSize);

     RINOK(inStream->Read(_buffer, size, &size));

     if (size == 0)

       break;

@@ -44,7 +43,7 @@
       RINOK(WriteStream(outStream, _buffer, size));

     }

     TotalSize += size;

-    if (progress != NULL)

+    if (progress)

     {

       RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));

     }

@@ -60,8 +59,16 @@
 

 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)

 {

-  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;

+  CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;

   return copyCoder->Code(inStream, outStream, NULL, NULL, progress);

 }

 

+HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)

+{

+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;

+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

+  RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));

+  return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;

+}

+

 }

diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
old mode 100755
new mode 100644
index 16c42ee..254266a
--- a/CPP/7zip/Compress/CopyCoder.h
+++ b/CPP/7zip/Compress/CopyCoder.h
@@ -28,6 +28,7 @@
 };

 

 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);

+HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress);

 

 }

 

diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
old mode 100755
new mode 100644
index e7e3822..a7f70fe
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -62,9 +62,22 @@
   for (UInt32 i = 0; i < numProps; i++)

   {

     const PROPVARIANT &prop = props[i];

-    if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256)

+    PROPID propID = propIDs[i];

+    if (propID >= NCoderPropID::kReduceSize)

+      continue;

+    if (prop.vt != VT_UI4)

       return E_INVALIDARG;

-    delta = prop.ulVal;

+    switch (propID)

+    {

+      case NCoderPropID::kDefaultProp:

+        delta = (UInt32)prop.ulVal;

+        if (delta < 1 || delta > 256)

+          return E_INVALIDARG;

+        break;

+      case NCoderPropID::kNumThreads: break;

+      case NCoderPropID::kLevel: break;

+      default: return E_INVALIDARG;

+    }

   }

   _delta = delta;

   return S_OK;

diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
old mode 100755
new mode 100644
index 9f15fdb..4ffb750
--- a/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -27,7 +27,8 @@
 CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),

   _inBufSize(1 << 20),

   _outBufSize(1 << 22),

-  FinishStream(false)

+  FinishStream(false),

+  NeedMoreInput(false)

 {

   _inSizeProcessed = 0;

   _inPos = _inSize = 0;

@@ -81,6 +82,7 @@
 {

   _inSizeProcessed = 0;

   _inPos = _inSize = 0;

+  NeedMoreInput = false;

   SetOutStreamSizeResume(outSize);

   return S_OK;

 }

@@ -144,9 +146,21 @@
         return S_FALSE;

       RINOK(res2);

       if (stopDecoding)

+      {

+        if (status == LZMA_STATUS_NEEDS_MORE_INPUT)

+          NeedMoreInput = true;

+        if (FinishStream &&

+              status != LZMA_STATUS_FINISHED_WITH_MARK &&

+              status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)

+          return S_FALSE;

         return S_OK;

+      }

       if (finished)

+      {

+        if (status == LZMA_STATUS_NEEDS_MORE_INPUT)

+          NeedMoreInput = true;

         return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);

+      }

     }

     if (progress)

     {

diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
old mode 100755
new mode 100644
index 801a77b..191fbf9
--- a/CPP/7zip/Compress/LzmaDecoder.h
+++ b/CPP/7zip/Compress/LzmaDecoder.h
@@ -73,10 +73,14 @@
 

   #endif

 

-  bool FinishStream;

+  bool FinishStream; // set it before decoding, if you need to decode full LZMA stream

+  

+  bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream

 

   CDecoder();

   virtual ~CDecoder();

+

+  UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; }

 };

 

 }}

diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
old mode 100755
new mode 100644
index aa96c0e..e6feb79
--- a/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -73,6 +73,8 @@
   return 1;

 }

 

+#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;

+

 HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)

 {

   if (propID == NCoderPropID::kMatchFinder)

@@ -81,18 +83,29 @@
       return E_INVALIDARG;

     return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;

   }

+  if (propID > NCoderPropID::kReduceSize)

+    return S_OK;

+  if (propID == NCoderPropID::kReduceSize)

+  {

+    if (prop.vt == VT_UI8)

+      ep.reduceSize = prop.uhVal.QuadPart;

+    return S_OK;

+  }

   if (prop.vt != VT_UI4)

     return E_INVALIDARG;

   UInt32 v = prop.ulVal;

   switch (propID)

   {

-    case NCoderPropID::kNumFastBytes: ep.fb = v; break;

-    case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;

-    case NCoderPropID::kAlgorithm: ep.algo = v; break;

-    case NCoderPropID::kDictionarySize: ep.dictSize = v; break;

-    case NCoderPropID::kPosStateBits: ep.pb = v; break;

-    case NCoderPropID::kLitPosBits: ep.lp = v; break;

-    case NCoderPropID::kLitContextBits: ep.lc = v; break;

+    case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break;

+    SET_PROP_32(kLevel, level)

+    SET_PROP_32(kNumFastBytes, fb)

+    SET_PROP_32(kMatchFinderCycles, mc)

+    SET_PROP_32(kAlgorithm, algo)

+    SET_PROP_32(kDictionarySize, dictSize)

+    SET_PROP_32(kPosStateBits, pb)

+    SET_PROP_32(kLitPosBits, lp)

+    SET_PROP_32(kLitContextBits, lc)

+    SET_PROP_32(kNumThreads, numThreads)

     default: return E_INVALIDARG;

   }

   return S_OK;

@@ -111,9 +124,7 @@
     switch (propID)

     {

       case NCoderPropID::kEndMarker:

-        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;

-      case NCoderPropID::kNumThreads:

-        if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;

+        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break;

       default:

         RINOK(SetLzmaProp(propID, prop, props));

     }

@@ -137,6 +148,7 @@
   CCompressProgressWrap progressWrap(progress);

 

   SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);

+  _inputProcessed = inWrap.Processed;

   if (res == SZ_ERROR_READ && inWrap.Res != S_OK)

     return inWrap.Res;

   if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)

@@ -145,5 +157,5 @@
     return progressWrap.Res;

   return SResToHRESULT(res);

 }

-  

+

 }}

diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
old mode 100755
new mode 100644
index c3e8961..3db30a9
--- a/CPP/7zip/Compress/LzmaEncoder.h
+++ b/CPP/7zip/Compress/LzmaEncoder.h
@@ -19,6 +19,7 @@
   public CMyUnknownImp

 {

   CLzmaEncHandle _encoder;

+  UInt64 _inputProcessed;

 public:

   MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

     

@@ -29,6 +30,7 @@
 

   CEncoder();

   virtual ~CEncoder();

+  UInt64 GetInputProcessedSize() const { return _inputProcessed; }

 };

 

 }}

diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
new file mode 100644
index 0000000..2373185
--- /dev/null
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -0,0 +1,167 @@
+// PpmdDecoder.cpp

+// 2009-03-11 : Igor Pavlov : Public domain

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+#include "../../../C/CpuArch.h"

+

+#include "../Common/StreamUtils.h"

+

+#include "PpmdDecoder.h"

+

+namespace NCompress {

+namespace NPpmd {

+

+static const UInt32 kBufSize = (1 << 20);

+

+enum

+{

+  kStatus_NeedInit,

+  kStatus_Normal,

+  kStatus_Finished,

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

+  Ppmd7_Free(&_ppmd, &g_BigAlloc);

+}

+

+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)

+{

+  if (size < 5)

+    return E_INVALIDARG;

+  _order = props[0];

+  UInt32 memSize = GetUi32(props + 1);

+  if (_order < PPMD7_MIN_ORDER ||

+      _order > PPMD7_MAX_ORDER ||

+      memSize < PPMD7_MIN_MEM_SIZE ||

+      memSize > PPMD7_MAX_MEM_SIZE)

+    return E_NOTIMPL;

+  if (!_inStream.Alloc(1 << 20))

+    return E_OUTOFMEMORY;

+  if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))

+    return E_OUTOFMEMORY;

+  return S_OK;

+}

+

+HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)

+{

+  switch(_status)

+  {

+    case kStatus_Finished: return S_OK;

+    case kStatus_Error: return S_FALSE;

+    case kStatus_NeedInit:

+      _inStream.Init();

+      if (!Ppmd7z_RangeDec_Init(&_rangeDec))

+      {

+        _status = kStatus_Error;

+        return S_FALSE;

+      }

+      _status = kStatus_Normal;

+      Ppmd7_Init(&_ppmd, _order);

+      break;

+  }

+  if (_outSizeDefined)

+  {

+    const UInt64 rem = _outSize - _processedSize;

+    if (size > rem)

+      size = (UInt32)rem;

+  }

+

+  UInt32 i;

+  int sym = 0;

+  for (i = 0; i != size; i++)

+  {

+    sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p);

+    if (_inStream.Extra || sym < 0)

+      break;

+    memStream[i] = (Byte)sym;

+  }

+

+  _processedSize += i;

+  if (_inStream.Extra)

+  {

+    _status = kStatus_Error;

+    return _inStream.Res;

+  }

+  if (sym < 0)

+    _status = (sym < -1) ? kStatus_Error : kStatus_Finished;

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)

+{

+  if (!_outBuf)

+  {

+    _outBuf = (Byte *)::MidAlloc(kBufSize);

+    if (!_outBuf)

+      return E_OUTOFMEMORY;

+  }

+  

+  _inStream.Stream = inStream;

+  SetOutStreamSize(outSize);

+

+  do

+  {

+    const UInt64 startPos = _processedSize;

+    HRESULT res = CodeSpec(_outBuf, kBufSize);

+    size_t processed = (size_t)(_processedSize - startPos);

+    RINOK(WriteStream(outStream, _outBuf, processed));

+    RINOK(res);

+    if (_status == kStatus_Finished)

+      break;

+    if (progress)

+    {

+      UInt64 inSize = _inStream.GetProcessed();

+      RINOK(progress->SetRatioInfo(&inSize, &_processedSize));

+    }

+  }

+  while (!_outSizeDefined || _processedSize < _outSize);

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)

+{

+  _outSizeDefined = (outSize != NULL);

+  if (_outSizeDefined)

+    _outSize = *outSize;

+  _processedSize = 0;

+  _status = kStatus_NeedInit;

+  return S_OK;

+}

+

+#ifndef NO_READ_FROM_CODER

+

+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)

+{

+  InSeqStream = inStream;

+  _inStream.Stream = inStream;

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::ReleaseInStream()

+{

+  InSeqStream.Release();

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  const UInt64 startPos = _processedSize;

+  HRESULT res = CodeSpec((Byte *)data, size);

+  if (processedSize)

+    *processedSize = (UInt32)(_processedSize - startPos);

+  return res;

+}

+

+#endif

+

+}}

diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
old mode 100755
new mode 100644
index 3a8df78..e232077
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -1,5 +1,4 @@
 // PpmdEncoder.cpp

-// 2009-03-11 : Igor Pavlov : Public domain

 

 #include "StdAfx.h"

 

@@ -19,11 +18,35 @@
 static void SzBigFree(void *, void *address) { BigFree(address); }

 static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

 

-CEncoder::CEncoder():

-  _inBuf(NULL),

-  _usedMemSize(1 << 24),

-  _order(6)

+static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };

+

+void CEncProps::Normalize(int level)

 {

+  if (level < 0) level = 5;

+  if (level > 9) level = 9;

+  if (MemSize == (UInt32)(Int32)-1)

+    MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19));

+  const unsigned kMult = 16;

+  if (MemSize / kMult > ReduceSize)

+  {

+    for (unsigned i = 16; i <= 31; i++)

+    {

+      UInt32 m = (UInt32)1 << i;

+      if (ReduceSize <= m / kMult)

+      {

+        if (MemSize > m)

+          MemSize = m;

+        break;

+      }

+    }

+  }

+  if (Order == -1) Order = kOrders[level];

+}

+

+CEncoder::CEncoder():

+  _inBuf(NULL)

+{

+  _props.Normalize(-1);

   _rangeEnc.Stream = &_outStream.p;

   Ppmd7_Construct(&_ppmd);

 }

@@ -34,30 +57,44 @@
   Ppmd7_Free(&_ppmd, &g_BigAlloc);

 }

 

-STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)

 {

+  int level = -1;

+  CEncProps props;

   for (UInt32 i = 0; i < numProps; i++)

   {

-    const PROPVARIANT &prop = props[i];

+    const PROPVARIANT &prop = coderProps[i];

+    PROPID propID = propIDs[i];

+    if (propID > NCoderPropID::kReduceSize)

+      continue;

+    if (propID == NCoderPropID::kReduceSize)

+    {

+      if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)

+        props.ReduceSize = (UInt32)prop.uhVal.QuadPart;

+      continue;

+    }

     if (prop.vt != VT_UI4)

       return E_INVALIDARG;

     UInt32 v = (UInt32)prop.ulVal;

-    switch(propIDs[i])

+    switch (propID)

     {

       case NCoderPropID::kUsedMemorySize:

         if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)

           return E_INVALIDARG;

-        _usedMemSize = v;

+        props.MemSize = v;

         break;

       case NCoderPropID::kOrder:

         if (v < 2 || v > 32)

           return E_INVALIDARG;

-        _order = (Byte)v;

+        props.Order = (Byte)v;

         break;

-      default:

-        return E_INVALIDARG;

+      case NCoderPropID::kNumThreads: break;

+      case NCoderPropID::kLevel: level = (int)v; break;

+      default: return E_INVALIDARG;

     }

   }

+  props.Normalize(level);

+  _props = props;

   return S_OK;

 }

 

@@ -65,8 +102,8 @@
 {

   const UInt32 kPropSize = 5;

   Byte props[kPropSize];

-  props[0] = _order;

-  SetUi32(props + 1, _usedMemSize);

+  props[0] = (Byte)_props.Order;

+  SetUi32(props + 1, _props.MemSize);

   return WriteStream(outStream, props, kPropSize);

 }

 

@@ -81,14 +118,14 @@
   }

   if (!_outStream.Alloc(1 << 20))

     return E_OUTOFMEMORY;

-  if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))

+  if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc))

     return E_OUTOFMEMORY;

 

   _outStream.Stream = outStream;

   _outStream.Init();

 

   Ppmd7z_RangeEnc_Init(&_rangeEnc);

-  Ppmd7_Init(&_ppmd, _order);

+  Ppmd7_Init(&_ppmd, _props.Order);

 

   UInt64 processed = 0;

   for (;;)

diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h
new file mode 100644
index 0000000..66ce437
--- /dev/null
+++ b/CPP/7zip/Compress/PpmdEncoder.h
@@ -0,0 +1,57 @@
+// PpmdEncoder.h

+

+#ifndef __COMPRESS_PPMD_ENCODER_H

+#define __COMPRESS_PPMD_ENCODER_H

+

+#include "../../../C/Ppmd7.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+#include "../Common/CWrappers.h"

+

+namespace NCompress {

+namespace NPpmd {

+

+struct CEncProps

+{

+  UInt32 MemSize;

+  UInt32 ReduceSize;

+  int Order;

+  

+  CEncProps()

+  {

+    MemSize = (UInt32)(Int32)-1;

+    ReduceSize = (UInt32)(Int32)-1;

+    Order = -1;

+  }

+  void Normalize(int level);

+};

+

+class CEncoder :

+  public ICompressCoder,

+  public ICompressSetCoderProperties,

+  public ICompressWriteCoderProperties,

+  public CMyUnknownImp

+{

+  Byte *_inBuf;

+  CByteOutBufWrap _outStream;

+  CPpmd7z_RangeEnc _rangeEnc;

+  CPpmd7 _ppmd;

+  CEncProps _props;

+public:

+  MY_UNKNOWN_IMP2(

+      ICompressSetCoderProperties,

+      ICompressWriteCoderProperties)

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+  CEncoder();

+  ~CEncoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h
old mode 100755
new mode 100644
index e9e8e32..2c254a5
--- a/CPP/7zip/Compress/RangeCoder.h
+++ b/CPP/7zip/Compress/RangeCoder.h
@@ -1,5 +1,5 @@
 // Compress/RangeCoder.h

-// 2009-05-30 : Igor Pavlov : Public domain

+// 2013-01-10 : Igor Pavlov : Public domain

 

 #ifndef __COMPRESS_RANGE_CODER_H

 #define __COMPRESS_RANGE_CODER_H

@@ -10,7 +10,7 @@
 namespace NCompress {

 namespace NRangeCoder {

 

-const int kNumTopBits = 24;

+const unsigned kNumTopBits = 24;

 const UInt32 kTopValue = (1 << kNumTopBits);

 

 class CEncoder

@@ -21,7 +21,7 @@
   UInt64 Low;

   UInt32 Range;

   COutBuffer Stream;

-  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }

+  bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }

 

   void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }

   void Init()

@@ -36,14 +36,12 @@
   void FlushData()

   {

     // Low += 1;

-    for(int i = 0; i < 5; i++)

+    for (int i = 0; i < 5; i++)

       ShiftLow();

   }

 

   HRESULT FlushStream() { return Stream.Flush();  }

 

-  void ReleaseStream() { Stream.ReleaseStream(); }

-

   void Encode(UInt32 start, UInt32 size, UInt32 total)

   {

     Low += start * (Range /= total);

@@ -57,7 +55,7 @@
 

   void ShiftLow()

   {

-    if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)

+    if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0)

     {

       Byte temp = _cache;

       do

@@ -65,7 +63,7 @@
         Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));

         temp = 0xFF;

       }

-      while(--_cacheSize != 0);

+      while (--_cacheSize != 0);

       _cache = (Byte)((UInt32)Low >> 24);

     }

     _cacheSize++;

@@ -103,7 +101,7 @@
     }

   }

 

-  UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }

+  UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }

 };

 

 class CDecoder

@@ -112,7 +110,7 @@
   CInBuffer Stream;

   UInt32 Range;

   UInt32 Code;

-  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }

+  bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }

 

   void Normalize()

   {

@@ -129,15 +127,13 @@
     Stream.Init();

     Code = 0;

     Range = 0xFFFFFFFF;

-    for(int i = 0; i < 5; i++)

+    for (int i = 0; i < 5; i++)

       Code = (Code << 8) | Stream.ReadByte();

   }

 

-  void ReleaseStream() { Stream.ReleaseStream(); }

-

   UInt32 GetThreshold(UInt32 total)

   {

-    return (Code) / ( Range /= total);

+    return (Code) / (Range /= total);

   }

 

   void Decode(UInt32 start, UInt32 size)

@@ -197,7 +193,7 @@
     return symbol;

   }

 

-  UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }

+  UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); }

 };

 

 }}

diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h
old mode 100755
new mode 100644
index f06408c..927a8dd
--- a/CPP/7zip/Compress/RangeCoderBit.h
+++ b/CPP/7zip/Compress/RangeCoderBit.h
@@ -1,5 +1,5 @@
 // Compress/RangeCoderBit.h

-// 2009-05-30 : Igor Pavlov : Public domain

+// 2013-01-10 : Igor Pavlov : Public domain

 

 #ifndef __COMPRESS_RANGE_CODER_BIT_H

 #define __COMPRESS_RANGE_CODER_BIT_H

@@ -9,17 +9,17 @@
 namespace NCompress {

 namespace NRangeCoder {

 

-const int kNumBitModelTotalBits  = 11;

+const unsigned kNumBitModelTotalBits = 11;

 const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);

 

-const int kNumMoveReducingBits = 4;

+const unsigned kNumMoveReducingBits = 4;

 

-const int kNumBitPriceShiftBits = 4;

+const unsigned kNumBitPriceShiftBits = 4;

 const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;

 

 extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

 

-template <int numMoveBits>

+template <unsigned numMoveBits>

 class CBitModel

 {

 public:

@@ -39,7 +39,7 @@
   void Init() { Prob = kBitModelTotal / 2; }

 };

 

-template <int numMoveBits>

+template <unsigned numMoveBits>

 class CBitEncoder: public CBitModel<numMoveBits>

 {

 public:

@@ -69,14 +69,14 @@
   }

   UInt32 GetPrice(UInt32 symbol) const

   {

-    return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];

+    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 <int numMoveBits>

+template <unsigned numMoveBits>

 class CBitDecoder: public CBitModel<numMoveBits>

 {

 public:

diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h
old mode 100755
new mode 100644
index c28ffce..42a088f
--- a/CPP/7zip/Compress/StdAfx.h
+++ b/CPP/7zip/Compress/StdAfx.h
@@ -3,6 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../Common/MyWindows.h"

+#include "../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
old mode 100755
new mode 100644
diff --git a/CPP/7zip/Crc64.mak b/CPP/7zip/Crc64.mak
new file mode 100644
index 0000000..08e56f9
--- /dev/null
+++ b/CPP/7zip/Crc64.mak
@@ -0,0 +1,8 @@
+C_OBJS = $(C_OBJS) \

+  $O\XzCrc64.obj

+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM"

+C_OBJS = $(C_OBJS) \

+!ELSE

+ASM_OBJS = $(ASM_OBJS) \

+!ENDIF

+  $O\XzCrc64Opt.obj

diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp
new file mode 100644
index 0000000..70c8473
--- /dev/null
+++ b/CPP/7zip/Crypto/7zAes.cpp
@@ -0,0 +1,240 @@
+// 7zAes.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Sha256.h"

+

+#include "../../Windows/Synchronization.h"

+

+#include "../Common/StreamObjects.h"

+#include "../Common/StreamUtils.h"

+

+#include "7zAes.h"

+#include "MyAes.h"

+

+#ifndef EXTRACT_ONLY

+#include "RandGen.h"

+#endif

+

+using namespace NWindows;

+

+namespace NCrypto {

+namespace NSevenZ {

+

+bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const

+{

+  if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)

+    return false;

+  for (UInt32 i = 0; i < SaltSize; i++)

+    if (Salt[i] != a.Salt[i])

+      return false;

+  return (Password == a.Password);

+}

+

+void CKeyInfo::CalculateDigest()

+{

+  if (NumCyclesPower == 0x3F)

+  {

+    UInt32 pos;

+    for (pos = 0; pos < SaltSize; pos++)

+      Key[pos] = Salt[pos];

+    for (UInt32 i = 0; i < Password.Size() && pos < kKeySize; i++)

+      Key[pos++] = Password[i];

+    for (; pos < kKeySize; pos++)

+      Key[pos] = 0;

+  }

+  else

+  {

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

+    {

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

+          break;

+    }

+    Sha256_Final(&sha, Key);

+  }

+}

+

+bool CKeyInfoCache::Find(CKeyInfo &key)

+{

+  FOR_VECTOR (i, Keys)

+  {

+    const CKeyInfo &cached = Keys[i];

+    if (key.IsEqualTo(cached))

+    {

+      for (int j = 0; j < kKeySize; j++)

+        key.Key[j] = cached.Key[j];

+      if (i != 0)

+        Keys.MoveToFront(i);

+      return true;

+    }

+  }

+  return false;

+}

+

+void CKeyInfoCache::Add(CKeyInfo &key)

+{

+  if (Find(key))

+    return;

+  if (Keys.Size() >= Size)

+    Keys.DeleteBack();

+  Keys.Insert(0, key);

+}

+

+static CKeyInfoCache g_GlobalKeyCache(32);

+static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;

+

+CBase::CBase():

+  _cachedKeys(16),

+  _ivSize(0)

+{

+  for (int i = 0; i < sizeof(_iv); i++)

+    _iv[i] = 0;

+}

+

+void CBase::CalculateDigest()

+{

+  NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);

+  if (_cachedKeys.Find(_key))

+    g_GlobalKeyCache.Add(_key);

+  else

+  {

+    if (!g_GlobalKeyCache.Find(_key))

+    {

+      _key.CalculateDigest();

+      g_GlobalKeyCache.Add(_key);

+    }

+    _cachedKeys.Add(_key);

+  }

+}

+

+#ifndef EXTRACT_ONLY

+

+/*

+STDMETHODIMP CEncoder::ResetSalt()

+{

+  _key.SaltSize = 4;

+  g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);

+  return S_OK;

+}

+*/

+

+STDMETHODIMP CEncoder::ResetInitVector()

+{

+  _ivSize = 8;

+  g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);

+  return S_OK;

+}

+

+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+   // _key.Init();

+   for (UInt32 i = _ivSize; i < sizeof(_iv); i++)

+    _iv[i] = 0;

+

+  UInt32 ivSize = _ivSize;

+  

+  // _key.NumCyclesPower = 0x3F;

+  _key.NumCyclesPower = 19;

+

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

+  {

+    RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize));

+  }

+  if (ivSize > 0)

+  {

+    RINOK(WriteStream(outStream, _iv, ivSize));

+  }

+  return S_OK;

+}

+

+HRESULT CEncoder::CreateFilter()

+{

+  _aesFilter = new CAesCbcEncoder(kKeySize);

+  return S_OK;

+}

+

+#endif

+

+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)

+{

+  _key.Init();

+  UInt32 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)

+    return E_INVALIDARG;

+  for (i = 0; i < _key.SaltSize; i++)

+    _key.Salt[i] = data[pos++];

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

+    _iv[i] = data[pos++];

+  return (_key.NumCyclesPower <= 24) ? S_OK :  E_NOTIMPL;

+}

+

+STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)

+{

+  _key.Password.CopyFrom(data, (size_t)size);

+  return S_OK;

+}

+

+STDMETHODIMP CBaseCoder::Init()

+{

+  CalculateDigest();

+  if (_aesFilter == 0)

+  {

+    RINOK(CreateFilter());

+  }

+  CMyComPtr<ICryptoProperties> cp;

+  RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));

+  RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));

+  RINOK(cp->SetInitVector(_iv, sizeof(_iv)));

+  return _aesFilter->Init();

+}

+

+STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)

+{

+  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
new file mode 100644
index 0000000..baa1258
--- /dev/null
+++ b/CPP/7zip/Crypto/7zAes.h
@@ -0,0 +1,117 @@
+// 7zAes.h

+

+#ifndef __CRYPTO_7Z_AES_H

+#define __CRYPTO_7Z_AES_H

+

+#include "../../Common/MyBuffer.h"

+#include "../../Common/MyCom.h"

+#include "../../Common/MyVector.h"

+

+#include "../ICoder.h"

+#include "../IPassword.h"

+

+namespace NCrypto {

+namespace NSevenZ {

+

+const int kKeySize = 32;

+

+class CKeyInfo

+{

+public:

+  int NumCyclesPower;

+  UInt32 SaltSize;

+  Byte Salt[16];

+  CByteBuffer Password;

+  Byte Key[kKeySize];

+

+  bool IsEqualTo(const CKeyInfo &a) const;

+  void CalculateDigest();

+

+  CKeyInfo() { Init(); }

+  void Init()

+  {

+    NumCyclesPower = 0;

+    SaltSize = 0;

+    for (int i = 0; i < sizeof(Salt); i++)

+      Salt[i] = 0;

+  }

+};

+

+class CKeyInfoCache

+{

+  unsigned Size;

+  CObjectVector<CKeyInfo> Keys;

+public:

+  CKeyInfoCache(unsigned size): Size(size) {}

+  bool Find(CKeyInfo &key);

+  // HRESULT Calculate(CKeyInfo &key);

+  void Add(CKeyInfo &key);

+};

+

+class CBase

+{

+  CKeyInfoCache _cachedKeys;

+protected:

+  CKeyInfo _key;

+  Byte _iv[16];

+  UInt32 _ivSize;

+  void CalculateDigest();

+  CBase();

+};

+

+class CBaseCoder:

+  public ICompressFilter,

+  public ICryptoSetPassword,

+  public CMyUnknownImp,

+  public CBase

+{

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

+  

+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);

+};

+

+#ifndef EXTRACT_ONLY

+

+class CEncoder:

+  public CBaseCoder,

+  public ICompressWriteCoderProperties,

+  // public ICryptoResetSalt,

+  public ICryptoResetInitVector

+{

+  virtual HRESULT CreateFilter();

+public:

+  MY_UNKNOWN_IMP3(

+      ICryptoSetPassword,

+      ICompressWriteCoderProperties,

+      // ICryptoResetSalt,

+      ICryptoResetInitVector)

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+  // STDMETHOD(ResetSalt)();

+  STDMETHOD(ResetInitVector)();

+};

+#endif

+

+class CDecoder:

+  public CBaseCoder,

+  public ICompressSetDecoderProperties2

+{

+  virtual HRESULT CreateFilter();

+public:

+  MY_UNKNOWN_IMP2(

+      ICryptoSetPassword,

+      ICompressSetDecoderProperties2)

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp
new file mode 100644
index 0000000..87f8ae9
--- /dev/null
+++ b/CPP/7zip/Crypto/7zAesRegister.cpp
@@ -0,0 +1,18 @@
+// 7zAesRegister.cpp

+

+#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

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true };

+

+REGISTER_CODEC(7zAES)

diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp
new file mode 100644
index 0000000..1d399d7
--- /dev/null
+++ b/CPP/7zip/Crypto/MyAes.cpp
@@ -0,0 +1,112 @@
+// Crypto/MyAes.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/CpuArch.h"

+

+#include "MyAes.h"

+

+namespace NCrypto {

+

+static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;

+

+CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize):

+  _keySize(keySize),

+  _keyIsSet(false),

+  _encodeMode(encodeMode)

+{

+  _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);

+  memset(_iv, 0, AES_BLOCK_SIZE);

+  SetFunctions(0);

+}

+

+STDMETHODIMP CAesCbcCoder::Init()

+{

+  AesCbc_Init(_aes + _offset, _iv);

+  return _keyIsSet ? S_OK : E_FAIL;

+}

+

+STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size)

+{

+  if (!_keyIsSet)

+    return 0;

+  if (size == 0)

+    return 0;

+  if (size < AES_BLOCK_SIZE)

+    return AES_BLOCK_SIZE;

+  size >>= 4;

+  _codeFunc(_aes + _offset, data, size);

+  return size << 4;

+}

+

+STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size)

+{

+  if ((size & 0x7) != 0 || size < 16 || size > 32)

+    return E_INVALIDARG;

+  if (_keySize != 0 && size != _keySize)

+    return E_INVALIDARG;

+  AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec;

+  setKeyFunc(_aes + _offset + 4, data, size);

+  _keyIsSet = true;

+  return S_OK;

+}

+

+STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size)

+{

+  if (size != AES_BLOCK_SIZE)

+    return E_INVALIDARG;

+  memcpy(_iv, data, size);

+  CAesCbcCoder::Init(); // don't call virtual function here !!!

+  return S_OK;

+}

+

+EXTERN_C_BEGIN

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+EXTERN_C_END

+

+bool CAesCbcCoder::SetFunctions(UInt32 algo)

+{

+  _codeFunc = _encodeMode ?

+      g_AesCbc_Encode :

+      g_AesCbc_Decode;

+  if (algo == 1)

+  {

+    _codeFunc = _encodeMode ?

+        AesCbc_Encode:

+        AesCbc_Decode;

+  }

+  if (algo == 2)

+  {

+    #ifdef MY_CPU_X86_OR_AMD64

+    if (g_AesCbc_Encode != AesCbc_Encode_Intel)

+    #endif

+      return false;

+  }

+  return true;

+}

+

+STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)

+{

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = coderProps[i];

+    if (propIDs[i] == NCoderPropID::kDefaultProp)

+    {

+      if (prop.vt != VT_UI4)

+        return E_INVALIDARG;

+      if (!SetFunctions(prop.ulVal))

+        return E_NOTIMPL;

+    }

+  }

+  return S_OK;

+}

+

+}

diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
new file mode 100644
index 0000000..71f3fa7
--- /dev/null
+++ b/CPP/7zip/Crypto/MyAes.h
@@ -0,0 +1,52 @@
+// Crypto/MyAes.h

+

+#ifndef __CRYPTO_MY_AES_H

+#define __CRYPTO_MY_AES_H

+

+#include "../../../C/Aes.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+namespace NCrypto {

+

+class CAesCbcCoder:

+  public ICompressFilter,

+  public ICryptoProperties,

+  public ICompressSetCoderProperties,

+  public CMyUnknownImp

+{

+  AES_CODE_FUNC _codeFunc;

+  unsigned _offset;

+  unsigned _keySize;

+  bool _keyIsSet;

+  bool _encodeMode;

+  UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];

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

+  STDMETHOD(SetKey)(const Byte *data, UInt32 size);

+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

+};

+

+struct CAesCbcEncoder: public CAesCbcCoder

+{

+  CAesCbcEncoder(unsigned keySize = 0): CAesCbcCoder(true, keySize) {}

+};

+

+struct CAesCbcDecoder: public CAesCbcCoder

+{

+  CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {}

+};

+

+

+}

+

+#endif

diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp
new file mode 100644
index 0000000..2815b1d
--- /dev/null
+++ b/CPP/7zip/Crypto/MyAesReg.cpp
@@ -0,0 +1,19 @@
+// MyAesReg.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#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

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodecCbc, CreateCodecCbcOut, 0x06F00181, L"AES256CBC", 1, true };

+REGISTER_CODEC(AES256CBC)

+

diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp
new file mode 100644
index 0000000..983662a
--- /dev/null
+++ b/CPP/7zip/Crypto/RandGen.cpp
@@ -0,0 +1,115 @@
+// RandGen.cpp

+

+#include "StdAfx.h"

+

+#include "../../Windows/Synchronization.h"

+

+#include "RandGen.h"

+

+#ifndef _WIN32

+#include <unistd.h>

+#define USE_POSIX_TIME

+#define USE_POSIX_TIME2

+#endif

+

+#ifdef USE_POSIX_TIME

+#include <time.h>

+#ifdef USE_POSIX_TIME2

+#include <sys/time.h>

+#endif

+#endif

+

+// This is not very good random number generator.

+// Please use it only for salt.

+// First generated data block depends from timer and processID.

+// Other generated data blocks depend from previous state

+// Maybe it's possible to restore original timer value from generated value.

+

+#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));

+

+void CRandomGenerator::Init()

+{

+  CSha256 hash;

+  Sha256_Init(&hash);

+

+  #ifdef _WIN32

+  DWORD w = ::GetCurrentProcessId();

+  HASH_UPD(w);

+  w = ::GetCurrentThreadId();

+  HASH_UPD(w);

+  #else

+  pid_t pid = getpid();

+  HASH_UPD(pid);

+  pid = getppid();

+  HASH_UPD(pid);

+  #endif

+

+  for (unsigned i = 0; i <

+    #ifdef _DEBUG

+    2;

+    #else

+    1000;

+    #endif

+    i++)

+  {

+    #ifdef _WIN32

+    LARGE_INTEGER v;

+    if (::QueryPerformanceCounter(&v))

+      HASH_UPD(v.QuadPart);

+    #endif

+

+    #ifdef USE_POSIX_TIME

+    #ifdef USE_POSIX_TIME2

+    timeval v;

+    if (gettimeofday(&v, 0) == 0)

+    {

+      HASH_UPD(v.tv_sec);

+      HASH_UPD(v.tv_usec);

+    }

+    #endif

+    time_t v2 = time(NULL);

+    HASH_UPD(v2);

+    #endif

+

+    DWORD tickCount = ::GetTickCount();

+    HASH_UPD(tickCount);

+    

+    for (unsigned j = 0; j < 100; j++)

+    {

+      Sha256_Final(&hash, _buff);

+      Sha256_Init(&hash);

+      Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);

+    }

+  }

+  Sha256_Final(&hash, _buff);

+  _needInit = false;

+}

+

+static NWindows::NSynchronization::CCriticalSection g_CriticalSection;

+

+void CRandomGenerator::Generate(Byte *data, unsigned size)

+{

+  g_CriticalSection.Enter();

+  if (_needInit)

+    Init();

+  while (size > 0)

+  {

+    CSha256 hash;

+    

+    Sha256_Init(&hash);

+    Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);

+    Sha256_Final(&hash, _buff);

+    

+    Sha256_Init(&hash);

+    UInt32 salt = 0xF672ABD1;

+    HASH_UPD(salt);

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

+      *data++ = buff[i];

+  }

+  g_CriticalSection.Leave();

+}

+

+CRandomGenerator g_RandomGenerator;

diff --git a/CPP/7zip/Crypto/RandGen.h b/CPP/7zip/Crypto/RandGen.h
new file mode 100644
index 0000000..ff44450
--- /dev/null
+++ b/CPP/7zip/Crypto/RandGen.h
@@ -0,0 +1,21 @@
+// RandGen.h

+

+#ifndef __CRYPTO_RAND_GEN_H

+#define __CRYPTO_RAND_GEN_H

+

+#include "../../../C/Sha256.h"

+

+class CRandomGenerator

+{

+  Byte _buff[SHA256_DIGEST_SIZE];

+  bool _needInit;

+

+  void Init();

+public:

+  CRandomGenerator(): _needInit(true) {};

+  void Generate(Byte *data, unsigned size);

+};

+

+extern CRandomGenerator g_RandomGenerator;

+

+#endif

diff --git a/CPP/7zip/Crypto/StdAfx.h b/CPP/7zip/Crypto/StdAfx.h
new file mode 100644
index 0000000..42a088f
--- /dev/null
+++ b/CPP/7zip/Crypto/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../Common/Common.h"

+

+#endif

diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc
new file mode 100644
index 0000000..c11017b
--- /dev/null
+++ b/CPP/7zip/GuiCommon.rc
@@ -0,0 +1,81 @@
+#include <windows.h>

+

+// #include <winnt.h>

+// #include <WinUser.h>

+

+// for Windows CE:

+#include <CommCtrl.h>

+

+

+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

+

+#undef m

+#undef bxs

+#undef bys

+#undef bxsDots

+#undef y

+#undef xc

+#undef yc

+#undef xs

+#undef ys

+#undef bx

+#undef bx1

+#undef bx2

+#undef bx3

+#undef by

+#undef by1

+#undef by2

+#undef by3

+#undef gSpace

+#undef gSize

+#undef marg2

+#undef marg3

+

+#undef MY_DIALOG

+#undef MY_RESIZE_DIALOG

+#undef MY_PAGE

+

+#define m 8

+#define bxs 64

+#define bys 16

+#define bxsDots 20

+

+#define xs (xc + m + m)

+#define ys (yc + m + m)

+

+#define bx1 (xs - m - bxs)

+#define bx2 (bx1 - m - bxs)

+#define bx3 (bx2 - m - bxs)

+#define bx bx1

+

+#define by1 (ys - m - bys)

+#define by2 (by1 - m - bys)

+#define by by1

+

+

+#define MY_MODAL_DIALOG_STYLE  STYLE  DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU

+

+#define MY_MODAL_RESIZE_DIALOG_STYLE  MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME

+

+#define MY_PAGE_STYLE  STYLE  WS_CHILD | WS_DISABLED | WS_CAPTION

+

+#define MY_FONT  FONT 8, "MS Shell Dlg"

+

+#define SMALL_PAGE_SIZE_X 120

+

+// #define MY_DIALOG         DIALOG 0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+// #define MY_RESIZE_DIALOG  DIALOG 0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT

+#define MY_PAGE           DIALOG 0, 0, xs, ys  MY_PAGE_STYLE  MY_FONT

+

+#define OK_CANCEL \

+  DEFPUSHBUTTON  "OK",     IDOK,     bx2, by, bxs, bys \

+  PUSHBUTTON     "Cancel", IDCANCEL, bx1, by, bxs, bys

+

+

+#define MY_COMBO  CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP

+#define MY_COMBO_SORTED  MY_COMBO | CBS_SORT

+#define MY_COMBO_WITH_EDIT  CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP 

+

+#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP

+

+#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX

diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
old mode 100755
new mode 100644
index cbd45a4..2b01644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -6,14 +6,17 @@
 

 01 IFolderArchive.h

 

-  05  IArchiveFolder

+  // 05  IArchiveFolder   // old 

   // 06  IInFolderArchive // old

   07  IFileExtractCallback.h::IFolderArchiveExtractCallback

-  0A  IOutFolderArchive

+  // 0A  IOutFolderArchive

   0B  IFolderArchiveUpdateCallback

   0C  Agent.h::IArchiveFolderInternal

-  0D

+  0D  IArchiveFolder

   0E  IInFolderArchive

+  0F  IOutFolderArchive

+  20  IFileExtractCallback.h::IGetProp

+  30  IFileExtractCallback.h::IFolderExtractToStreamCallback

 

 03 IStream.h

 

@@ -23,6 +26,8 @@
   04  IOutStream

   06  IStreamGetSize

   07  IOutStreamFlush

+  08  IStreamGetProps

+  09  IStreamGetProps2

 

 

 04 ICoder.h

@@ -50,6 +55,8 @@
   8C  ICryptoResetInitVector

   90  ICryptoSetPassword

   A0  ICryptoSetCRC

+  C0  IHasher

+  C1  IHashers

 

 

 05 IPassword.h

@@ -61,6 +68,8 @@
 06 IArchive.h

 

   03  ISetProperties

+  04  IArchiveKeepModeForNextOpen

+  05  IArchiveAllowTail

 

   10  IArchiveOpenCallback

   20  IArchiveExtractCallback

@@ -69,6 +78,8 @@
   50  IArchiveOpenSetSubArchiveName

   60  IInArchive

   61  IArchiveOpenSeq

+  70  IArchiveGetRawProps

+  71  IArchiveGetRootProps

 

   80  IArchiveUpdateCallback

   82  IArchiveUpdateCallback2

@@ -84,7 +95,7 @@
   03 IFolderGetPath

   04 IFolderWasChanged

   05 // IFolderReload

-  06 IFolderOperations

+  06 // IFolderOperations old

   07 IFolderGetSystemIconIndex

   08 IFolderGetItemFullSize

   09 IFolderClone

@@ -96,6 +107,11 @@
   0F 

   10 IFolderArcProps

   11 IGetFolderArcProps

+  12 // IFolderOperations

+  13 IFolderOperations

+  14 IFolderCalcItemFullSize

+  15 IFolderCompare

+  16 IFolderGetItemName

 

 

 09 IFolder.h :: FOLDER_MANAGER_INTERFACE

@@ -128,6 +144,11 @@
   0C xz

   0D ppmd

 

+  CD IHex

+  CE Hxs

+  CF TE

+  D0 UEFIc

+  D1 UEFIs

   D2 SquashFS

   D3 CramFS

   D4 APM

@@ -150,7 +171,7 @@
   E5 Compound

   E6 Wim

   E7 Iso

-  E8 Bkf

+  E8 

   E9 Chm

   EA Split

   EB Rpm

@@ -168,3 +189,4 @@
 

 {23170F69-40C1-2790-id} Codec Decoders

 {23170F69-40C1-2791-id} Codec Encoders

+{23170F69-40C1-2792-id} Hashers

diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
old mode 100755
new mode 100644
index cb74f98..9153adc
--- a/CPP/7zip/ICoder.h
+++ b/CPP/7zip/ICoder.h
@@ -44,7 +44,9 @@
     kNumPasses,

     kAlgorithm,

     kNumThreads,

-    kEndMarker

+    kEndMarker,

+    kLevel,

+    kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size.

   };

 }

 

@@ -179,8 +181,31 @@
     kOutStreams,

     kDescription,

     kDecoderIsAssigned,

-    kEncoderIsAssigned

+    kEncoderIsAssigned,

+    kDigestSize

   };

 }

 

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

+};

+

+CODER_INTERFACE(IHashers, 0xC1)

+{

+  STDMETHOD_(UInt32, GetNumHashers)() PURE;

+  STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;

+  STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE;

+};

+

+extern "C"

+{

+  typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);

+  typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);

+}

+

 #endif

diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h
old mode 100755
new mode 100644
index 5679d84..e366007
--- a/CPP/7zip/IPassword.h
+++ b/CPP/7zip/IPassword.h
@@ -3,8 +3,8 @@
 #ifndef __IPASSWORD_H

 #define __IPASSWORD_H

 

+#include "../Common/MyTypes.h"

 #include "../Common/MyUnknown.h"

-#include "../Common/Types.h"

 

 #include "IDecl.h"

 

@@ -21,4 +21,3 @@
 };

 

 #endif

-

diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
old mode 100755
new mode 100644
index 09486ba..b98f480
--- a/CPP/7zip/IProgress.h
+++ b/CPP/7zip/IProgress.h
@@ -3,8 +3,8 @@
 #ifndef __IPROGRESS_H

 #define __IPROGRESS_H

 

+#include "../Common/MyTypes.h"

 #include "../Common/MyUnknown.h"

-#include "../Common/Types.h"

 

 #include "IDecl.h"

 

diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
old mode 100755
new mode 100644
index 89f02f5..d347def
--- a/CPP/7zip/IStream.h
+++ b/CPP/7zip/IStream.h
@@ -3,8 +3,8 @@
 #ifndef __ISTREAM_H

 #define __ISTREAM_H

 

+#include "../Common/MyTypes.h"

 #include "../Common/MyUnknown.h"

-#include "../Common/Types.h"

 

 #include "IDecl.h"

 

@@ -14,26 +14,71 @@
 STREAM_INTERFACE(ISequentialInStream, 0x01)

 {

   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;

+  

   /*

-  Out: if size != 0, return_value = S_OK and (*processedSize == 0),

-    then there are no more bytes in stream.

-  if (size > 0) && there are bytes in stream,

-  this function must read at least 1 byte.

-  This function is allowed to read less than number of remaining bytes in stream.

-  You must call Read function in loop, if you need exact amount of data

+  The requirement for caller: (processedSize != NULL).

+  The callee can allow (processedSize == NULL) for compatibility reasons.

+    

+  if (size == 0), this function returns S_OK and (*processedSize) is set to 0.

+

+  if (size != 0)

+  {

+    Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size),

+      where (avail_size) is the size of remaining bytes in stream.

+    If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0).

+    You must call Read() in loop, if you need to read exact amount of data.

+  }

+

+  If seek pointer before Read() call was changed to position past the end of stream:

+    if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0.

+  

+  ERROR CASES:

+    If the function returns error code, then (*processedSize) is size of

+    data written to (data) buffer (it can be data before error or data with errors).

+    The recommended way for callee to work with reading errors:

+      1) write part of data before error to (data) buffer and return S_OK.

+      2) return error code for further calls of Read().

   */

 };

 

 STREAM_INTERFACE(ISequentialOutStream, 0x02)

 {

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;

+  

   /*

-  if (size > 0) this function must write at least 1 byte.

-  This function is allowed to write less than "size".

-  You must call Write function in loop, if you need to write exact amount of data

+  The requirement for caller: (processedSize != NULL).

+  The callee can allow (processedSize == NULL) for compatibility reasons.

+

+  if (size != 0)

+  {

+    Partial write is allowed: (*processedSize <= size),

+    but this function must write at least 1 byte: (*processedSize > 0).

+    You must call Write() in loop, if you need to write exact amount of data.

+  }

+

+  ERROR CASES:

+    If the function returns error code, then (*processedSize) is size of

+    data written from (data) buffer.

   */

 };

 

+#ifdef __HRESULT_FROM_WIN32

+#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)

+#else

+#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK   HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)

+#endif

+

+/*  Seek() Function

+  If you seek before the beginning of the stream, Seek() function returns error code:

+      Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK).

+      or STG_E_INVALIDFUNCTION

+      

+  It is allowed to seek past the end of the stream.

+

+

+  if Seek() returns error, then the value of *newPosition is undefined.

+*/

+

 STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)

 {

   STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

@@ -55,4 +100,28 @@
   STDMETHOD(Flush)() PURE;

 };

 

+

+STREAM_INTERFACE(IStreamGetProps, 0x08)

+{

+  STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) PURE;

+};

+

+struct CStreamFileProps

+{

+  UInt64 Size;

+  UInt64 VolID;

+  UInt64 FileID_Low;

+  UInt64 FileID_High;

+  UInt32 NumLinks;

+  UInt32 Attrib;

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+};

+

+STREAM_INTERFACE(IStreamGetProps2, 0x09)

+{

+  STDMETHOD(GetProps2)(CStreamFileProps *props) PURE;

+};

+

 #endif

diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
old mode 100755
new mode 100644
index f549249..06e6c58
--- a/CPP/7zip/MyVersion.h
+++ b/CPP/7zip/MyVersion.h
@@ -1,8 +1,6 @@
-#define MY_VER_MAJOR 9

-#define MY_VER_MINOR 20

-#define MY_VER_BUILD 0

-#define MY_VERSION "9.20"

-#define MY_7ZIP_VERSION "7-Zip 9.20"

-#define MY_DATE "2010-11-18"

-#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"

+#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

diff --git a/CPP/7zip/MyVersionInfo.rc b/CPP/7zip/MyVersionInfo.rc
old mode 100755
new mode 100644
index 84e4ac3..eddf893
--- a/CPP/7zip/MyVersionInfo.rc
+++ b/CPP/7zip/MyVersionInfo.rc
@@ -1,52 +1,2 @@
-#define MY_VS_FFI_FILEFLAGSMASK  0x0000003FL

-#define MY_VOS_NT_WINDOWS32  0x00040004L

-#define MY_VOS_CE_WINDOWS32  0x00050004L

-

-#define MY_VFT_APP  0x00000001L

-#define MY_VFT_DLL  0x00000002L

-

-// #include <WinVer.h>

 #include "MyVersion.h"

-

-#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0

-

-#ifdef DEBUG

-#define DBG_FL VS_FF_DEBUG

-#else

-#define DBG_FL 0

-#endif

-

-#define MY_VERSION_INFO(fileType, descr, intName, origName)  \

-LANGUAGE 9, 1 \

-1 VERSIONINFO \

-  FILEVERSION MY_VER \

-  PRODUCTVERSION MY_VER \

-  FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \

-  FILEFLAGS DBG_FL \

-  FILEOS MY_VOS_NT_WINDOWS32 \

-  FILETYPE fileType \

-  FILESUBTYPE 0x0L \

-BEGIN \

-    BLOCK "StringFileInfo" \

-    BEGIN  \

-        BLOCK "040904b0" \

-        BEGIN \

-            VALUE "CompanyName", "Igor Pavlov" \

-            VALUE "FileDescription", descr \

-            VALUE "FileVersion", MY_VERSION  \

-            VALUE "InternalName", intName \

-            VALUE "LegalCopyright", MY_COPYRIGHT \

-            VALUE "OriginalFilename", origName \

-            VALUE "ProductName", "7-Zip" \

-            VALUE "ProductVersion", MY_VERSION \

-        END \

-    END \

-    BLOCK "VarFileInfo" \

-    BEGIN \

-        VALUE "Translation", 0x409, 1200 \

-    END \

-END

-

-#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe")

-

-#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll")

+#include "..\..\C\7zVersion.rc"

diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
old mode 100755
new mode 100644
index 1aabc65..da2acd7
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -1,13 +1,15 @@
 // PropID.h

 

-#ifndef __7ZIP_PROPID_H

-#define __7ZIP_PROPID_H

+#ifndef __7ZIP_PROP_ID_H

+#define __7ZIP_PROP_ID_H

+

+#include "../Common/MyTypes.h"

 

 enum

 {

   kpidNoProperty = 0,

-  kpidMainSubfile = 1,

-  kpidHandlerItemIndex = 2,

+  kpidMainSubfile,

+  kpidHandlerItemIndex,

   kpidPath,

   kpidName,

   kpidExtension,

@@ -59,18 +61,64 @@
   kpidCreatorApp,

   kpidSectorSize,

   kpidPosixAttrib,

-  kpidLink,

+  kpidSymLink,

   kpidError,

-

-  kpidTotalSize = 0x1100,

+  kpidTotalSize,

   kpidFreeSpace,

   kpidClusterSize,

   kpidVolumeName,

-

-  kpidLocalName = 0x1200,

+  kpidLocalName,

   kpidProvider,

+  kpidNtSecure,

+  kpidIsAltStream,

+  kpidIsAux,

+  kpidIsDeleted,

+  kpidIsTree,

+  kpidSha1,

+  kpidSha256,

+  kpidErrorType,

+  kpidNumErrors,

+  kpidErrorFlags,

+  kpidWarningFlags,

+  kpidWarning,

+  kpidNumStreams,

+  kpidNumAltStreams,

+  kpidAltStreamsSize,

+  kpidVirtualSize,

+  kpidUnpackSize,

+  kpidTotalPhySize,

+  kpidVolumeIndex,

+  kpidSubType,

+  kpidShortComment,

+  kpidCodePage,

+  kpidIsNotArcType,

+  kpidPhySizeCantBeDetected,

+  kpidZerosTailIsAllowed,

+  kpidTailSize,

+  kpidEmbeddedStubSize,

+  kpidNtReparse,

+  kpidHardLink,

+  kpidINode,

+  kpidStreamId,

+

+  kpid_NUM_DEFINED,

 

   kpidUserDefined = 0x10000

 };

 

+extern Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE

+

+const UInt32 kpv_ErrorFlags_IsNotArc              = 1 << 0;

+const UInt32 kpv_ErrorFlags_HeadersError          = 1 << 1;

+const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2;

+const UInt32 kpv_ErrorFlags_UnavailableStart      = 1 << 3;

+const UInt32 kpv_ErrorFlags_UnconfirmedStart      = 1 << 4;

+const UInt32 kpv_ErrorFlags_UnexpectedEnd         = 1 << 5;

+const UInt32 kpv_ErrorFlags_DataAfterEnd          = 1 << 6;

+const UInt32 kpv_ErrorFlags_UnsupportedMethod     = 1 << 7;

+const UInt32 kpv_ErrorFlags_UnsupportedFeature    = 1 << 8;

+const UInt32 kpv_ErrorFlags_DataError             = 1 << 9;

+const UInt32 kpv_ErrorFlags_CrcError              = 1 << 10;

+// const UInt32 kpv_ErrorFlags_Unsupported           = 1 << 11;

+

 #endif

diff --git a/CPP/7zip/SubBuild.mak b/CPP/7zip/SubBuild.mak
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
old mode 100755
new mode 100644
index 7001fe8..011eb56
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -2,37 +2,48 @@
 

 #include "StdAfx.h"

 

-#include "Common/IntToString.h"

-#include "Common/MyInitGuid.h"

-#include "Common/StringConvert.h"

+#include <stdio.h>

 

-#include "Windows/DLL.h"

-#include "Windows/FileDir.h"

-#include "Windows/FileFind.h"

-#include "Windows/FileName.h"

-#include "Windows/NtCheck.h"

-#include "Windows/PropVariant.h"

-#include "Windows/PropVariantConversions.h"

+#include "../../../Common/Defs.h"

+#include "../../../Common/MyInitGuid.h"

+

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/DLL.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/NtCheck.h"

+#include "../../../Windows/PropVariant.h"

+#include "../../../Windows/PropVariantConv.h"

 

 #include "../../Common/FileStreams.h"

 

 #include "../../Archive/IArchive.h"

 

 #include "../../IPassword.h"

-#include "../../MyVersion.h"

+#include "../../../../C/7zVersion.h"

 

+#ifdef _WIN32

+HINSTANCE g_hInstance = 0;

+#endif

+

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

 

 using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

 

 #define kDllName "7z.dll"

 

-static const char *kCopyrightString = MY_7ZIP_VERSION

+static const char *kCopyrightString = "\n7-Zip " MY_VERSION

 " ("  kDllName " client) "

-MY_COPYRIGHT " " MY_DATE;

+MY_COPYRIGHT " " MY_DATE "\n";

 

 static const char *kHelpString =

 "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"

@@ -42,34 +53,46 @@
 "  Client7z.exe x archive.7z   : eXtract files from archive.7z\n";

 

 

-typedef UINT32 (WINAPI * CreateObjectFunc)(

-    const GUID *clsID,

-    const GUID *interfaceID,

-    void **outObject);

+static AString FStringToConsoleString(const FString &s)

+{

+  return GetOemString(fs2us(s));

+}

 

+static FString CmdStringToFString(const char *s)

+{

+  return us2fs(GetUnicodeString(s));

+}

 

-void PrintString(const UString &s)

+static void PrintString(const UString &s)

 {

   printf("%s", (LPCSTR)GetOemString(s));

 }

 

-void PrintString(const AString &s)

+static void PrintString(const AString &s)

 {

   printf("%s", (LPCSTR)s);

 }

 

-void PrintNewLine()

+static void PrintNewLine()

 {

   PrintString("\n");

 }

 

-void PrintStringLn(const AString &s)

+static void PrintStringLn(const AString &s)

 {

   PrintString(s);

   PrintNewLine();

 }

 

-void PrintError(const AString &s)

+static void PrintError(const char *message, const FString &name)

+{

+  printf("Error: %s", (LPCSTR)message);

+  PrintNewLine();

+  PrintString(FStringToConsoleString(name));

+  PrintNewLine();

+}

+

+static void PrintError(const AString &s)

 {

   PrintNewLine();

   PrintString(s);

@@ -148,8 +171,6 @@
 //////////////////////////////////////////////////////////////

 // Archive Extracting callback class

 

-static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";

-

 static const char *kTestingString    =  "Testing     ";

 static const char *kExtractingString =  "Extracting  ";

 static const char *kSkippingString   =  "Skipping    ";

@@ -157,7 +178,11 @@
 static const char *kUnsupportedMethod = "Unsupported Method";

 static const char *kCRCFailed = "CRC Failed";

 static const char *kDataError = "Data Error";

-static const char *kUnknownError = "Unknown Error";

+static const char *kUnavailableData = "Unavailable data";

+static const char *kUnexpectedEnd = "Unexpected end of data";

+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";

 

 class CArchiveExtractCallback:

   public IArchiveExtractCallback,

@@ -181,9 +206,9 @@
 

 private:

   CMyComPtr<IInArchive> _archiveHandler;

-  UString _directoryPath;  // Output directory

+  FString _directoryPath;  // Output directory

   UString _filePath;       // name inside arcvhive

-  UString _diskFilePath;   // full path to file on disk

+  FString _diskFilePath;   // full path to file on disk

   bool _extractMode;

   struct CProcessedFileInfo

   {

@@ -198,7 +223,7 @@
   CMyComPtr<ISequentialOutStream> _outFileStream;

 

 public:

-  void Init(IInArchive *archiveHandler, const UString &directoryPath);

+  void Init(IInArchive *archiveHandler, const FString &directoryPath);

 

   UInt64 NumErrors;

   bool PasswordIsDefined;

@@ -207,12 +232,12 @@
   CArchiveExtractCallback() : PasswordIsDefined(false) {}

 };

 

-void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)

+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath)

 {

   NumErrors = 0;

   _archiveHandler = archiveHandler;

   _directoryPath = directoryPath;

-  NFile::NName::NormalizeDirPathPrefix(_directoryPath);

+  NName::NormalizeDirPathPrefix(_directoryPath);

 }

 

 STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)

@@ -294,10 +319,8 @@
     // Get Size

     NCOM::CPropVariant prop;

     RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));

-    bool newFileSizeDefined = (prop.vt != VT_EMPTY);

     UInt64 newFileSize;

-    if (newFileSizeDefined)

-      newFileSize = ConvertPropVariantToUInt64(prop);

+    /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize);

   }

 

   

@@ -305,24 +328,24 @@
     // Create folders for file

     int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);

     if (slashPos >= 0)

-      NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));

+      CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));

   }

 

-  UString fullProcessedPath = _directoryPath + _filePath;

+  FString fullProcessedPath = _directoryPath + us2fs(_filePath);

   _diskFilePath = fullProcessedPath;

 

   if (_processedFileInfo.isDir)

   {

-    NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);

+    CreateComplexDir(fullProcessedPath);

   }

   else

   {

-    NFile::NFind::CFileInfoW fi;

+    NFind::CFileInfo fi;

     if (fi.Find(fullProcessedPath))

     {

-      if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))

+      if (!DeleteFileAlways(fullProcessedPath))

       {

-        PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);

+        PrintError("Can not delete output file", fullProcessedPath);

         return E_ABORT;

       }

     }

@@ -331,7 +354,7 @@
     CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

     if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))

     {

-      PrintString((UString)L"can not open output file " + fullProcessedPath);

+      PrintError("Can not open output file", fullProcessedPath);

       return E_ABORT;

     }

     _outFileStream = outStreamLoc;

@@ -359,27 +382,53 @@
 

 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)

 {

-  switch(operationResult)

+  switch (operationResult)

   {

     case NArchive::NExtract::NOperationResult::kOK:

       break;

     default:

     {

       NumErrors++;

-      PrintString("     ");

-      switch(operationResult)

+      PrintString("  :  ");

+      const char *s = NULL;

+      switch (operationResult)

       {

-        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

-          PrintString(kUnsupportedMethod);

+        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

+          s = kUnsupportedMethod;

           break;

         case NArchive::NExtract::NOperationResult::kCRCError:

-          PrintString(kCRCFailed);

+          s = kCRCFailed;

           break;

         case NArchive::NExtract::NOperationResult::kDataError:

-          PrintString(kDataError);

+          s = kDataError;

           break;

-        default:

-          PrintString(kUnknownError);

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

+      {

+        PrintString("Error : ");

+        PrintString(s);

+      }

+      else

+      {

+        char temp[16];

+        ConvertUInt32ToString(operationResult, temp);

+        PrintString("Error #");

+        PrintString(temp);

       }

     }

   }

@@ -392,7 +441,7 @@
   }

   _outFileStream.Release();

   if (_extractMode && _processedFileInfo.AttribDefined)

-    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib);

+    SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib);

   PrintNewLine();

   return S_OK;

 }

@@ -423,7 +472,7 @@
   FILETIME ATime;

   FILETIME MTime;

   UString Name;

-  UString FullPath;

+  FString FullPath;

   UInt32 Attrib;

 

   bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }

@@ -458,7 +507,7 @@
   UString VolName;

   UString VolExt;

 

-  UString DirPrefix;

+  FString DirPrefix;

   const CObjectVector<CDirItem> *DirItems;

 

   bool PasswordIsDefined;

@@ -467,7 +516,7 @@
 

   bool m_NeedBeClosed;

 

-  UStringVector FailedFiles;

+  FStringVector FailedFiles;

   CRecordVector<HRESULT> FailedCodes;

 

   CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};

@@ -508,13 +557,13 @@
   if (newProperties != NULL)

     *newProperties = BoolToInt(true);

   if (indexInArchive != NULL)

-    *indexInArchive = (UInt32)-1;

+    *indexInArchive = (UInt32)(Int32)-1;

   return S_OK;

 }

 

 STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

 {

-  NWindows::NCOM::CPropVariant prop;

+  NCOM::CPropVariant prop;

   

   if (propID == kpidIsAnti)

   {

@@ -571,7 +620,7 @@
   {

     CInFileStream *inStreamSpec = new CInFileStream;

     CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

-    UString path = DirPrefix + dirItem.FullPath;

+    FString path = DirPrefix + dirItem.FullPath;

     if (!inStreamSpec->Open(path))

     {

       DWORD sysError = ::GetLastError();

@@ -612,7 +661,7 @@
   wchar_t temp[16];

   ConvertUInt32ToString(index + 1, temp);

   UString res = temp;

-  while (res.Length() < 2)

+  while (res.Len() < 2)

     res = UString(L'0') + res;

   UString fileName = VolName;

   fileName += L'.';

@@ -620,7 +669,7 @@
   fileName += VolExt;

   COutFileStream *streamSpec = new COutFileStream;

   CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);

-  if (!streamSpec->Create(fileName, false))

+  if (!streamSpec->Create(us2fs(fileName), false))

     return ::GetLastError();

   *volumeStream = streamLoc.Detach();

   return S_OK;

@@ -643,8 +692,6 @@
   return StringToBstr(Password, password);

 }

 

-

-

 //////////////////////////////////////////////////////////////////////////

 // Main function

 

@@ -661,14 +708,14 @@
     PrintStringLn(kHelpString);

     return 1;

   }

-  NWindows::NDLL::CLibrary lib;

-  if (!lib.Load(TEXT(kDllName)))

+  NDLL::CLibrary lib;

+  if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName)))

   {

     PrintError("Can not load 7-zip library");

     return 1;

   }

-  CreateObjectFunc createObjectFunc = (CreateObjectFunc)lib.GetProc("CreateObject");

-  if (createObjectFunc == 0)

+  Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject");

+  if (!createObjectFunc)

   {

     PrintError("Can not get CreateObject");

     return 1;

@@ -677,14 +724,14 @@
   char c;

   {

     AString command = args[1];

-    if (command.Length() != 1)

+    if (command.Len() != 1)

     {

       PrintError("incorrect command");

       return 1;

     }

-    c = MyCharLower(command[0]);

+    c = (char)MyCharLower_Ascii(command[0]);

   }

-  UString archiveName = GetUnicodeString(args[2]);

+  FString archiveName = CmdStringToFString(args[2]);

   if (c == 'a')

   {

     // create archive command

@@ -694,27 +741,29 @@
       return 1;

     }

     CObjectVector<CDirItem> dirItems;

-    int i;

-    for (i = 3; i < numArgs; i++)

     {

-      CDirItem di;

-      UString name = GetUnicodeString(args[i]);

-      

-      NFile::NFind::CFileInfoW fi;

-      if (!fi.Find(name))

+      int i;

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

       {

-        PrintString(UString(L"Can't find file") + name);

-        return 1;

+        CDirItem di;

+        FString name = CmdStringToFString(args[i]);

+        

+        NFind::CFileInfo fi;

+        if (!fi.Find(name))

+        {

+          PrintError("Can't find file", name);

+          return 1;

+        }

+        

+        di.Attrib = fi.Attrib;

+        di.Size = fi.Size;

+        di.CTime = fi.CTime;

+        di.ATime = fi.ATime;

+        di.MTime = fi.MTime;

+        di.Name = fs2us(name);

+        di.FullPath = name;

+        dirItems.Add(di);

       }

-

-      di.Attrib = fi.Attrib;

-      di.Size = fi.Size;

-      di.CTime = fi.CTime;

-      di.ATime = fi.ATime;

-      di.MTime = fi.MTime;

-      di.Name = name;

-      di.FullPath = name;

-      dirItems.Add(di);

     }

     COutFileStream *outFileStreamSpec = new COutFileStream;

     CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;

@@ -744,8 +793,8 @@
         L"s",

         L"x"

       };

-      const int kNumProps = sizeof(names) / sizeof(names[0]);

-      NWindows::NCOM::CPropVariant values[kNumProps] =

+      const unsigned kNumProps = ARRAY_SIZE(names);

+      NCOM::CPropVariant values[kNumProps] =

       {

         false,    // solid mode OFF

         (UInt32)9 // compression level = 9 - ultra

@@ -768,10 +817,10 @@
       PrintError("Update Error");

       return 1;

     }

-    for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)

+    FOR_VECTOR (i, updateCallbackSpec->FailedFiles)

     {

       PrintNewLine();

-      PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);

+      PrintError("Error for file", updateCallbackSpec->FailedFiles[i]);

     }

     if (updateCallbackSpec->FailedFiles.Size() != 0)

       return 1;

@@ -807,7 +856,7 @@
     

     if (!fileSpec->Open(archiveName))

     {

-      PrintError("Can not open archive file");

+      PrintError("Can not open archive file", archiveName);

       return 1;

     }

 

@@ -820,7 +869,7 @@
       

       if (archive->Open(file, 0, openCallback) != S_OK)

       {

-        PrintError("Can not open archive");

+        PrintError("Can not open file as archive", archiveName);

         return 1;

       }

     }

@@ -834,20 +883,23 @@
       {

         {

           // Get uncompressed size of file

-          NWindows::NCOM::CPropVariant prop;

+          NCOM::CPropVariant prop;

           archive->GetProperty(i, kpidSize, &prop);

-          UString s = ConvertPropVariantToString(prop);

+          char s[32];

+          ConvertPropVariantToShortString(prop, s);

           PrintString(s);

           PrintString("  ");

         }

         {

           // Get name of file

-          NWindows::NCOM::CPropVariant prop;

+          NCOM::CPropVariant prop;

           archive->GetProperty(i, kpidPath, &prop);

-          UString s = ConvertPropVariantToString(prop);

-          PrintString(s);

+          if (prop.vt == VT_BSTR)

+            PrintString(prop.bstrVal);

+          else if (prop.vt != VT_EMPTY)

+            PrintString("ERROR!");

         }

-        PrintString("\n");

+        PrintNewLine();

       }

     }

     else

@@ -855,7 +907,7 @@
       // Extract command

       CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;

       CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);

-      extractCallbackSpec->Init(archive, L""); // second parameter is output folder path

+      extractCallbackSpec->Init(archive, FTEXT("")); // second parameter is output folder path

       extractCallbackSpec->PasswordIsDefined = false;

       // extractCallbackSpec->PasswordIsDefined = true;

       // extractCallbackSpec->Password = L"1";

diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
old mode 100755
new mode 100644
index 34eb42b..4a4711c
--- a/CPP/7zip/UI/Client7z/Client7z.dsp
+++ b/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -39,9 +39,10 @@
 # PROP Use_Debug_Libraries 0

 # PROP Output_Dir "Release"

 # PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

 # PROP Target_Dir ""

 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c

-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c

+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c

 # ADD BASE RSC /l 0x419 /d "NDEBUG"

 # ADD RSC /l 0x419 /d "NDEBUG"

 BSC32=bscmake.exe

@@ -49,7 +50,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe"

 

 !ELSEIF  "$(CFG)" == "Client7z - Win32 Debug"

 

@@ -65,7 +66,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" /Yu"stdafx.h" /FD /GZ /c

-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c

+# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c

 # ADD BASE RSC /l 0x419 /d "_DEBUG"

 # ADD RSC /l 0x419 /d "_DEBUG"

 BSC32=bscmake.exe

@@ -73,7 +74,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept

 

 !ENDIF 

 

@@ -86,6 +87,10 @@
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

 # Begin Source File

 

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

 SOURCE=.\StdAfx.cpp

 # ADD CPP /Yc"stdafx.h"

 # End Source File

@@ -147,11 +152,11 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\PropVariantConversions.cpp

+SOURCE=..\..\..\Windows\PropVariantConv.cpp

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\..\Windows\PropVariantConversions.h

+SOURCE=..\..\..\Windows\PropVariantConv.h

 # End Source File

 # End Group

 # Begin Group "Common"

@@ -222,5 +227,9 @@
 

 SOURCE=.\Client7z.cpp

 # End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sort.h

+# End Source File

 # End Target

 # End Project

diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h
old mode 100755
new mode 100644
index 2edddf4..59d9ac1
--- a/CPP/7zip/UI/Client7z/StdAfx.h
+++ b/CPP/7zip/UI/Client7z/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include <windows.h>

-#include <stdio.h>

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
old mode 100755
new mode 100644
index e3a8239..9f68f16
--- a/CPP/7zip/UI/Client7z/makefile
+++ b/CPP/7zip/UI/Client7z/makefile
@@ -1,8 +1,7 @@
-PROG = 7z.exe

+PROG = 7zcl.exe

 MY_CONSOLE = 1

-CFLAGS = $(CFLAGS) -I ../../../

 

-CONSOLE_OBJS = \

+CURRENT_OBJS = \

   $O\Client7z.obj \

 

 COMMON_OBJS = \

@@ -21,25 +20,9 @@
   $O\FileIO.obj \

   $O\FileName.obj \

   $O\PropVariant.obj \

-  $O\PropVariantConversions.obj \

+  $O\PropVariantConv.obj \

 

 7ZIP_COMMON_OBJS = \

   $O\FileStreams.obj \

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(CONSOLE_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-

-!include "../../../Build.mak"

-

-$(CONSOLE_OBJS): $(*B).cpp

-	$(COMPL)

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

+!include "../../7zip.mak"

diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc
new file mode 100644
index 0000000..97086e9
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/resource.rc
@@ -0,0 +1,3 @@
+#include "../../../../C/7zVersion.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
old mode 100755
new mode 100644
index 7fd012b..9e0eab0
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -1,6 +1,8 @@
 // ArchiveCommandLine.cpp

 

 #include "StdAfx.h"

+#undef printf

+#undef sprintf

 

 #ifdef _WIN32

 #ifndef UNDER_CE

@@ -9,15 +11,15 @@
 #endif

 #include <stdio.h>

 

-#include "Common/ListFileUtils.h"

-#include "Common/StringConvert.h"

-#include "Common/StringToInt.h"

+#include "../../../Common/ListFileUtils.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/StringToInt.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/FileName.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileName.h"

 #ifdef _WIN32

-#include "Windows/FileMapping.h"

-#include "Windows/Synchronization.h"

+#include "../../../Windows/FileMapping.h"

+#include "../../../Windows/Synchronization.h"

 #endif

 

 #include "ArchiveCommandLine.h"

@@ -48,6 +50,30 @@
 using namespace NWindows;

 using namespace NFile;

 

+static bool StringToUInt32(const wchar_t *s, UInt32 &v)

+{

+  if (*s == 0)

+    return false;

+  const wchar_t *end;

+  v = ConvertStringToUInt32(s, &end);

+  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) += u;

+  }

+}

+

 int g_CodePage = -1;

 

 namespace NKey {

@@ -86,19 +112,47 @@
   kTechMode,

   kShareForWrite,

   kCaseSensitive,

-  kCalcCrc

+  kHash,

+  kArcNameMode,

+

+  kDisableWildcardParsing,

+  kElimDup,

+  kFullPathMode,

+  

+  kHardLinks,

+  kSymLinks,

+  kNtSecurity,

+  kAltStreams,

+  kReplaceColonForAltStream,

+  kWriteToAltStreamIfColon,

+

+  kDeleteAfterCompressing,

+  kSetArcMTime,

+  kExcludedArcType

 };

 

 }

 

 

-static const wchar_t kRecursedIDChar = 'R';

-static const wchar_t *kRecursedPostCharSet = L"0-";

+static const wchar_t kRecursedIDChar = 'r';

+static const char *kRecursedPostCharSet = "0-";

+

+static const char *k_ArcNameMode_PostCharSet = "sea";

+

+static inline const EArcNameMode ParseArcNameMode(int postCharIndex)

+{

+  switch (postCharIndex)

+  {

+    case 1: return k_ArcNameMode_Exact;

+    case 2: return k_ArcNameMode_Add;

+    default: return k_ArcNameMode_Smart;

+  }

+}

 

 namespace NRecursedPostCharIndex {

   enum EEnum

   {

-    kWildCardRecursionOnly = 0,

+    kWildcardRecursionOnly = 0,

     kNoRecursion = 1

   };

 }

@@ -110,135 +164,127 @@
 static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be

 static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be

 

-static const wchar_t *kOverwritePostCharSet = L"asut";

+static const char *kOverwritePostCharSet = "asut";

 

 NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =

 {

-  NExtract::NOverwriteMode::kWithoutPrompt,

-  NExtract::NOverwriteMode::kSkipExisting,

-  NExtract::NOverwriteMode::kAutoRename,

-  NExtract::NOverwriteMode::kAutoRenameExisting

+  NExtract::NOverwriteMode::kOverwrite,

+  NExtract::NOverwriteMode::kSkip,

+  NExtract::NOverwriteMode::kRename,

+  NExtract::NOverwriteMode::kRenameExisting

 };

 

 static const CSwitchForm kSwitchForms[] =

-  {

-    { L"?",  NSwitchType::kSimple, false },

-    { L"H",  NSwitchType::kSimple, false },

-    { L"-HELP",  NSwitchType::kSimple, false },

-    { L"BA", NSwitchType::kSimple, false },

-    { L"BD", NSwitchType::kSimple, false },

-    { L"T",  NSwitchType::kUnLimitedPostString, false, 1 },

-    { L"Y",  NSwitchType::kSimple, false },

-    #ifndef _NO_CRYPTO

-    { L"P",  NSwitchType::kUnLimitedPostString, false, 0 },

-    #endif

-    { L"M",  NSwitchType::kUnLimitedPostString, true, 1 },

-    { L"O",  NSwitchType::kUnLimitedPostString, false, 1 },

-    { L"W",  NSwitchType::kUnLimitedPostString, false, 0 },

-    { L"I",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

-    { L"X",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

-    { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

-    { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

-    { L"AN", NSwitchType::kSimple, false },

-    { L"U",  NSwitchType::kUnLimitedPostString, true, 1},

-    { L"V",  NSwitchType::kUnLimitedPostString, true, 1},

-    { L"R",  NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },

-    { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },

-    { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },

-    { L"SO", NSwitchType::kSimple, false, 0 },

-    { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},

-    { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},

-    { L"AD",  NSwitchType::kSimple, false },

-    { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},

-    { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},

-    { L"SCC", NSwitchType::kUnLimitedPostString, false, 0},

-    { L"SLT", NSwitchType::kSimple, false },

-    { L"SSW", NSwitchType::kSimple, false },

-    { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" },

-    { L"SCRC", NSwitchType::kSimple, false }

-  };

-

-static const CCommandForm g_CommandForms[] =

 {

-  { L"A", false },

-  { L"U", false },

-  { L"D", false },

-  { L"T", false },

-  { L"E", false },

-  { L"X", false },

-  { L"L", false },

-  { L"B", false },

-  { L"I", false }

+  { "?" },

+  { "h" },

+  { "-help" },

+  { "ba" },

+  { "bd" },

+  { "t",  NSwitchType::kString, false, 1 },

+  { "y" },

+  #ifndef _NO_CRYPTO

+  { "p",  NSwitchType::kString },

+  #endif

+  { "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 },

+  { "sfx", NSwitchType::kString },

+  { "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" },

+  { "spe", NSwitchType::kMinus },

+  { "spf", NSwitchType::kString, false, 0 },

+  

+  { "snh", NSwitchType::kMinus },

+  { "snl", NSwitchType::kMinus },

+  { "sni" },

+  { "sns", NSwitchType::kMinus },

+  

+  { "snr" },

+  { "snc" },

+  

+  { "sdel" },

+  { "stl" },

+  { "stx", NSwitchType::kString, true, 1 }

 };

 

-static const int kNumCommandForms = sizeof(g_CommandForms) /  sizeof(g_CommandForms[0]);

-

 static const wchar_t *kUniversalWildcard = L"*";

 static const int kMinNonSwitchWords = 1;

 static const int kCommandIndex = 0;

 

-// ---------------------------

-// exception messages

-

-static const char *kUserErrorMessage  = "Incorrect command line";

+// 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 *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 *kEmptyFilePath = "Empty file path";

+static const char *kCannotFindArchive = "Cannot find archive";

 

-static void ThrowException(const char *errorMessage)

+bool CArcCommand::IsFromExtractGroup() const

 {

-  throw CArchiveCommandLineException(errorMessage);

-}

-

-static void ThrowUserErrorException()

-{

-  ThrowException(kUserErrorMessage);

-}

-

-// ---------------------------

-

-bool CArchiveCommand::IsFromExtractGroup() const

-{

-  switch(CommandType)

+  switch (CommandType)

   {

     case NCommandType::kTest:

     case NCommandType::kExtract:

-    case NCommandType::kFullExtract:

+    case NCommandType::kExtractFull:

       return true;

-    default:

-      return false;

   }

+  return false;

 }

 

-NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const

+NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const

 {

-  switch(CommandType)

+  switch (CommandType)

   {

     case NCommandType::kTest:

-    case NCommandType::kFullExtract:

-      return NExtract::NPathMode::kFullPathnames;

-    default:

-      return NExtract::NPathMode::kNoPathnames;

+    case NCommandType::kExtractFull:

+      return NExtract::NPathMode::kFullPaths;

   }

+  return NExtract::NPathMode::kNoPaths;

 }

 

-bool CArchiveCommand::IsFromUpdateGroup() const

+bool CArcCommand::IsFromUpdateGroup() const

 {

-  return (CommandType == NCommandType::kAdd ||

-    CommandType == NCommandType::kUpdate ||

-    CommandType == NCommandType::kDelete);

+  switch (CommandType)

+  {

+    case NCommandType::kAdd:

+    case NCommandType::kUpdate:

+    case NCommandType::kDelete:

+    case NCommandType::kRename:

+      return true;

+  }

+  return false;

 }

 

 static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)

 {

   switch (index)

   {

-    case NRecursedPostCharIndex::kWildCardRecursionOnly:

-      return NRecursedType::kWildCardOnlyRecursed;

+    case NRecursedPostCharIndex::kWildcardRecursionOnly:

+      return NRecursedType::kWildcardOnlyRecursed;

     case NRecursedPostCharIndex::kNoRecursion:

       return NRecursedType::kNonRecursed;

     default:

@@ -246,170 +292,281 @@
   }

 }

 

-static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)

+static const char *g_Commands = "audtexlbih";

+

+static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command)

 {

-  UString commandStringUpper = commandString;

-  commandStringUpper.MakeUpper();

-  UString postString;

-  int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,

-      postString) ;

-  if (commandIndex < 0)

-    return false;

-  command.CommandType = (NCommandType::EEnum)commandIndex;

-  return true;

+  UString s = commandString;

+  s.MakeLower_Ascii();

+  if (s.Len() == 1)

+  {

+    if (s[0] > 0x7F)

+      return false;

+    int index = FindCharPosInString(g_Commands, (char)s[0]);

+    if (index < 0)

+      return false;

+    command.CommandType = (NCommandType::EEnum)index;

+    return true;

+  }

+  if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n')

+  {

+    command.CommandType = (NCommandType::kRename);

+    return true;

+  }

+  return false;

 }

 

 // ------------------------------------------------------------------

 // filenames functions

 

-static void AddNameToCensor(NWildcard::CCensor &wildcardCensor,

-    const UString &name, bool include, NRecursedType::EEnum type)

+static void AddNameToCensor(NWildcard::CCensor &censor,

+    const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching)

 {

   bool recursed = false;

 

   switch (type)

   {

-    case NRecursedType::kWildCardOnlyRecursed:

-      recursed = DoesNameContainWildCard(name);

+    case NRecursedType::kWildcardOnlyRecursed:

+      recursed = DoesNameContainWildcard(name);

       break;

     case NRecursedType::kRecursed:

       recursed = true;

       break;

   }

-  wildcardCensor.AddItem(include, name, recursed);

+  censor.AddPreItem(include, name, recursed, wildcardMatching);

 }

 

-static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,

-    LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)

+static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,

+    const UString &oldName, const UString &newName, NRecursedType::EEnum type,

+    bool wildcardMatching)

+{

+  CRenamePair &pair = renamePairs->AddNew();

+  pair.OldName = oldName;

+  pair.NewName = newName;

+  pair.RecursedType = type;

+  pair.WildcardParsing = wildcardMatching;

+

+  if (!pair.Prepare())

+  {

+    UString val;

+    val += pair.OldName;

+    AddNewLine(val);

+    val += pair.NewName;

+    AddNewLine(val);

+    if (type == NRecursedType::kRecursed)

+      val += L"-r";

+    else if (type == NRecursedType::kRecursed)

+      val += L"-r0";

+    throw CArcCmdLineException("Unsupported rename command:", val);

+  }

+}

+

+static void AddToCensorFromListFile(

+    CObjectVector<CRenamePair> *renamePairs,

+    NWildcard::CCensor &censor,

+    LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage)

 {

   UStringVector names;

-  if (!NFind::DoesFileExist(fileName))

-    throw kCannotFindListFile;

-  if (!ReadNamesFromListFile(fileName, names, codePage))

-    throw kIncorrectListFile;

-  for (int i = 0; i < names.Size(); i++)

-    AddNameToCensor(wildcardCensor, names[i], include, type);

+  if (!NFind::DoesFileExist(us2fs(fileName)))

+    throw CArcCmdLineException(kCannotFindListFile, fileName);

+  if (!ReadNamesFromListFile(us2fs(fileName), names, codePage))

+    throw CArcCmdLineException(kIncorrectListFile, fileName);

+  if (renamePairs)

+  {

+    if ((names.Size() & 1) != 0)

+      throw CArcCmdLineException(kIncorrectListFile, fileName);

+    for (unsigned i = 0; i < names.Size(); i += 2)

+    {

+      // change type !!!!

+      AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching);

+    }

+  }

+  else

+    FOR_VECTOR (i, names)

+      AddNameToCensor(censor, names[i], include, type, wildcardMatching);

 }

 

 static void AddToCensorFromNonSwitchesStrings(

-    int startIndex,

-    NWildcard::CCensor &wildcardCensor,

+    CObjectVector<CRenamePair> *renamePairs,

+    unsigned startIndex,

+    NWildcard::CCensor &censor,

     const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,

-    bool thereAreSwitchIncludes, UINT codePage)

+    bool wildcardMatching,

+    bool thereAreSwitchIncludes, Int32 codePage)

 {

-  if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))

-    AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type);

-  for (int i = startIndex; i < nonSwitchStrings.Size(); i++)

+  if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes)

+    AddNameToCensor(censor, kUniversalWildcard, true, type,

+        true // wildcardMatching

+        );

+

+  int oldIndex = -1;

+  

+  for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++)

   {

     const UString &s = nonSwitchStrings[i];

     if (s.IsEmpty())

-      throw kEmptyFilePath;

+      throw CArcCmdLineException(kEmptyFilePath);

     if (s[0] == kFileListID)

-      AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);

+      AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage);

+    else if (renamePairs)

+    {

+      if (oldIndex == -1)

+        oldIndex = startIndex;

+      else

+      {

+        // NRecursedType::EEnum type is used for global wildcard (-i! switches)

+        AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching);

+        // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type);

+        oldIndex = -1;

+      }

+    }

     else

-      AddNameToCensor(wildcardCensor, s, true, type);

+      AddNameToCensor(censor, s, true, type, wildcardMatching);

+  }

+  

+  if (oldIndex != -1)

+  {

+    throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]);

   }

 }

 

 #ifdef _WIN32

-static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,

-    const UString &switchParam, bool include,

-    NRecursedType::EEnum commonRecursedType)

+

+struct CEventSetEnd

 {

-  int splitPos = switchParam.Find(L':');

-  if (splitPos < 0)

-    ThrowUserErrorException();

-  UString mappingName = switchParam.Left(splitPos);

+  UString Name;

   

-  UString switchParam2 = switchParam.Mid(splitPos + 1);

-  splitPos = switchParam2.Find(L':');

-  if (splitPos < 0)

-    ThrowUserErrorException();

-  

-  UString mappingSize = switchParam2.Left(splitPos);

-  UString eventName = switchParam2.Mid(splitPos + 1);

-  

-  UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);

-  UInt32 dataSize = (UInt32)dataSize64;

-  {

-    CFileMapping fileMapping;

-    if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0)

-      ThrowException("Can not open mapping");

-    LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize);

-    if (data == NULL)

-      ThrowException("MapViewOfFile error");

-    try

-    {

-      const wchar_t *curData = (const wchar_t *)data;

-      if (*curData != 0)

-        ThrowException("Incorrect mapping data");

-      UInt32 numChars = dataSize / sizeof(wchar_t);

-      UString name;

-      for (UInt32 i = 1; i < numChars; i++)

-      {

-        wchar_t c = curData[i];

-        if (c == L'\0')

-        {

-          AddNameToCensor(wildcardCensor, name, include, commonRecursedType);

-          name.Empty();

-        }

-        else

-          name += c;

-      }

-      if (!name.IsEmpty())

-        ThrowException("data error");

-    }

-    catch(...)

-    {

-      UnmapViewOfFile(data);

-      throw;

-    }

-    UnmapViewOfFile(data);

-  }

-  

+  CEventSetEnd(const wchar_t *name): Name(name) {}

+  ~CEventSetEnd()

   {

     NSynchronization::CManualResetEvent event;

-    if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK)

+    if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0)

       event.Set();

   }

+};

+

+const char *k_IncorrectMapCommand = "Incorrect Map command";

+

+static const char *ParseMapWithPaths(

+    NWildcard::CCensor &censor,

+    const UString &s2, bool include,

+    NRecursedType::EEnum commonRecursedType,

+    bool wildcardMatching)

+{

+  UString s = s2;

+  int pos = s.Find(L':');

+  if (pos < 0)

+    return k_IncorrectMapCommand;

+  int pos2 = s.Find(L':', pos + 1);

+  if (pos2 < 0)

+    return k_IncorrectMapCommand;

+

+  CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1));

+  s.DeleteFrom(pos2);

+  UInt32 size;

+  if (!StringToUInt32(s.Ptr(pos + 1), size)

+      || size < sizeof(wchar_t)

+      || size > ((UInt32)1 << 31)

+      || size % sizeof(wchar_t) != 0)

+    return "Unsupported Map data size";

+

+  s.DeleteFrom(pos);

+  CFileMapping map;

+  if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0)

+    return "Can not open mapping";

+  LPVOID data = map.Map(FILE_MAP_READ, 0, size);

+  if (!data)

+    return "MapViewOfFile error";

+  CFileUnmapper unmapper(data);

+

+  UString name;

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

+  if (*p != 0) // data format marker

+    return "Unsupported Map data";

+  UInt32 numChars = size / sizeof(wchar_t);

+  for (UInt32 i = 1; i < numChars; i++)

+  {

+    wchar_t c = p[i];

+    if (c == 0)

+    {

+      // MessageBoxW(0, name, L"7-Zip", 0);

+      AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching);

+      name.Empty();

+    }

+    else

+      name += c;

+  }

+  if (!name.IsEmpty())

+    return "Map data error";

+

+  return NULL;

 }

+

 #endif

 

-static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,

+static void AddSwitchWildcardsToCensor(

+    NWildcard::CCensor &censor,

     const UStringVector &strings, bool include,

-    NRecursedType::EEnum commonRecursedType, UINT codePage)

+    NRecursedType::EEnum commonRecursedType,

+    bool wildcardMatching,

+    Int32 codePage)

 {

-  for (int i = 0; i < strings.Size(); i++)

+  const char *errorMessage = NULL;

+  unsigned i;

+  for (i = 0; i < strings.Size(); i++)

   {

     const UString &name = strings[i];

     NRecursedType::EEnum recursedType;

-    int pos = 0;

-    if (name.Length() < kSomeCludePostStringMinSize)

-      ThrowUserErrorException();

-    if (::MyCharUpper(name[pos]) == kRecursedIDChar)

+    unsigned pos = 0;

+    

+    if (name.Len() < kSomeCludePostStringMinSize)

+    {

+      errorMessage = "Too short switch";

+      break;

+    }

+    

+    if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar)

     {

       pos++;

-      int index = UString(kRecursedPostCharSet).Find(name[pos]);

+      wchar_t c = name[pos];

+      int index = -1;

+      if (c <= 0x7F)

+        index = FindCharPosInString(kRecursedPostCharSet, (char)c);

       recursedType = GetRecursedTypeFromIndex(index);

       if (index >= 0)

         pos++;

     }

     else

       recursedType = commonRecursedType;

-    if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)

-      ThrowUserErrorException();

-    UString tail = name.Mid(pos + 1);

+    

+    if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize)

+    {

+      errorMessage = "Too short switch";

+      break;

+    }

+    

+    UString tail = name.Ptr(pos + 1);

+    

     if (name[pos] == kImmediateNameID)

-      AddNameToCensor(wildcardCensor, tail, include, recursedType);

+      AddNameToCensor(censor, tail, include, recursedType, wildcardMatching);

     else if (name[pos] == kFileListID)

-      AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);

+      AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage);

     #ifdef _WIN32

     else if (name[pos] == kMapNameID)

-      ParseMapWithPaths(wildcardCensor, tail, include, recursedType);

+    {

+      errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching);

+      if (errorMessage)

+        break;

+    }

     #endif

     else

-      ThrowUserErrorException();

+    {

+      errorMessage = "Incorrect wildcarc type marker";

+      break;

+    }

   }

+  if (i != strings.Size())

+    throw CArcCmdLineException(errorMessage, strings[i]);

 }

 

 #ifdef _WIN32

@@ -418,20 +575,25 @@
 

 static void ConvertToLongName(const UString &prefix, UString &name)

 {

-  if (name.IsEmpty() || DoesNameContainWildCard(name))

+  if (name.IsEmpty() || DoesNameContainWildcard(name))

     return;

-  NFind::CFileInfoW fi;

-  if (fi.Find(prefix + name))

-    name = fi.Name;

+  NFind::CFileInfo fi;

+  const FString path = us2fs(prefix + name);

+  if (NFile::NName::IsDevicePath(path))

+    return;

+  if (fi.Find(path))

+    name = fs2us(fi.Name);

 }

 

 static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)

 {

-  for (int i = 0; i < items.Size(); i++)

+  FOR_VECTOR (i, items)

   {

     NWildcard::CItem &item = items[i];

     if (item.Recursive || item.PathParts.Size() != 1)

       continue;

+    if (prefix.IsEmpty() && item.IsDriveItem())

+      continue;

     ConvertToLongName(prefix, item.PathParts.Front());

   }

 }

@@ -440,17 +602,22 @@
 {

   ConvertToLongNames(prefix, node.IncludeItems);

   ConvertToLongNames(prefix, node.ExcludeItems);

-  int i;

+  unsigned i;

   for (i = 0; i < node.SubNodes.Size(); i++)

-    ConvertToLongName(prefix, node.SubNodes[i].Name);

+  {

+    UString &name = node.SubNodes[i].Name;

+    if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))

+      continue;

+    ConvertToLongName(prefix, name);

+  }

   // mix folders with same name

   for (i = 0; i < node.SubNodes.Size(); i++)

   {

     NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];

-    for (int j = i + 1; j < node.SubNodes.Size();)

+    for (unsigned j = i + 1; j < node.SubNodes.Size();)

     {

       const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];

-      if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)

+      if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name))

       {

         nextNode1.IncludeItems += nextNode2.IncludeItems;

         nextNode1.ExcludeItems += nextNode2.ExcludeItems;

@@ -463,13 +630,13 @@
   for (i = 0; i < node.SubNodes.Size(); i++)

   {

     NWildcard::CCensorNode &nextNode = node.SubNodes[i];

-    ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode);

+    ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);

   }

 }

 

-static void ConvertToLongNames(NWildcard::CCensor &censor)

+void ConvertToLongNames(NWildcard::CCensor &censor)

 {

-  for (int i = 0; i < censor.Pairs.Size(); i++)

+  FOR_VECTOR (i, censor.Pairs)

   {

     NWildcard::CPair &pair = censor.Pairs[i];

     ConvertToLongNames(pair.Prefix, pair.Head);

@@ -478,9 +645,10 @@
 

 #endif

 

+/*

 static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)

 {

-  switch(i)

+  switch (i)

   {

     case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;

     case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;

@@ -489,35 +657,36 @@
   }

   throw 98111603;

 }

+*/

 

-const UString kUpdatePairStateIDSet = L"PQRXYZW";

-const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};

+static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw";

+static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};

 

-const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti

-

-const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";

-const wchar_t kUpdateNewArchivePostCharID = '!';

+static const unsigned kNumUpdatePairActions = 4;

+static const char *kUpdateIgnoreItselfPostStringID = "-";

+static const wchar_t kUpdateNewArchivePostCharID = '!';

 

 

 static bool ParseUpdateCommandString2(const UString &command,

     NUpdateArchive::CActionSet &actionSet, UString &postString)

 {

-  for (int i = 0; i < command.Length();)

+  for (unsigned i = 0; i < command.Len();)

   {

-    wchar_t c = MyCharUpper(command[i]);

-    int statePos = kUpdatePairStateIDSet.Find(c);

+    wchar_t c = MyCharLower_Ascii(command[i]);

+    int statePos = FindCharPosInString(kUpdatePairStateIDSet, c);

     if (statePos < 0)

     {

-      postString = command.Mid(i);

+      postString = command.Ptr(i);

       return true;

     }

     i++;

-    if (i >= command.Length())

+    if (i >= command.Len())

       return false;

-    int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));

-    if (actionPos < 0)

+    c = command[i];

+    if (c < '0' || c >= '0' + kNumUpdatePairActions)

       return false;

-    actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);

+    int actionPos = c - '0';

+    actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);

     if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)

       return false;

     i++;

@@ -530,10 +699,12 @@
     const UStringVector &updatePostStrings,

     const NUpdateArchive::CActionSet &defaultActionSet)

 {

-  for (int i = 0; i < updatePostStrings.Size(); i++)

+  const char *errorMessage = "incorrect update switch command";

+  unsigned i;

+  for (i = 0; i < updatePostStrings.Size(); i++)

   {

     const UString &updateString = updatePostStrings[i];

-    if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)

+    if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID))

     {

       if (options.UpdateArchiveItself)

       {

@@ -547,7 +718,7 @@
 

       UString postString;

       if (!ParseUpdateCommandString2(updateString, actionSet, postString))

-        ThrowUserErrorException();

+        break;

       if (postString.IsEmpty())

       {

         if (options.UpdateArchiveItself)

@@ -555,64 +726,23 @@
       }

       else

       {

-        if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)

-          ThrowUserErrorException();

+        if (postString[0] != kUpdateNewArchivePostCharID)

+          break;

         CUpdateArchiveCommand uc;

-        UString archivePath = postString.Mid(1);

+        UString archivePath = postString.Ptr(1);

         if (archivePath.IsEmpty())

-          ThrowUserErrorException();

+          break;

         uc.UserArchivePath = archivePath;

         uc.ActionSet = actionSet;

         options.Commands.Add(uc);

       }

     }

   }

+  if (i != updatePostStrings.Size())

+    throw CArcCmdLineException(errorMessage, updatePostStrings[i]);

 }

 

-static const char kByteSymbol = 'B';

-static const char kKiloSymbol = 'K';

-static const char kMegaSymbol = 'M';

-static const char kGigaSymbol = 'G';

-

-static bool ParseComplexSize(const UString &src, UInt64 &result)

-{

-  UString s = src;

-  s.MakeUpper();

-

-  const wchar_t *start = s;

-  const wchar_t *end;

-  UInt64 number = ConvertStringToUInt64(start, &end);

-  int numDigits = (int)(end - start);

-  if (numDigits == 0 || s.Length() > numDigits + 1)

-    return false;

-  if (s.Length() == numDigits)

-  {

-    result = number;

-    return true;

-  }

-  int numBits;

-  switch (s[numDigits])

-  {

-    case kByteSymbol:

-      result = number;

-      return true;

-    case kKiloSymbol:

-      numBits = 10;

-      break;

-    case kMegaSymbol:

-      numBits = 20;

-      break;

-    case kGigaSymbol:

-      numBits = 30;

-      break;

-    default:

-      return false;

-  }

-  if (number >= ((UInt64)1 << (64 - numBits)))

-    return false;

-  result = number << numBits;

-  return true;

-}

+bool ParseComplexSize(const wchar_t *s, UInt64 &result);

 

 static void SetAddCommandOptions(

     NCommandType::EEnum commandType,

@@ -620,16 +750,16 @@
     CUpdateOptions &options)

 {

   NUpdateArchive::CActionSet defaultActionSet;

-  switch(commandType)

+  switch (commandType)

   {

     case NCommandType::kAdd:

-      defaultActionSet = NUpdateArchive::kAddActionSet;

+      defaultActionSet = NUpdateArchive::k_ActionSet_Add;

       break;

     case NCommandType::kDelete:

-      defaultActionSet = NUpdateArchive::kDeleteActionSet;

+      defaultActionSet = NUpdateArchive::k_ActionSet_Delete;

       break;

     default:

-      defaultActionSet = NUpdateArchive::kUpdateActionSet;

+      defaultActionSet = NUpdateArchive::k_ActionSet_Update;

   }

   

   options.UpdateArchiveItself = true;

@@ -645,22 +775,22 @@
   {

     const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];

     if (postString.IsEmpty())

-      NDirectory::MyGetTempPath(options.WorkingDir);

+      NDir::MyGetTempPath(options.WorkingDir);

     else

-      options.WorkingDir = postString;

+      options.WorkingDir = us2fs(postString);

   }

   options.SfxMode = parser[NKey::kSfx].ThereIs;

   if (options.SfxMode)

-    options.SfxModule = parser[NKey::kSfx].PostStrings[0];

+    options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]);

 

   if (parser[NKey::kVolume].ThereIs)

   {

     const UStringVector &sv = parser[NKey::kVolume].PostStrings;

-    for (int i = 0; i < sv.Size(); i++)

+    FOR_VECTOR (i, sv)

     {

       UInt64 size;

-      if (!ParseComplexSize(sv[i], size))

-        ThrowException("Incorrect volume size");

+      if (!ParseComplexSize(sv[i], size) || size == 0)

+        throw CArcCmdLineException("Incorrect volume size:", sv[i]);

       options.VolumesSizes.Add(size);

     }

   }

@@ -670,38 +800,28 @@
 {

   if (parser[NKey::kProperty].ThereIs)

   {

-    // options.MethodMode.Properties.Clear();

-    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)

+    FOR_VECTOR (i, parser[NKey::kProperty].PostStrings)

     {

-      CProperty property;

-      const UString &postString = parser[NKey::kProperty].PostStrings[i];

-      int index = postString.Find(L'=');

-      if (index < 0)

-        property.Name = postString;

-      else

+      CProperty prop;

+      prop.Name = parser[NKey::kProperty].PostStrings[i];

+      int index = prop.Name.Find(L'=');

+      if (index >= 0)

       {

-        property.Name = postString.Left(index);

-        property.Value = postString.Mid(index + 1);

+        prop.Value = prop.Name.Ptr(index + 1);

+        prop.Name.DeleteFrom(index);

       }

-      properties.Add(property);

+      properties.Add(prop);

     }

   }

 }

 

-CArchiveCommandLineParser::CArchiveCommandLineParser():

-  parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}

+CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {}

 

-void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,

-    CArchiveCommandLineOptions &options)

+void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,

+    CArcCmdLineOptions &options)

 {

-  try

-  {

-    parser.ParseStrings(kSwitchForms, commandStrings);

-  }

-  catch(...)

-  {

-    ThrowUserErrorException();

-  }

+  if (!parser.ParseStrings(kSwitchForms, commandStrings))

+    throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine);

 

   options.IsInTerminal = MY_IS_TERMINAL(stdin);

   options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);

@@ -711,62 +831,67 @@
   options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;

   options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;

 

+  if (parser[NKey::kCaseSensitive].ThereIs)

+  {

+    g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus;

+    options.CaseSensitiveChange = true;

+    options.CaseSensitive = g_CaseSensitive;

+  }

+

   #ifdef _WIN32

   options.LargePages = false;

   if (parser[NKey::kLargePages].ThereIs)

   {

-    const UString &postString = parser[NKey::kLargePages].PostStrings.Front();

-    if (postString.IsEmpty())

-      options.LargePages = true;

+    options.LargePages = !parser[NKey::kLargePages].WithMinus;

   }

   #endif

 }

 

 struct CCodePagePair

 {

-  const wchar_t *Name;

-  UINT CodePage;

+  const char *Name;

+  Int32 CodePage;

 };

 

+static const unsigned kNumByteOnlyCodePages = 3;

+

 static CCodePagePair g_CodePagePairs[] =

 {

-  { L"UTF-8", CP_UTF8 },

-  { L"WIN", CP_ACP },

-  { L"DOS", CP_OEMCP }

+  { "utf-8", CP_UTF8 },

+  { "win", CP_ACP },

+  { "dos", CP_OEMCP },

+  { "utf-16le", MY__CP_UTF16 },

+  { "utf-16be", MY__CP_UTF16BE }

 };

 

-static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal)

+static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex,

+    bool byteOnlyCodePages, Int32 defaultVal)

 {

   if (!parser[keyIndex].ThereIs)

     return defaultVal;

 

   UString name = parser[keyIndex].PostStrings.Back();

-  name.MakeUpper();

-  int i;

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

+  UInt32 v;

+  if (StringToUInt32(name, v))

+    if (v < ((UInt32)1 << 16))

+      return (Int32)v;

+  name.MakeLower_Ascii();

+  unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs);

+  for (unsigned i = 0;; i++)

   {

+    if (i == num) // to disable warnings from different compilers

+      throw CArcCmdLineException("Unsupported charset:", name);

     const CCodePagePair &pair = g_CodePagePairs[i];

-    if (name.Compare(pair.Name) == 0)

+    if (name.IsEqualTo(pair.Name))

       return pair.CodePage;

   }

-  if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]))

-    ThrowUserErrorException();

-  return -1;

 }

 

-static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)

-{

-  const wchar_t *end;

-  UInt64 number = ConvertStringToUInt64(s, &end);

-  if (*end != 0)

-    return false;

-  if (number > (UInt32)0xFFFFFFFF)

-    return false;

-  v = (UInt32)number;

-  return true;

-}

-

-void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,

+void EnumerateDirItemsAndSort(

+    bool storeAltStreams,

+    NWildcard::CCensor &censor,

+    NWildcard::ECensorPathMode censorPathMode,

+    const UString &addPathPrefix,

     UStringVector &sortedPaths,

     UStringVector &sortedFullPaths)

 {

@@ -774,13 +899,18 @@
   {

     CDirItems dirItems;

     {

-      UStringVector errorPaths;

-      CRecordVector<DWORD> errorCodes;

-      HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes);

-      if (res != S_OK || errorPaths.Size() > 0)

-        throw "cannot find archive";

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

+      }

     }

-    for (int i = 0; i < dirItems.Items.Size(); i++)

+    FOR_VECTOR (i, dirItems.Items)

     {

       const CDirItem &dirItem = dirItems.Items[i];

       if (!dirItem.IsDir())

@@ -789,44 +919,72 @@
   }

   

   if (paths.Size() == 0)

-    throw "there is no such archive";

+    throw CArcCmdLineException(kCannotFindArchive);

   

   UStringVector fullPaths;

   

-  int i;

+  unsigned i;

   for (i = 0; i < paths.Size(); i++)

   {

-    UString fullPath;

-    NFile::NDirectory::MyGetFullPathName(paths[i], fullPath);

-    fullPaths.Add(fullPath);

+    FString fullPath;

+    NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath);

+    fullPaths.Add(fs2us(fullPath));

   }

-  CIntVector indices;

+  CUIntVector indices;

   SortFileNames(fullPaths, indices);

-  sortedPaths.Reserve(indices.Size());

-  sortedFullPaths.Reserve(indices.Size());

+  sortedPaths.ClearAndReserve(indices.Size());

+  sortedFullPaths.ClearAndReserve(indices.Size());

   for (i = 0; i < indices.Size(); i++)

   {

-    int index = indices[i];

-    sortedPaths.Add(paths[index]);

-    sortedFullPaths.Add(fullPaths[index]);

+    unsigned index = indices[i];

+    sortedPaths.AddInReserved(paths[index]);

+    sortedFullPaths.AddInReserved(fullPaths[index]);

+    if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)

+      throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]);

   }

 }

 

-void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)

+static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)

+{

+  bp.Def = parser[switchID].ThereIs;

+  if (bp.Def)

+    bp.Val = !parser[switchID].WithMinus;

+}

+

+void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)

 {

   const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

   int numNonSwitchStrings = nonSwitchStrings.Size();

   if (numNonSwitchStrings < kMinNonSwitchWords)

-    ThrowUserErrorException();

+    throw CArcCmdLineException("The command must be spcified");

 

   if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))

-    ThrowUserErrorException();

+    throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);

 

   options.TechMode = parser[NKey::kTechMode].ThereIs;

-  options.CalcCrc = parser[NKey::kCalcCrc].ThereIs;

-

-  if (parser[NKey::kCaseSensitive].ThereIs)

-    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);

+  if (parser[NKey::kHash].ThereIs)

+    options.HashMethods = parser[NKey::kHash].PostStrings;

+  

+  if (parser[NKey::kElimDup].ThereIs)

+  {

+    options.ExtractOptions.ElimDup.Def = true;

+    options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus;

+  }

+  

+  NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath;

+  bool fullPathMode = parser[NKey::kFullPathMode].ThereIs;

+  if (fullPathMode)

+  {

+    censorPathMode = NWildcard::k_AbsPath;

+    const UString &s = parser[NKey::kFullPathMode].PostStrings[0];

+    if (!s.IsEmpty())

+    {

+      if (s == L"2")

+        censorPathMode = NWildcard::k_FullPath;

+      else

+        throw CArcCmdLineException("Unsupported -spf:", s);

+    }

+  }

 

   NRecursedType::EEnum recursedType;

   if (parser[NKey::kRecursed].ThereIs)

@@ -834,43 +992,55 @@
   else

     recursedType = NRecursedType::kNonRecursed;

 

-  g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1);

-  UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8);

+  bool wildcardMatching = true;

+  if (parser[NKey::kDisableWildcardParsing].ThereIs)

+    wildcardMatching = false;

+

+  g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1);

+  Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8);

 

   bool thereAreSwitchIncludes = false;

+  

   if (parser[NKey::kInclude].ThereIs)

   {

     thereAreSwitchIncludes = true;

-    AddSwitchWildCardsToCensor(options.WildcardCensor,

-        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);

+    AddSwitchWildcardsToCensor(options.Censor,

+        parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage);

   }

+

   if (parser[NKey::kExclude].ThereIs)

-    AddSwitchWildCardsToCensor(options.WildcardCensor,

-        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);

+    AddSwitchWildcardsToCensor(options.Censor,

+        parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage);

  

   int curCommandIndex = kCommandIndex + 1;

   bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&

       options.Command.CommandType != NCommandType::kBenchmark &&

-      options.Command.CommandType != NCommandType::kInfo;

+      options.Command.CommandType != NCommandType::kInfo &&

+      options.Command.CommandType != NCommandType::kHash;

 

   bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

   bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;

+  bool isRename = options.Command.CommandType == NCommandType::kRename;

 

-  if (isExtractOrList && options.StdInMode)

+  if ((isExtractOrList || isRename) && options.StdInMode)

     thereIsArchiveName = false;

 

+  if (parser[NKey::kArcNameMode].ThereIs)

+    options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex);

+

   if (thereIsArchiveName)

   {

     if (curCommandIndex >= numNonSwitchStrings)

-      ThrowUserErrorException();

+      throw CArcCmdLineException("Cannot find archive name");

     options.ArchiveName = nonSwitchStrings[curCommandIndex++];

     if (options.ArchiveName.IsEmpty())

-      ThrowUserErrorException();

+      throw CArcCmdLineException("Archive name cannot by empty");

   }

 

-  AddToCensorFromNonSwitchesStrings(

-      curCommandIndex, options.WildcardCensor,

-      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);

+  AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL,

+      curCommandIndex, options.Censor,

+      nonSwitchStrings, recursedType, wildcardMatching,

+      thereAreSwitchIncludes, codePage);

 

   options.YesToAll = parser[NKey::kYes].ThereIs;

 

@@ -886,28 +1056,73 @@
   if (parser[NKey::kArchiveType].ThereIs)

     options.ArcType = parser[NKey::kArchiveType].PostStrings[0];

 

+  options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings;

+

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

+  SetBoolPair(parser, NKey::kHardLinks, options.HardLinks);

+  SetBoolPair(parser, NKey::kSymLinks, options.SymLinks);

+

   if (isExtractOrList)

   {

-    if (!options.WildcardCensor.AllAreRelative())

-      ThrowException("Cannot use absolute pathnames for this command");

+    CExtractOptionsBase &eo = options.ExtractOptions;

 

-    NWildcard::CCensor archiveWildcardCensor;

+    {

+      CExtractNtOptions &nt = eo.NtOptions;

+      nt.NtSecurity = options.NtSecurity;

+

+      nt.AltStreams = options.AltStreams;

+      if (!options.AltStreams.Def)

+        nt.AltStreams.Val = true;

+

+      nt.HardLinks = options.HardLinks;

+      if (!options.HardLinks.Def)

+        nt.HardLinks.Val = true;

+

+      nt.SymLinks = options.SymLinks;

+      if (!options.SymLinks.Def)

+        nt.SymLinks.Val = true;

+

+      nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;

+      nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;

+    }

+      

+    options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);

+    options.Censor.ExtendExclude();

+

+    // are there paths that look as non-relative (!Prefix.IsEmpty())

+    if (!options.Censor.AllAreRelative())

+      throw CArcCmdLineException("Cannot use absolute pathnames for this command");

+

+    NWildcard::CCensor arcCensor;

 

     if (parser[NKey::kArInclude].ThereIs)

-      AddSwitchWildCardsToCensor(archiveWildcardCensor,

-          parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);

+      AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage);

     if (parser[NKey::kArExclude].ThereIs)

-      AddSwitchWildCardsToCensor(archiveWildcardCensor,

-          parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);

+      AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage);

 

     if (thereIsArchiveName)

-      AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);

+      AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching);

+

+    arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);

 

     #ifdef _WIN32

-    ConvertToLongNames(archiveWildcardCensor);

+    ConvertToLongNames(arcCensor);

     #endif

 

-    archiveWildcardCensor.ExtendExclude();

+    arcCensor.ExtendExclude();

 

     if (options.StdInMode)

     {

@@ -917,54 +1132,76 @@
     }

     else

     {

-      EnumerateDirItemsAndSort(archiveWildcardCensor,

-        options.ArchivePathsSorted,

-        options.ArchivePathsFullSorted);

+      EnumerateDirItemsAndSort(

+          false,     // scanAltStreams

+          arcCensor,

+          NWildcard::k_RelatPath,

+          UString(), // addPathPrefix

+          options.ArchivePathsSorted,

+          options.ArchivePathsFullSorted);

     }

     

     if (isExtractGroupCommand)

     {

-      SetMethodOptions(parser, options.ExtractProperties);

       if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)

-        throw kSameTerminalError;

+        throw CArcCmdLineException(kSameTerminalError);

       if (parser[NKey::kOutputDir].ThereIs)

       {

-        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];

-        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);

+        eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);

+        NFile::NName::NormalizeDirPathPrefix(eo.OutputDir);

       }

 

-      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;

+      eo.OverwriteMode = NExtract::NOverwriteMode::kAsk;

       if (parser[NKey::kOverwrite].ThereIs)

-        options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];

+      {

+        eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];

+        eo.OverwriteMode_Force = true;

+      }

       else if (options.YesToAll)

-        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;

+      {

+        eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite;

+        eo.OverwriteMode_Force = true;

+      }

+    }

+

+    eo.PathMode = options.Command.GetPathMode();

+    if (censorPathMode == NWildcard::k_AbsPath)

+    {

+      eo.PathMode = NExtract::NPathMode::kAbsPaths;

+      eo.PathMode_Force = true;

+    }

+    else if (censorPathMode == NWildcard::k_FullPath)

+    {

+      eo.PathMode = NExtract::NPathMode::kFullPaths;

+      eo.PathMode_Force = true;

     }

   }

   else if (options.Command.IsFromUpdateGroup())

   {

+    if (parser[NKey::kArInclude].ThereIs)

+      throw CArcCmdLineException("-ai switch is not supported for this command");

+

     CUpdateOptions &updateOptions = options.UpdateOptions;

 

     SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);

     

-    SetMethodOptions(parser, updateOptions.MethodMode.Properties);

+    updateOptions.MethodMode.Properties = options.Properties;

 

     if (parser[NKey::kShareForWrite].ThereIs)

       updateOptions.OpenShareForWrite = true;

 

-    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

+    updateOptions.PathMode = censorPathMode;

 

-    if (options.EnablePercents)

-    {

-      if ((options.StdOutMode && !options.IsStdErrTerminal) ||

-         (!options.StdOutMode && !options.IsStdOutTerminal))

-        options.EnablePercents = false;

-    }

+    updateOptions.AltStreams = options.AltStreams;

+    updateOptions.NtSecurity = options.NtSecurity;

+    updateOptions.HardLinks = options.HardLinks;

+    updateOptions.SymLinks = options.SymLinks;

 

     updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;

     if (updateOptions.EMailMode)

     {

       updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();

-      if (updateOptions.EMailAddress.Length() > 0)

+      if (updateOptions.EMailAddress.Len() > 0)

         if (updateOptions.EMailAddress[0] == L'.')

         {

           updateOptions.EMailRemoveAfter = true;

@@ -975,68 +1212,46 @@
     updateOptions.StdOutMode = options.StdOutMode;

     updateOptions.StdInMode = options.StdInMode;

 

+    updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs;

+    updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs;

+

     if (updateOptions.StdOutMode && updateOptions.EMailMode)

-      throw "stdout mode and email mode cannot be combined";

+      throw CArcCmdLineException("stdout mode and email mode cannot be combined");

     if (updateOptions.StdOutMode && options.IsStdOutTerminal)

-      throw kTerminalOutError;

+      throw CArcCmdLineException(kTerminalOutError);

     if (updateOptions.StdInMode)

       updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

 

-    #ifdef _WIN32

-    ConvertToLongNames(options.WildcardCensor);

-    #endif

+    if (options.Command.CommandType == NCommandType::kRename)

+      if (updateOptions.Commands.Size() != 1)

+        throw CArcCmdLineException("Only one archive can be created with rename command");

   }

   else if (options.Command.CommandType == NCommandType::kBenchmark)

   {

-    options.NumThreads = (UInt32)-1;

-    options.DictionarySize = (UInt32)-1;

     options.NumIterations = 1;

     if (curCommandIndex < numNonSwitchStrings)

     {

-      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))

-        ThrowUserErrorException();

+      if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations))

+        throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]);

+      curCommandIndex++;

     }

-    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)

-    {

-      UString postString = parser[NKey::kProperty].PostStrings[i];

-      postString.MakeUpper();

-      if (postString.Length() < 2)

-        ThrowUserErrorException();

-      if (postString[0] == 'D')

-      {

-        int pos = 1;

-        if (postString[pos] == '=')

-          pos++;

-        UInt32 logSize;

-        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))

-          ThrowUserErrorException();

-        if (logSize > 31)

-          ThrowUserErrorException();

-        options.DictionarySize = 1 << logSize;

-      }

-      else if (postString[0] == 'M' && postString[1] == 'T' )

-      {

-        int pos = 2;

-        if (postString[pos] == '=')

-          pos++;

-        if (postString[pos] != 0)

-          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))

-            ThrowUserErrorException();

-      }

-      else if (postString[0] == 'M' && postString[1] == '=' )

-      {

-        int pos = 2;

-        if (postString[pos] != 0)

-          options.Method = postString.Mid(2);

-      }

-      else

-        ThrowUserErrorException();

-    }

+  }

+  else if (options.Command.CommandType == NCommandType::kHash)

+  {

+    options.Censor.AddPathsToCensor(censorPathMode);

+    options.Censor.ExtendExclude();

+

+    CHashOptions &hashOptions = options.HashOptions;

+    hashOptions.PathMode = censorPathMode;

+    hashOptions.Methods = options.HashMethods;

+    if (parser[NKey::kShareForWrite].ThereIs)

+      hashOptions.OpenShareForWrite = true;

+    hashOptions.StdInMode = options.StdInMode;

+    hashOptions.AltStreamsMode = options.AltStreams.Val;

   }

   else if (options.Command.CommandType == NCommandType::kInfo)

   {

   }

   else

-    ThrowUserErrorException();

-  options.WildcardCensor.ExtendExclude();

+    throw 9815676711;

 }

diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
old mode 100755
new mode 100644
index 491689e..3f4186f
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -3,15 +3,16 @@
 #ifndef __ARCHIVE_COMMAND_LINE_H

 #define __ARCHIVE_COMMAND_LINE_H

 

-#include "Common/CommandLineParser.h"

-#include "Common/Wildcard.h"

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/Wildcard.h"

 

 #include "Extract.h"

+#include "HashCalc.h"

 #include "Update.h"

 

-struct CArchiveCommandLineException: public AString

+struct CArcCmdLineException: public UString

 {

-  CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}

+  CArcCmdLineException(const char *a, const wchar_t *u = NULL);

 };

 

 namespace NCommandType { enum EEnum

@@ -21,35 +22,33 @@
   kDelete,

   kTest,

   kExtract,

-  kFullExtract,

+  kExtractFull,

   kList,

   kBenchmark,

-  kInfo

+  kInfo,

+  kHash,

+  kRename

 };}

 

-namespace NRecursedType { enum EEnum

-{

-  kRecursed,

-  kWildCardOnlyRecursed,

-  kNonRecursed

-};}

-

-struct CArchiveCommand

+struct CArcCommand

 {

   NCommandType::EEnum CommandType;

+

   bool IsFromExtractGroup() const;

   bool IsFromUpdateGroup() const;

-  bool IsTestMode() const { return CommandType == NCommandType::kTest; }

+  bool IsTestCommand() const { return CommandType == NCommandType::kTest; }

   NExtract::NPathMode::EEnum GetPathMode() const;

 };

 

-struct CArchiveCommandLineOptions

+struct CArcCmdLineOptions

 {

   bool HelpMode;

 

   #ifdef _WIN32

   bool LargePages;

   #endif

+  bool CaseSensitiveChange;

+  bool CaseSensitive;

 

   bool IsInTerminal;

   bool IsStdOutTerminal;

@@ -60,10 +59,9 @@
 

   bool YesToAll;

   bool ShowDialog;

-  // NWildcard::CCensor ArchiveWildcardCensor;

-  NWildcard::CCensor WildcardCensor;

+  NWildcard::CCensor Censor;

 

-  CArchiveCommand Command;

+  CArcCommand Command;

   UString ArchiveName;

 

   #ifndef _NO_CRYPTO

@@ -72,39 +70,52 @@
   #endif

 

   bool TechMode;

-  // Extract

-  bool CalcCrc;

+  

+  UStringVector HashMethods;

+

   bool AppendName;

-  UString OutputDir;

-  NExtract::NOverwriteMode::EEnum OverwriteMode;

   UStringVector ArchivePathsSorted;

   UStringVector ArchivePathsFullSorted;

-  CObjectVector<CProperty> ExtractProperties;

+  CObjectVector<CProperty> Properties;

+

+  CExtractOptionsBase ExtractOptions;

+

+  CBoolPair NtSecurity;

+  CBoolPair AltStreams;

+  CBoolPair HardLinks;

+  CBoolPair SymLinks;

 

   CUpdateOptions UpdateOptions;

+  CHashOptions HashOptions;

   UString ArcType;

+  UStringVector ExcludedArcTypes;

   bool EnablePercents;

 

   // Benchmark

   UInt32 NumIterations;

-  UInt32 NumThreads;

-  UInt32 DictionarySize;

-  UString Method;

 

-

-  CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};

+  CArcCmdLineOptions():

+      StdInMode(false),

+      StdOutMode(false),

+      CaseSensitiveChange(false),

+      CaseSensitive(false)

+      {};

 };

 

-class CArchiveCommandLineParser

+class CArcCmdLineParser

 {

   NCommandLineParser::CParser parser;

 public:

-  CArchiveCommandLineParser();

-  void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);

-  void Parse2(CArchiveCommandLineOptions &options);

+  CArcCmdLineParser();

+  void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);

+  void Parse2(CArcCmdLineOptions &options);

 };

 

-void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,

+void EnumerateDirItemsAndSort(

+    bool storeAltStreams,

+    NWildcard::CCensor &censor,

+    NWildcard::ECensorPathMode pathMode,

+    const UString &addPathPrefix,

     UStringVector &sortedPaths,

     UStringVector &sortedFullPaths);

 

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
old mode 100755
new mode 100644
index 2a322c5..315945b
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -2,40 +2,200 @@
 

 #include "StdAfx.h"

 

-#include "Common/ComTry.h"

-#include "Common/Wildcard.h"

+#undef sprintf

+#undef printf

 

-#include "Windows/FileDir.h"

-#include "Windows/FileFind.h"

-#include "Windows/PropVariant.h"

-#include "Windows/PropVariantConversions.h"

+#include "../../../Common/ComTry.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/PropVariant.h"

+#include "../../../Windows/PropVariantConv.h"

+

+#if defined(_WIN32) && !defined(UNDER_CE)  && !defined(_SFX)

+#define _USE_SECURITY_CODE

+#include "../../../Windows/SecurityUtils.h"

+#endif

 

 #include "../../Common/FilePathAutoRename.h"

 

 #include "../Common/ExtractingFilePath.h"

+#include "../Common/PropIDUtils.h"

 

 #include "ArchiveExtractCallback.h"

 

 using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

 

-static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";

-static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";

-static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";

+static const char *kCantAutoRename = "Can not create file with auto name";

+static const char *kCantRenameFile = "Can not rename existing file";

+static const char *kCantDeleteOutputFile = "Can not delete output file";

+static const char *kCantDeleteOutputDir = "Can not delete output folder";

+

+

+#ifndef _SFX

+

+STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  HRESULT result = S_OK;

+  if (_stream)

+    result = _stream->Write(data, size, &size);

+  if (_calculate)

+    _hash->Update(data, size);

+  _size += size;

+  if (processedSize)

+    *processedSize = size;

+  return result;

+}

+

+#endif

+

+#ifdef _USE_SECURITY_CODE

+bool InitLocalPrivileges()

+{

+  NSecurity::CAccessToken token;

+  if (!token.OpenProcessToken(GetCurrentProcess(),

+      TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))

+    return false;

+

+  TOKEN_PRIVILEGES tp;

+ 

+  tp.PrivilegeCount = 1;

+  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

+  

+  if  (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))

+    return false;

+  if (!token.AdjustPrivileges(&tp))

+    return false;

+  return (GetLastError() == ERROR_SUCCESS);

+}

+#endif

+

+#ifdef SUPPORT_LINKS

+

+int CHardLinkNode::Compare(const CHardLinkNode &a) const

+{

+  if (StreamId < a.StreamId) return -1;

+  if (StreamId > a.StreamId) return 1;

+  return MyCompare(INode, a.INode);

+}

+

+HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)

+{

+  h.INode = 0;

+  h.StreamId = (UInt64)(Int64)-1;

+  defined = false;

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetProperty(index, kpidINode, &prop));

+    if (!ConvertPropVariantToUInt64(prop, h.INode))

+      return S_OK;

+  }

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetProperty(index, kpidStreamId, &prop));

+    ConvertPropVariantToUInt64(prop, h.StreamId);

+  }

+  defined = true;

+  return S_OK;

+}

+

+

+HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)

+{

+  _hardLinks.Clear();

+

+  if (!_arc->Ask_INode)

+    return S_OK;

+  

+  IInArchive *archive = _arc->Archive;

+  CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;

+

+  {

+    UInt32 numItems;

+    if (realIndices)

+      numItems = realIndices->Size();

+    else

+    {

+      RINOK(archive->GetNumberOfItems(&numItems));

+    }

+

+    for (UInt32 i = 0; i < numItems; i++)

+    {

+      CHardLinkNode h;

+      bool defined;

+      RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined));

+      if (defined)

+        hardIDs.Add(h);

+    }

+  }

+  

+  hardIDs.Sort2();

+  

+  {

+    // wee keep only items that have 2 or more items

+    unsigned k = 0;

+    unsigned numSame = 1;

+    for (unsigned i = 1; i < hardIDs.Size(); i++)

+    {

+      if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)

+        numSame = 1;

+      else if (++numSame == 2)

+      {

+        if (i - 1 != k)

+          hardIDs[k] = hardIDs[i - 1];

+        k++;

+      }

+    }

+    hardIDs.DeleteFrom(k);

+  }

+  

+  _hardLinks.PrepareLinks();

+  return S_OK;

+}

+

+#endif

+

+CArchiveExtractCallback::CArchiveExtractCallback():

+    WriteCTime(true),

+    WriteATime(true),

+    WriteMTime(true),

+    _multiArchives(false)

+{

+  LocalProgressSpec = new CLocalProgress();

+  _localProgress = LocalProgressSpec;

+

+  #ifdef _USE_SECURITY_CODE

+  _saclEnabled = InitLocalPrivileges();

+  #endif

+}

 

 void CArchiveExtractCallback::Init(

+    const CExtractNtOptions &ntOptions,

     const NWildcard::CCensorNode *wildcardCensor,

     const CArc *arc,

     IFolderArchiveExtractCallback *extractCallback2,

-    bool stdOutMode, bool testMode, bool crcMode,

-    const UString &directoryPath,

+    bool stdOutMode, bool testMode,

+    const FString &directoryPath,

     const UStringVector &removePathParts,

     UInt64 packSize)

 {

+  _extractedFolderPaths.Clear();

+  _extractedFolderIndices.Clear();

+  

+  #ifdef SUPPORT_LINKS

+  _hardLinks.Clear();

+  #endif

+

+  _ntOptions = ntOptions;

   _wildcardCensor = wildcardCensor;

 

   _stdOutMode = stdOutMode;

   _testMode = testMode;

-  _crcMode = crcMode;

   _unpTotal = 1;

   _packTotal = packSize;

 

@@ -43,14 +203,31 @@
   _compressProgress.Release();

   _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);

 

+  #ifndef _SFX

+

+  _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);

+  if (ExtractToStreamCallback)

+  {

+    Int32 useStreams = 0;

+    if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)

+      useStreams = 0;

+    if (useStreams == 0)

+      ExtractToStreamCallback.Release();

+  }

+  

+  #endif

+

   LocalProgressSpec->Init(extractCallback2, true);

   LocalProgressSpec->SendProgress = false;

-

  

   _removePathParts = removePathParts;

+  _baseParentFolder = (UInt32)(Int32)-1;

+  _use_baseParentFolder_mode = false;

+

   _arc = arc;

   _directoryPath = directoryPath;

-  NFile::NName::NormalizeDirPathPrefix(_directoryPath);

+  NName::NormalizeDirPathPrefix(_directoryPath);

+  NDir::MyGetFullPathName(directoryPath, _directoryPathFull);

 }

 

 STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)

@@ -107,15 +284,48 @@
   COM_TRY_END

 }

 

-void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)

+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')

+

+static inline bool IsDriveName(const UString &s)

 {

-  fullPath = _directoryPath;

-  for (int i = 0; i < dirPathParts.Size(); i++)

+  return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]);

+}

+

+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)

+{

+  bool isAbsPath = false;

+  

+  if (!dirPathParts.IsEmpty())

+  {

+    const UString &s = dirPathParts[0];

+    if (s.IsEmpty())

+      isAbsPath = true;

+    #ifdef _WIN32

+    else

+    {

+      if (dirPathParts.Size() > 1 && IsDriveName(s))

+        isAbsPath = true;

+    }

+    #endif

+  }

+  

+  if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)

+    fullPath.Empty();

+  else

+    fullPath = _directoryPath;

+

+  FOR_VECTOR (i, dirPathParts)

   {

     if (i > 0)

-      fullPath += wchar_t(NFile::NName::kDirDelimiter);

-    fullPath += dirPathParts[i];

-    NFile::NDirectory::MyCreateDirectory(fullPath);

+      fullPath += FCHAR_PATH_SEPARATOR;

+    const UString &s = dirPathParts[i];

+    fullPath += us2fs(s);

+    #ifdef _WIN32

+    if (_pathMode == NExtract::NPathMode::kAbsPaths)

+      if (i == 0 && IsDriveName(s))

+        continue;

+    #endif

+    CreateDir(fullPath);

   }

 }

 

@@ -136,23 +346,100 @@
 

 HRESULT CArchiveExtractCallback::GetUnpackSize()

 {

-  NCOM::CPropVariant prop;

-  RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop));

-  _curSizeDefined = (prop.vt != VT_EMPTY);

-  if (_curSizeDefined)

-    _curSize = ConvertPropVariantToUInt64(prop);

-  return S_OK;

+  return _arc->GetItemSize(_index, _curSize, _curSizeDefined);

 }

 

+HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)

+{

+  return _extractCallback2->MessageError(

+      UString(L"ERROR: ") +

+      GetUnicodeString(message) + L": " + fs2us(path));

+}

+

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

+}

+

+#ifndef _SFX

+

+STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)

+{

+  if (propID == kpidName)

+  {

+    COM_TRY_BEGIN

+    NCOM::CPropVariant prop = Name.Ptr();

+    prop.Detach(value);

+    return S_OK;

+    COM_TRY_END

+  }

+  return Arc->Archive->GetProperty(IndexInArc, propID, value);

+}

+

+#endif

+

+

+#ifdef SUPPORT_LINKS

+

+static UString GetDirPrefixOf(const UString &src)

+{

+  UString s = src;

+  if (!s.IsEmpty())

+  {

+    if (s.Back() == WCHAR_PATH_SEPARATOR)

+      s.DeleteBack();

+    int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);

+    s.DeleteFrom(pos + 1);

+  }

+  return s;

+}

+

+static bool IsSafePath(const UString &path)

+{

+  UStringVector parts;

+  SplitPathToParts(path, parts);

+  int level = 0;

+  FOR_VECTOR(i, parts)

+  {

+    const UString &s = parts[i];

+    if (s.IsEmpty())

+      continue;

+    if (s == L".")

+      continue;

+    if (s == L"..")

+    {

+      if (level <= 0)

+        return false;

+      level--;

+    }

+    else

+      level++;

+  }

+  return level > 0;

+}

+

+#endif

+

+

 STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)

 {

   COM_TRY_BEGIN

-  _crcStream.Release();

+

   *outStream = 0;

+

+  #ifndef _SFX

+  if (_hashStream)

+    _hashStreamSpec->ReleaseStream();

+  _hashStreamWasUsed = false;

+  #endif

+

   _outFileStream.Release();

 

   _encrypted = false;

   _isSplit = false;

+  _isAltStream = false;

   _curSize = 0;

   _curSizeDefined = false;

   _index = index;

@@ -161,7 +448,7 @@
 

   IInArchive *archive = _arc->Archive;

   RINOK(_arc->GetItemPath(index, fullPath));

-  RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir));

+  RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir));

 

   _filePath = fullPath;

 

@@ -176,26 +463,220 @@
       _isSplit = true;

     }

   }

+

+  #ifdef SUPPORT_LINKS

+  

+  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

+    }

+    else if (prop.vt == VT_EMPTY)

+    {

+      // linkPath.Empty();

+    }

+    else

+      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

+    }

+    else if (prop.vt == VT_EMPTY)

+    {

+      // linkPath.Empty();

+    }

+    else

+      return E_FAIL;

+  }

+

+  bool isOkReparse = false;

+

+  if (linkPath.IsEmpty() && _arc->GetRawProps)

+  {

+    const void *data;

+    UInt32 dataSize;

+    UInt32 propType;

+    _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);

+    if (dataSize != 0)

+    {

+      if (propType != NPropDataType::kRaw)

+        return E_FAIL;

+      UString s;

+      CReparseAttr reparse;

+      isOkReparse = reparse.Parse((const Byte *)data, dataSize);

+      if (isOkReparse)

+      {

+        isHardLink = false;

+        linkPath = reparse.GetPath();

+        isJunction = reparse.IsMountPoint();

+        isRelative = reparse.IsRelative();

+        #ifndef _WIN32

+        linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', );

+        #endif

+      }

+    }

+  }

+

+  if (!linkPath.IsEmpty())

+  {

+    #ifdef _WIN32

+    linkPath.Replace('/', WCHAR_PATH_SEPARATOR);

+    #endif

     

-  RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted));

+    for (;;)

+    // while (NName::IsAbsolutePath(linkPath))

+    {

+      unsigned n = NName::GetRootPrefixSize(linkPath);

+      if (n == 0)

+        break;

+      isRelative = false;

+      linkPath.DeleteFrontal(n);

+    }

+  }

+

+  if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0)

+  {

+    UStringVector pathParts;

+    SplitPathToParts(linkPath, pathParts);

+    bool badPrefix = false;

+    FOR_VECTOR (i, _removePathParts)

+    {

+      if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)

+      {

+        badPrefix = true;

+        break;

+      }

+    }

+    if (!badPrefix)

+      pathParts.DeleteFrontal(_removePathParts.Size());

+    linkPath = MakePathNameFromParts(pathParts);

+  }

+

+  #endif

+  

+  RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted));

 

   RINOK(GetUnpackSize());

 

+  RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream));

+

+  if (!_ntOptions.AltStreams.Val && _isAltStream)

+    return S_OK;

+

   if (_wildcardCensor)

   {

-    if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir))

+    if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir))

       return S_OK;

   }

 

-  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)

-  {

-    if (_stdOutMode)

-    {

-      CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;

-      *outStream = outStreamLoc.Detach();

-      return S_OK;

-    }

 

+  UStringVector pathParts;

+

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

+  }

+  else

+  {

+    SplitPathToParts(fullPath, pathParts);

+    

+    if (pathParts.IsEmpty())

+      return E_FAIL;

+    unsigned numRemovePathParts = 0;

+    

+    switch (_pathMode)

+    {

+      case NExtract::NPathMode::kCurPaths:

+      {

+        bool badPrefix = false;

+        if (pathParts.Size() <= _removePathParts.Size())

+          badPrefix = true;

+        else

+        {

+          FOR_VECTOR (i, _removePathParts)

+          {

+            if (!_removePathParts[i].IsEqualToNoCase(pathParts[i]))

+            {

+              badPrefix = true;

+              break;

+            }

+          }

+        }

+        if (badPrefix)

+        {

+          if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)

+            return E_FAIL;

+        }

+        else

+          numRemovePathParts = _removePathParts.Size();

+        break;

+      }

+      case NExtract::NPathMode::kNoPaths:

+      {

+        numRemovePathParts = pathParts.Size() - 1;

+        break;

+      }

+      /*

+      case NExtract::NPathMode::kFullPaths:

+      case NExtract::NPathMode::kAbsPaths:

+        break;

+      */

+    }

+    

+    pathParts.DeleteFrontal(numRemovePathParts);

+  }

+

+  #ifndef _SFX

+

+  if (ExtractToStreamCallback)

+  {

+    if (!GetProp)

+    {

+      GetProp_Spec = new CGetProp;

+      GetProp = GetProp_Spec;

+    }

+    GetProp_Spec->Arc = _arc;

+    GetProp_Spec->IndexInArc = index;

+    GetProp_Spec->Name = MakePathNameFromParts(pathParts);

+

+    return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp);

+  }

+

+  #endif

+

+  CMyComPtr<ISequentialOutStream> outStreamLoc;

+

+if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)

+{

+  if (_stdOutMode)

+  {

+    outStreamLoc = new CStdOutFileStream;

+  }

+  else

+  {

     {

       NCOM::CPropVariant prop;

       RINOK(archive->GetProperty(index, kpidAttrib, &prop));

@@ -217,35 +698,15 @@
     bool isAnti = false;

     RINOK(_arc->IsItemAnti(index, isAnti));

 

-    UStringVector pathParts;

-    SplitPathToParts(fullPath, pathParts);

-    

-    if (pathParts.IsEmpty())

-      return E_FAIL;

-    int numRemovePathParts = 0;

-    switch(_pathMode)

-    {

-      case NExtract::NPathMode::kFullPathnames:

-        break;

-      case NExtract::NPathMode::kCurrentPathnames:

-      {

-        numRemovePathParts = _removePathParts.Size();

-        if (pathParts.Size() <= numRemovePathParts)

-          return E_FAIL;

-        for (int i = 0; i < numRemovePathParts; i++)

-          if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)

-            return E_FAIL;

-        break;

-      }

-      case NExtract::NPathMode::kNoPathnames:

-      {

-        numRemovePathParts = pathParts.Size() - 1;

-        break;

-      }

-    }

-    pathParts.Delete(0, numRemovePathParts);

-    MakeCorrectPath(pathParts);

+    bool replace = _isAltStream ?

+        _ntOptions.ReplaceColonForAltStream :

+        !_ntOptions.WriteToAltStreamIfColon;

+

+    if (_pathMode != NExtract::NPathMode::kAbsPaths)

+      MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace);

+    Correct_IfEmptyLastPart(pathParts);

     UString processedPath = MakePathNameFromParts(pathParts);

+    

     if (!isAnti)

     {

       if (!_fi.IsDir)

@@ -256,139 +717,270 @@
     

       if (!pathParts.IsEmpty())

       {

-        UString fullPathNew;

+        FString fullPathNew;

         CreateComplexDirectory(pathParts, fullPathNew);

         if (_fi.IsDir)

-          NFile::NDirectory::SetDirTime(fullPathNew,

+        {

+          _extractedFolderPaths.Add(fullPathNew);

+          _extractedFolderIndices.Add(index);

+          SetDirTime(fullPathNew,

             (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,

             (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,

             (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));

+        }

       }

     }

 

 

-    UString fullProcessedPath = _directoryPath + processedPath;

+    FString fullProcessedPath = us2fs(processedPath);

+    if (_pathMode != NExtract::NPathMode::kAbsPaths ||

+        !NName::IsAbsolutePath(processedPath))

+      fullProcessedPath = _directoryPath + fullProcessedPath;

 

     if (_fi.IsDir)

     {

       _diskFilePath = fullProcessedPath;

       if (isAnti)

-        NFile::NDirectory::MyRemoveDirectory(_diskFilePath);

-      return S_OK;

+        RemoveDir(_diskFilePath);

+      #ifdef SUPPORT_LINKS

+      if (linkPath.IsEmpty())

+      #endif

+        return S_OK;

     }

-

-    if (!_isSplit)

+    else if (!_isSplit)

     {

-    NFile::NFind::CFileInfoW fileInfo;

+    NFind::CFileInfo fileInfo;

     if (fileInfo.Find(fullProcessedPath))

     {

-      switch(_overwriteMode)

+      switch (_overwriteMode)

       {

-        case NExtract::NOverwriteMode::kSkipExisting:

+        case NExtract::NOverwriteMode::kSkip:

           return S_OK;

-        case NExtract::NOverwriteMode::kAskBefore:

+        case NExtract::NOverwriteMode::kAsk:

         {

+          int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));

+          #ifdef _WIN32

+          int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));

+          slashPos = MyMax(slashPos, slash1Pos);

+          #endif

+          FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;

+

           Int32 overwiteResult;

           RINOK(_extractCallback2->AskOverwrite(

-              fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath,

+              fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath,

               _fi.MTimeDefined ? &_fi.MTime : NULL,

               _curSizeDefined ? &_curSize : NULL,

               &overwiteResult))

 

-          switch(overwiteResult)

+          switch (overwiteResult)

           {

-            case NOverwriteAnswer::kCancel:

-              return E_ABORT;

-            case NOverwriteAnswer::kNo:

-              return S_OK;

-            case NOverwriteAnswer::kNoToAll:

-              _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;

-              return S_OK;

-            case NOverwriteAnswer::kYesToAll:

-              _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;

-              break;

-            case NOverwriteAnswer::kYes:

-              break;

-            case NOverwriteAnswer::kAutoRename:

-              _overwriteMode = NExtract::NOverwriteMode::kAutoRename;

-              break;

+            case NOverwriteAnswer::kCancel: return E_ABORT;

+            case NOverwriteAnswer::kNo: return S_OK;

+            case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;

+            case NOverwriteAnswer::kYes: break;

+            case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break;

+            case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break;

             default:

               return E_FAIL;

           }

         }

       }

-      if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)

+      if (_overwriteMode == NExtract::NOverwriteMode::kRename)

       {

         if (!AutoRenamePath(fullProcessedPath))

         {

-          UString message = UString(kCantAutoRename) + fullProcessedPath;

-          RINOK(_extractCallback2->MessageError(message));

+          RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));

           return E_FAIL;

         }

       }

-      else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)

+      else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)

       {

-        UString existPath = fullProcessedPath;

+        FString existPath = fullProcessedPath;

         if (!AutoRenamePath(existPath))

         {

-          UString message = kCantAutoRename + fullProcessedPath;

-          RINOK(_extractCallback2->MessageError(message));

+          RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));

           return E_FAIL;

         }

-        if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))

+        // MyMoveFile can raname folders. So it's OK to use it folders too

+        if (!MyMoveFile(fullProcessedPath, existPath))

         {

-          UString message = UString(kCantRenameFile) + fullProcessedPath;

-          RINOK(_extractCallback2->MessageError(message));

+          RINOK(SendMessageError(kCantRenameFile, fullProcessedPath));

           return E_FAIL;

         }

       }

       else

-        if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))

+      {

+        if (fileInfo.IsDir())

         {

-          UString message = UString(kCantDeleteOutputFile) +  fullProcessedPath;

-          RINOK(_extractCallback2->MessageError(message));

+          // do we need to delete all files in folder?

+          if (!RemoveDir(fullProcessedPath))

+          {

+            RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath));

+            return S_OK;

+          }

+        }

+        else if (!DeleteFileAlways(fullProcessedPath))

+        {

+          RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath));

           return S_OK;

           // return E_FAIL;

         }

-    }

-    }

-    if (!isAnti)

-    {

-      _outFileStreamSpec = new COutFileStream;

-      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

-      if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))

-      {

-        // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)

-        {

-          UString message = L"can not open output file " + fullProcessedPath;

-          RINOK(_extractCallback2->MessageError(message));

-          return S_OK;

-        }

       }

-      if (_isSplit)

-      {

-        RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));

-      }

-      _outFileStream = outStreamLoc;

-      *outStream = outStreamLoc.Detach();

+    }

     }

     _diskFilePath = fullProcessedPath;

+    

+

+    if (!isAnti)

+    {

+      #ifdef SUPPORT_LINKS

+

+      if (!linkPath.IsEmpty())

+      {

+        #ifndef UNDER_CE

+

+        UString relatPath;

+        if (isRelative)

+          relatPath = GetDirPrefixOf(_filePath);

+        relatPath += linkPath;

+        

+        if (!IsSafePath(relatPath))

+        {

+          RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath)));

+        }

+        else

+        {

+          FString existPath;

+          if (isHardLink || !isRelative)

+          {

+            if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath))

+            {

+              RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));

+            }

+          }

+          else

+          {

+            existPath = us2fs(linkPath);

+          }

+          

+          if (!existPath.IsEmpty())

+          {

+            if (isHardLink)

+            {

+              if (!MyCreateHardLink(fullProcessedPath, existPath))

+              {

+                RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));

+                // return S_OK;

+              }

+            }

+            else if (_ntOptions.SymLinks.Val)

+            {

+              // bool isSymLink = true; // = false for junction

+              if (_fi.IsDir && !isRelative)

+              {

+                // if it's before Vista we use Junction Point

+                // isJunction = true;

+                // convertToAbs = true;

+              }

+              

+              CByteBuffer data;

+              if (FillLinkData(data, fs2us(existPath), !isJunction))

+              {

+                CReparseAttr attr;

+                if (!attr.Parse(data, data.Size()))

+                {

+                  return E_FAIL; // "Internal conversion error";

+                }

+                

+                if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size()))

+                {

+                  RINOK(SendMessageError("Can not set reparse data", fullProcessedPath));

+                }

+              }

+            }

+          }

+        }

+        

+        #endif

+      }

+      else

+      #endif // SUPPORT_LINKS

+      {

+        bool needWriteFile = true;

+        

+        #ifdef SUPPORT_LINKS

+        if (!_hardLinks.IDs.IsEmpty())

+        {

+          CHardLinkNode h;

+          bool defined;

+          RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));

+          if (defined)

+          {

+            {

+              int linkIndex = _hardLinks.IDs.FindInSorted2(h);

+              if (linkIndex >= 0)

+              {

+                FString &hl = _hardLinks.Links[linkIndex];

+                if (hl.IsEmpty())

+                  hl = fullProcessedPath;

+                else

+                {

+                  if (!MyCreateHardLink(fullProcessedPath, hl))

+                  {

+                    RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl));

+                    return S_OK;

+                  }

+                  needWriteFile = false;

+                }

+              }

+            }

+          }

+        }

+        #endif

+        

+        if (needWriteFile)

+        {

+          _outFileStreamSpec = new COutFileStream;

+          CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

+          if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))

+          {

+            // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)

+            {

+              RINOK(SendMessageError("Can not open output file ", fullProcessedPath));

+              return S_OK;

+            }

+          }

+          if (_isSplit)

+          {

+            RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));

+          }

+          _outFileStream = outStreamLoc;

+        }

+      }

+    }

+    

+    outStreamLoc = _outFileStream;

   }

-  else

+}

+

+  #ifndef _SFX

+

+  if (_hashStream)

   {

-    *outStream = NULL;

+    if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||

+        askExtractMode == NArchive::NExtract::NAskMode::kTest)

+    {

+      _hashStreamSpec->SetStream(outStreamLoc);

+      outStreamLoc = _hashStream;

+      _hashStreamSpec->Init(true);

+      _hashStreamWasUsed = true;

+    }

   }

-  if (_crcMode)

-  {

-    _crcStreamSpec = new COutStreamWithCRC;

-    _crcStream = _crcStreamSpec;

-    CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec;

-    _crcStreamSpec->SetStream(*outStream);

-    if (*outStream)

-      (*outStream)->Release();

-    *outStream = crcStream.Detach();

-    _crcStreamSpec->Init(true);

-  }

+

+  #endif

+

+  if (outStreamLoc)

+    *outStream = outStreamLoc.Detach();

   return S_OK;

   COM_TRY_END

 }

@@ -396,6 +988,12 @@
 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)

 {

   COM_TRY_BEGIN

+

+  #ifndef _SFX

+  if (ExtractToStreamCallback)

+    return ExtractToStreamCallback->PrepareOperation7(askExtractMode);

+  #endif

+  

   _extractMode = false;

   switch (askExtractMode)

   {

@@ -414,24 +1012,25 @@
 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)

 {

   COM_TRY_BEGIN

-  switch(operationResult)

+

+  #ifndef _SFX

+  if (ExtractToStreamCallback)

+    return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted);

+  #endif

+

+  #ifndef _SFX

+

+  if (_hashStreamWasUsed)

   {

-    case NArchive::NExtract::NOperationResult::kOK:

-    case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

-    case NArchive::NExtract::NOperationResult::kCRCError:

-    case NArchive::NExtract::NOperationResult::kDataError:

-      break;

-    default:

-      _outFileStream.Release();

-      return E_FAIL;

-  }

-  if (_crcStream)

-  {

-    CrcSum += _crcStreamSpec->GetCRC();

-    _curSize = _crcStreamSpec->GetSize();

+    _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath);

+    _curSize = _hashStreamSpec->GetSize();

     _curSizeDefined = true;

-    _crcStream.Release();

+    _hashStreamSpec->ReleaseStream();

+    _hashStreamWasUsed = false;

   }

+

+  #endif

+

   if (_outFileStream)

   {

     _outFileStreamSpec->SetTime(

@@ -443,17 +1042,48 @@
     RINOK(_outFileStreamSpec->Close());

     _outFileStream.Release();

   }

+  

+  #ifdef _USE_SECURITY_CODE

+  if (_ntOptions.NtSecurity.Val && _arc->GetRawProps)

+  {

+    const void *data;

+    UInt32 dataSize;

+    UInt32 propType;

+    _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);

+    if (dataSize != 0)

+    {

+      if (propType != NPropDataType::kRaw)

+        return E_FAIL;

+      if (CheckNtSecure((const Byte *)data, dataSize))

+      {

+        SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;

+        if (_saclEnabled)

+          securInfo |= SACL_SECURITY_INFORMATION;

+        ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data);

+      }

+    }

+  }

+  #endif

+

   if (!_curSizeDefined)

     GetUnpackSize();

   if (_curSizeDefined)

-    UnpackSize += _curSize;

+  {

+    if (_isAltStream)

+      AltStreams_UnpackSize += _curSize;

+    else

+      UnpackSize += _curSize;

+  }

+    

   if (_fi.IsDir)

     NumFolders++;

+  else if (_isAltStream)

+    NumAltStreams++;

   else

     NumFiles++;

 

   if (_extractMode && _fi.AttribDefined)

-    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib);

+    SetFileAttrib(_diskFilePath, _fi.Attrib);

   RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));

   return S_OK;

   COM_TRY_END

@@ -486,3 +1116,76 @@
   COM_TRY_END

 }

 

+

+struct CExtrRefSortPair

+{

+  int Len;

+  int Index;

+

+  int Compare(const CExtrRefSortPair &a) const;

+};

+

+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

+

+int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const

+{

+  RINOZ(-MyCompare(Len, a.Len));

+  return MyCompare(Index, a.Index);

+}

+

+static int GetNumSlashes(const FChar *s)

+{

+  for (int numSlashes = 0;;)

+  {

+    FChar c = *s++;

+    if (c == 0)

+      return numSlashes;

+    if (

+        #ifdef _WIN32

+        c == FTEXT('\\') ||

+        #endif

+        c == FTEXT('/'))

+      numSlashes++;

+  }

+}

+

+HRESULT CArchiveExtractCallback::SetDirsTimes()

+{

+  CRecordVector<CExtrRefSortPair> pairs;

+  pairs.ClearAndSetSize(_extractedFolderPaths.Size());

+  unsigned i;

+  

+  for (i = 0; i < _extractedFolderPaths.Size(); i++)

+  {

+    CExtrRefSortPair &pair = pairs[i];

+    pair.Index = i;

+    pair.Len = GetNumSlashes(_extractedFolderPaths[i]);

+  }

+  

+  pairs.Sort2();

+  

+  for (i = 0; i < pairs.Size(); i++)

+  {

+    int pairIndex = pairs[i].Index;

+    int index = _extractedFolderIndices[pairIndex];

+

+    FILETIME CTime;

+    FILETIME ATime;

+    FILETIME MTime;

+  

+    bool CTimeDefined;

+    bool ATimeDefined;

+    bool MTimeDefined;

+

+    RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));

+    RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));

+    RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));

+

+    // printf("\n%S", _extractedFolderPaths[pairIndex]);

+    SetDirTime(_extractedFolderPaths[pairIndex],

+      (WriteCTime && CTimeDefined) ? &CTime : NULL,

+      (WriteATime && ATimeDefined) ? &ATime : NULL,

+      (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
old mode 100755
new mode 100644
index b7a6a47..7000532
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -3,8 +3,8 @@
 #ifndef __ARCHIVE_EXTRACT_CALLBACK_H

 #define __ARCHIVE_EXTRACT_CALLBACK_H

 

-#include "Common/MyCom.h"

-#include "Common/Wildcard.h"

+#include "../../../Common/MyCom.h"

+#include "../../../Common/Wildcard.h"

 

 #include "../../IPassword.h"

 

@@ -13,12 +13,117 @@
 

 #include "../../Archive/IArchive.h"

 

-#include "../../Archive/Common/OutStreamWithCRC.h"

-

 #include "ExtractMode.h"

 #include "IFileExtractCallback.h"

 #include "OpenArchive.h"

 

+#include "HashCalc.h"

+

+#ifndef _SFX

+

+class COutStreamWithHash:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+  bool _calculate;

+public:

+  IHashCalc *_hash;

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init(bool calculate = true)

+  {

+    InitCRC();

+    _size = 0;

+    _calculate = calculate;

+  }

+  void EnableCalc(bool calculate) { _calculate = calculate; }

+  void InitCRC() { _hash->InitForNewFile(); }

+  UInt64 GetSize() const { return _size; }

+};

+

+#endif

+

+struct CExtractNtOptions

+{

+  CBoolPair NtSecurity;

+  CBoolPair SymLinks;

+  CBoolPair HardLinks;

+  CBoolPair AltStreams;

+  bool ReplaceColonForAltStream;

+  bool WriteToAltStreamIfColon;

+

+  CExtractNtOptions():

+      ReplaceColonForAltStream(false),

+      WriteToAltStreamIfColon(false)

+  {

+    SymLinks.Val = true;

+    HardLinks.Val = true;

+    AltStreams.Val = true;

+  }

+};

+

+#ifndef _SFX

+

+class CGetProp:

+  public IGetProp,

+  public CMyUnknownImp

+{

+public:

+  const CArc *Arc;

+  UInt32 IndexInArc;

+  UString Name; // relative path

+

+  MY_UNKNOWN_IMP1(IGetProp)

+  INTERFACE_IGetProp(;)

+};

+

+#endif

+

+#ifndef _SFX

+#ifndef UNDER_CE

+

+#define SUPPORT_LINKS

+

+#endif

+#endif

+

+

+#ifdef SUPPORT_LINKS

+

+struct CHardLinkNode

+{

+  UInt64 StreamId;

+  UInt64 INode;

+

+  int Compare(const CHardLinkNode &a) const;

+};

+

+class CHardLinks

+{

+public:

+  CRecordVector<CHardLinkNode> IDs;

+  CObjectVector<FString> Links;

+

+  void Clear()

+  {

+    IDs.Clear();

+    Links.Clear();

+  }

+

+  void PrepareLinks()

+  {

+    while (Links.Size() < IDs.Size())

+      Links.AddNew();

+  }

+};

+

+#endif

+

 class CArchiveExtractCallback:

   public IArchiveExtractCallback,

   // public IArchiveVolumeExtractCallback,

@@ -27,18 +132,30 @@
   public CMyUnknownImp

 {

   const CArc *_arc;

+  CExtractNtOptions _ntOptions;

+

   const NWildcard::CCensorNode *_wildcardCensor;

   CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;

   CMyComPtr<ICompressProgressInfo> _compressProgress;

   CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;

-  UString _directoryPath;

+  FString _directoryPath;

+  FString _directoryPathFull;

   NExtract::NPathMode::EEnum _pathMode;

   NExtract::NOverwriteMode::EEnum _overwriteMode;

 

-  UString _diskFilePath;

+  #ifndef _SFX

+

+  CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;

+  CGetProp *GetProp_Spec;

+  CMyComPtr<IGetProp> GetProp;

+  

+  #endif

+

+  FString _diskFilePath;

   UString _filePath;

   UInt64 _position;

   bool _isSplit;

+  bool _isAltStream;

 

   bool _extractMode;

 

@@ -69,32 +186,49 @@
   COutFileStream *_outFileStreamSpec;

   CMyComPtr<ISequentialOutStream> _outFileStream;

 

-  COutStreamWithCRC *_crcStreamSpec;

-  CMyComPtr<ISequentialOutStream> _crcStream;

+  #ifndef _SFX

+  

+  COutStreamWithHash *_hashStreamSpec;

+  CMyComPtr<ISequentialOutStream> _hashStream;

+  bool _hashStreamWasUsed;

+  

+  #endif

 

   UStringVector _removePathParts;

+  bool _use_baseParentFolder_mode;

+  UInt32 _baseParentFolder;

 

   bool _stdOutMode;

   bool _testMode;

-  bool _crcMode;

   bool _multiArchives;

 

   CMyComPtr<ICompressProgressInfo> _localProgress;

   UInt64 _packTotal;

   UInt64 _unpTotal;

 

-  void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);

+  FStringVector _extractedFolderPaths;

+  CRecordVector<UInt32> _extractedFolderIndices;

+

+  #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)

+  bool _saclEnabled;

+  #endif

+

+  void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);

   HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);

   HRESULT GetUnpackSize();

 

+  HRESULT SendMessageError(const char *message, const FString &path);

+  HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);

+

 public:

 

   CLocalProgress *LocalProgressSpec;

 

   UInt64 NumFolders;

   UInt64 NumFiles;

+  UInt64 NumAltStreams;

   UInt64 UnpackSize;

-  UInt32 CrcSum;

+  UInt64 AltStreams_UnpackSize;

   

   MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)

   // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)

@@ -108,15 +242,7 @@
 

   STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

-  CArchiveExtractCallback():

-      WriteCTime(true),

-      WriteATime(true),

-      WriteMTime(true),

-      _multiArchives(false)

-  {

-    LocalProgressSpec = new CLocalProgress();

-    _localProgress = LocalProgressSpec;

-  }

+  CArchiveExtractCallback();

 

   void InitForMulti(bool multiArchives,

       NExtract::NPathMode::EEnum pathMode,

@@ -125,19 +251,49 @@
     _multiArchives = multiArchives;

     _pathMode = pathMode;

     _overwriteMode = overwriteMode;

-    NumFolders = NumFiles = UnpackSize = 0;

-    CrcSum = 0;

+    NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;

   }

 

+  #ifndef _SFX

+

+  void SetHashMethods(IHashCalc *hash)

+  {

+    if (!hash)

+      return;

+    _hashStreamSpec = new COutStreamWithHash;

+    _hashStream = _hashStreamSpec;

+    _hashStreamSpec->_hash = hash;

+  }

+

+  #endif

+

   void Init(

+      const CExtractNtOptions &ntOptions,

       const NWildcard::CCensorNode *wildcardCensor,

       const CArc *arc,

       IFolderArchiveExtractCallback *extractCallback2,

-      bool stdOutMode, bool testMode, bool crcMode,

-      const UString &directoryPath,

+      bool stdOutMode, bool testMode,

+      const FString &directoryPath,

       const UStringVector &removePathParts,

       UInt64 packSize);

 

+  #ifdef SUPPORT_LINKS

+private:

+  CHardLinks _hardLinks;

+public:

+  // call PrepareHardLinks() after Init()

+  HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items

+  #endif

+

+  // call it after Init()

+

+  void SetBaseParentFolderIndex(UInt32 indexInArc)

+  {

+    _use_baseParentFolder_mode = true;

+    _baseParentFolder = indexInArc;

+  }

+

+  HRESULT SetDirsTimes();

 };

 

 #endif

diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
old mode 100755
new mode 100644
index c62c7f1..cabc955
--- a/CPP/7zip/UI/Common/ArchiveName.cpp
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -2,26 +2,42 @@
 

 #include "StdAfx.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/FileFind.h"

+#include "../../../Windows/FileDir.h"

 

 #include "ExtractingFilePath.h"

+#include "ArchiveName.h"

 

 using namespace NWindows;

 

-static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName)

+UString CreateArchiveName(const NFile::NFind::CFileInfo fileInfo, bool keepName)

 {

-  UString resultName = L"Archive";

+  FString resultName = fileInfo.Name;

+  if (!fileInfo.IsDir() && !keepName)

+  {

+    int dotPos = resultName.ReverseFind(FTEXT('.'));

+    if (dotPos > 0)

+    {

+      FString archiveName2 = resultName.Left(dotPos);

+      if (archiveName2.ReverseFind(FTEXT('.')) < 0)

+        resultName = archiveName2;

+    }

+  }

+  return GetCorrectFsPath(fs2us(resultName));

+}

+

+static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName)

+{

+  FString resultName = FTEXT("Archive");

   if (fromPrev)

   {

-    UString dirPrefix;

-    if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))

+    FString dirPrefix;

+    if (NFile::NDir::GetOnlyDirPrefix(srcName, dirPrefix))

     {

-      if (dirPrefix.Length() > 0)

-        if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR)

+      if (dirPrefix.Len() > 0)

+        if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR)

         {

-          dirPrefix.Delete(dirPrefix.Length() - 1);

-          NFile::NFind::CFileInfoW fileInfo;

+          dirPrefix.DeleteBack();

+          NFile::NFind::CFileInfo fileInfo;

           if (fileInfo.Find(dirPrefix))

             resultName = fileInfo.Name;

         }

@@ -29,7 +45,7 @@
   }

   else

   {

-    NFile::NFind::CFileInfoW fileInfo;

+    NFile::NFind::CFileInfo fileInfo;

     if (!fileInfo.Find(srcName))

       // return resultName;

       return srcName;

@@ -39,8 +55,8 @@
       int dotPos = resultName.ReverseFind('.');

       if (dotPos > 0)

       {

-        UString archiveName2 = resultName.Left(dotPos);

-        if (archiveName2.ReverseFind('.') < 0)

+        FString archiveName2 = resultName.Left(dotPos);

+        if (archiveName2.ReverseFind(FTEXT('.')) < 0)

           resultName = archiveName2;

       }

     }

@@ -50,5 +66,5 @@
 

 UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)

 {

-  return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName));

+  return GetCorrectFsPath(fs2us(CreateArchiveName2(us2fs(srcName), fromPrev, keepName)));

 }

diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
old mode 100755
new mode 100644
index ba18eea..e67cf1e
--- a/CPP/7zip/UI/Common/ArchiveName.h
+++ b/CPP/7zip/UI/Common/ArchiveName.h
@@ -1,10 +1,13 @@
 // ArchiveName.h

 

-#ifndef __ARCHIVENAME_H

-#define __ARCHIVENAME_H

+#ifndef __ARCHIVE_NAME_H

+#define __ARCHIVE_NAME_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

+

+#include "../../../Windows/FileFind.h"

 

 UString CreateArchiveName(const UString &srcName, 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
old mode 100755
new mode 100644
index bb8b6cc..f268dd9
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -2,10 +2,10 @@
 

 #include "StdAfx.h"

 

-#include "Common/StringConvert.h"

-#include "Common/ComTry.h"

+#include "../../../Common/ComTry.h"

 

-#include "Windows/PropVariant.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/PropVariant.h"

 

 #include "../../Common/FileStreams.h"

 

@@ -60,41 +60,32 @@
   COM_TRY_END

 }

 

-int COpenCallbackImp::FindName(const UString &name)

-{

-  for (int i = 0; i < FileNames.Size(); i++)

-    if (name.CompareNoCase(FileNames[i]) == 0)

-      return i;

-  return -1;

-}

-

 struct CInFileStreamVol: public CInFileStream

 {

-  UString Name;

+  int FileNameIndex;

   COpenCallbackImp *OpenCallbackImp;

   CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;

+ 

   ~CInFileStreamVol()

   {

     if (OpenCallbackRef)

-    {

-      int index = OpenCallbackImp->FindName(Name);

-      if (index >= 0)

-        OpenCallbackImp->FileNames.Delete(index);

-    }

+      OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;

   }

 };

 

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

   }

-  *inStream = NULL;

-  UString fullPath = _folderPrefix + name;

+  FString fullPath;

+  if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath))

+    return S_FALSE;

   if (!_fileInfo.Find(fullPath))

     return S_FALSE;

   if (_fileInfo.IsDir())

@@ -103,12 +94,14 @@
   CMyComPtr<IInStream> inStreamTemp = inFile;

   if (!inFile->Open(fullPath))

     return ::GetLastError();

-  *inStream = inStreamTemp.Detach();

-  inFile->Name = name;

+

+  FileSizes.Add(_fileInfo.Size);

+  FileNames.Add(name);

+  inFile->FileNameIndex = FileNames_WasUsed.Add(true);

   inFile->OpenCallbackImp = this;

   inFile->OpenCallbackRef = this;

-  FileNames.Add(name);

-  TotalSize += _fileInfo.Size;

+  // TotalSize += _fileInfo.Size;

+  *inStream = inStreamTemp.Detach();

   return S_OK;

   COM_TRY_END

 }

@@ -130,4 +123,3 @@
   COM_TRY_END

 }

 #endif

-  

diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
old mode 100755
new mode 100644
index a60fca3..f7b3618
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -3,10 +3,9 @@
 #ifndef __ARCHIVE_OPEN_CALLBACK_H

 #define __ARCHIVE_OPEN_CALLBACK_H

 

-#include "Common/MyCom.h"

-#include "Common/MyString.h"

+#include "../../../Common/MyCom.h"

 

-#include "Windows/FileFind.h"

+#include "../../../Windows/FileFind.h"

 

 #ifndef _NO_CRYPTO

 #include "../../IPassword.h"

@@ -21,7 +20,7 @@
 

 #define INTERFACE_IOpenCallbackUI_Crypto(x) \

   virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \

-  virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \

+  virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \

   virtual bool Open_WasPasswordAsked() x; \

   virtual void Open_ClearPasswordWasAskedFlag() x; \

   

@@ -72,32 +71,41 @@
   {

     _subArchiveMode = true;

     _subArchiveName = name;

-    TotalSize = 0;

-    return  S_OK;

+    // TotalSize = 0;

+    return S_OK;

   }

 

 private:

-  UString _folderPrefix;

-  NWindows::NFile::NFind::CFileInfoW _fileInfo;

+  FString _folderPrefix;

+  NWindows::NFile::NFind::CFileInfo _fileInfo;

   bool _subArchiveMode;

   UString _subArchiveName;

+

 public:

   UStringVector FileNames;

+  CBoolVector FileNames_WasUsed;

+  CRecordVector<UInt64> FileSizes;

+

   IOpenCallbackUI *Callback;

   CMyComPtr<IArchiveOpenCallback> ReOpenCallback;

-  UInt64 TotalSize;

+  // UInt64 TotalSize;

 

   COpenCallbackImp(): Callback(NULL) {}

-  void Init(const UString &folderPrefix, const UString &fileName)

+  void Init(const FString &folderPrefix, const FString &fileName)

   {

     _folderPrefix = folderPrefix;

     if (!_fileInfo.Find(_folderPrefix + fileName))

-      throw 1;

+      throw 20121118;

     FileNames.Clear();

+    FileNames_WasUsed.Clear();

+    FileSizes.Clear();

     _subArchiveMode = false;

-    TotalSize = 0;

+    // TotalSize = 0;

   }

-  int FindName(const UString &name);

+  bool SetSecondFileInfo(CFSTR newName)

+  {

+    return _fileInfo.Find(newName) && !_fileInfo.IsDir();

+  }

 };

 

 #endif

diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
old mode 100755
new mode 100644
index 0c85695..d8dc3a8
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -2,8 +2,6 @@
 

 #include "StdAfx.h"

 

-#include "Bench.h"

-

 #ifndef _WIN32

 #define USE_POSIX_TIME

 #define USE_POSIX_TIME2

@@ -30,27 +28,56 @@
 

 #include "../../../../C/7zCrc.h"

 #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

 

-#include "../../../Windows/PropVariant.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/StringToInt.h"

 

-static const UInt32 kUncompressMinBlockSize =

-#ifdef UNDER_CE

-1 << 24;

-#else

-1 << 26;

-#endif

+#include "../../Common/MethodProps.h"

+#include "../../Common/StreamUtils.h"

 

-static const UInt32 kCrcBlockSize =

-#ifdef UNDER_CE

-1 << 25;

-#else

-1 << 30;

-#endif

+#include "Bench.h"

+

+using namespace NWindows;

+

+static const UInt64 kComplexInCommands = (UInt64)1 <<

+  #ifdef UNDER_CE

+    31;

+  #else

+    34;

+  #endif

+

+static const UInt64 kComplexInSeconds = 4;

+

+static void SetComplexCommands(UInt32 complexInSeconds, UInt64 cpuFreq, UInt64 &complexInCommands)

+{

+  complexInCommands = kComplexInCommands;

+  const UInt64 kMinFreq = (UInt64)1000000 * 30;

+  const UInt64 kMaxFreq = (UInt64)1000000 * 20000;

+  if (cpuFreq < kMinFreq) cpuFreq = kMinFreq;

+  if (cpuFreq < kMaxFreq)

+  {

+    if (complexInSeconds != 0)

+      complexInCommands = complexInSeconds * cpuFreq;

+    else

+      complexInCommands = cpuFreq >> 2;

+  }

+}

+

+static const unsigned kNumHashDictBits = 17;

+static const UInt32 kFilterUnpackSize = (48 << 10);

+

+static const unsigned kOldLzmaDictBits = 30;

 

 static const UInt32 kAdditionalSize = (1 << 16);

 static const UInt32 kCompressedAdditionalSize = (1 << 10);

@@ -76,6 +103,7 @@
 public:

   size_t BufferSize;

   Byte *Buffer;

+

   CBenchBuffer(): Buffer(0) {}

   virtual ~CBenchBuffer() { Free(); }

   void Free()

@@ -90,7 +118,7 @@
     Free();

     Buffer = (Byte *)::MidAlloc(bufferSize);

     BufferSize = bufferSize;

-    return (Buffer != 0);

+    return (Buffer != 0 || bufferSize == 0);

   }

 };

 

@@ -99,7 +127,7 @@
   CBaseRandomGenerator *RG;

 public:

   void Set(CBaseRandomGenerator *rg) { RG = rg; }

-  UInt32 GetVal(UInt32 &res, int numBits)

+  UInt32 GetVal(UInt32 &res, unsigned numBits)

   {

     UInt32 val = res & (((UInt32)1 << numBits) - 1);

     res >>= numBits;

@@ -110,7 +138,14 @@
     UInt32 len = GetVal(res, 2);

     return GetVal(res, 1 + len);

   }

-  void Generate()

+

+  void GenerateSimpleRandom()

+  {

+    for (UInt32 i = 0; i < BufferSize; i++)

+      Buffer[i] = (Byte)RG->GetRnd();

+  }

+

+  void Generate(unsigned dictBits)

   {

     UInt32 pos = 0;

     UInt32 rep0 = 1;

@@ -131,7 +166,7 @@
           {

             UInt32 ppp = GetVal(res, 5) + 6;

             res = RG->GetRnd();

-            if (ppp > 30)

+            if (ppp > dictBits)

               continue;

             rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);

             res = RG->GetRnd();

@@ -190,9 +225,16 @@
   // bool _overflow;

 public:

   UInt32 Pos;

+  bool RealCopy;

+  bool CalcCrc;

+  UInt32 Crc;

+

   // CBenchmarkOutStream(): _overflow(false) {}

-  void Init()

+  void Init(bool realCopy, bool calcCrc)

   {

+    Crc = CRC_INIT_VAL;

+    RealCopy = realCopy;

+    CalcCrc = calcCrc;

     // _overflow = false;

     Pos = 0;

   }

@@ -205,7 +247,10 @@
   size_t curSize = BufferSize - Pos;

   if (curSize > size)

     curSize = size;

-  memcpy(Buffer + Pos, data, curSize);

+  if (RealCopy)

+    memcpy(Buffer + Pos, data, curSize);

+  if (CalcCrc)

+    Crc = CrcUpdate(Crc, data, curSize);

   Pos += (UInt32)curSize;

   if(processedSize != NULL)

     *processedSize = (UInt32)curSize;

@@ -222,15 +267,19 @@
   public CMyUnknownImp

 {

 public:

+  bool CalcCrc;

   UInt32 Crc;

   MY_UNKNOWN_IMP

+    

+  CCrcOutStream(): CalcCrc(true) {};

   void Init() { Crc = CRC_INIT_VAL; }

   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

 };

 

 STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

-  Crc = CrcUpdate(Crc, data, size);

+  if (CalcCrc)

+    Crc = CrcUpdate(Crc, data, size);

   if (processedSize != NULL)

     *processedSize = size;

   return S_OK;

@@ -275,15 +324,33 @@
   #endif

 }

 

-#ifndef USE_POSIX_TIME

-static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }

-#endif

+#ifdef USE_POSIX_TIME

 

-static UInt64 GetUserTime()

+struct CUserTime

 {

-  #ifdef USE_POSIX_TIME

-  return clock();

-  #else

+  UInt64 Sum;

+  clock_t Prev;

+  

+  void Init()

+  {

+    Prev = clock();

+    Sum = 0;

+  }

+

+  UInt64 GetUserTime()

+  {

+    clock_t v = clock();

+    Sum += v - Prev;

+    Prev = v;

+    return Sum;

+  }

+};

+

+#else

+

+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }

+UInt64 GetWinUserTime()

+{

   FILETIME creationTime, exitTime, kernelTime, userTime;

   if (

   #ifdef UNDER_CE

@@ -294,9 +361,18 @@
     , &creationTime, &exitTime, &kernelTime, &userTime) != 0)

     return GetTime64(userTime) + GetTime64(kernelTime);

   return (UInt64)GetTickCount() * 10000;

-  #endif

 }

 

+struct CUserTime

+{

+  UInt64 StartTime;

+

+  void Init() { StartTime = GetWinUserTime(); }

+  UInt64 GetUserTime() { return GetWinUserTime() - StartTime; }

+};

+

+#endif

+

 static UInt64 GetUserFreq()

 {

   #ifdef USE_POSIX_TIME

@@ -309,7 +385,7 @@
 class CBenchProgressStatus

 {

   #ifndef _7ZIP_ST

-  NWindows::NSynchronization::CCriticalSection CS;

+  NSynchronization::CCriticalSection CS;

   #endif

 public:

   HRESULT Res;

@@ -317,69 +393,79 @@
   void SetResult(HRESULT res)

   {

     #ifndef _7ZIP_ST

-    NWindows::NSynchronization::CCriticalSectionLock lock(CS);

+    NSynchronization::CCriticalSectionLock lock(CS);

     #endif

     Res = res;

   }

   HRESULT GetResult()

   {

     #ifndef _7ZIP_ST

-    NWindows::NSynchronization::CCriticalSectionLock lock(CS);

+    NSynchronization::CCriticalSectionLock lock(CS);

     #endif

     return Res;

   }

 };

 

+struct CBenchInfoCalc

+{

+  CBenchInfo BenchInfo;

+  CUserTime UserTime;

+

+  void SetStartTime();

+  void SetFinishTime(CBenchInfo &dest);

+};

+

+void CBenchInfoCalc::SetStartTime()

+{

+  BenchInfo.GlobalFreq = GetFreq();

+  BenchInfo.UserFreq = GetUserFreq();

+  BenchInfo.GlobalTime = ::GetTimeCount();

+  BenchInfo.UserTime = 0;

+  UserTime.Init();

+}

+

+void CBenchInfoCalc::SetFinishTime(CBenchInfo &dest)

+{

+  dest = BenchInfo;

+  dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime;

+  dest.UserTime = UserTime.GetUserTime();

+}

+

 class CBenchProgressInfo:

   public ICompressProgressInfo,

-  public CMyUnknownImp

+  public CMyUnknownImp,

+  public CBenchInfoCalc

 {

 public:

   CBenchProgressStatus *Status;

-  CBenchInfo BenchInfo;

   HRESULT Res;

-  IBenchCallback *callback;

-  CBenchProgressInfo(): callback(0) {}

+  IBenchCallback *Callback;

+

+  CBenchProgressInfo(): Callback(0) {}

   MY_UNKNOWN_IMP

   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

 };

 

-static void SetStartTime(CBenchInfo &bi)

-{

-  bi.GlobalFreq = GetFreq();

-  bi.UserFreq = GetUserFreq();

-  bi.GlobalTime = ::GetTimeCount();

-  bi.UserTime = ::GetUserTime();

-}

-

-static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)

-{

-  dest.GlobalFreq = GetFreq();

-  dest.UserFreq = GetUserFreq();

-  dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;

-  dest.UserTime = ::GetUserTime() - biStart.UserTime;

-}

-

 STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

 {

   HRESULT res = Status->GetResult();

   if (res != S_OK)

     return res;

-  if (!callback)

+  if (!Callback)

     return res;

-  CBenchInfo info = BenchInfo;

-  SetFinishTime(BenchInfo, info);

+  CBenchInfo info;

+  SetFinishTime(info);

   if (Status->EncodeMode)

   {

-    info.UnpackSize = *inSize;

-    info.PackSize = *outSize;

-    res = callback->SetEncodeResult(info, false);

+    info.UnpackSize = BenchInfo.UnpackSize + *inSize;

+    info.PackSize = BenchInfo.PackSize + *outSize;

+    res = Callback->SetEncodeResult(info, false);

   }

   else

   {

     info.PackSize = BenchInfo.PackSize + *inSize;

     info.UnpackSize = BenchInfo.UnpackSize + *outSize;

-    res = callback->SetDecodeResult(info, false);

+    res = Callback->SetDecodeResult(info, false);

   }

   if (res != S_OK)

     Status->SetResult(res);

@@ -406,12 +492,12 @@
   }

 }

 

-UInt64 GetUsage(const CBenchInfo &info)

+UInt64 CBenchInfo::GetUsage() const

 {

-  UInt64 userTime = info.UserTime;

-  UInt64 userFreq = info.UserFreq;

-  UInt64 globalTime = info.GlobalTime;

-  UInt64 globalFreq = info.GlobalFreq;

+  UInt64 userTime = UserTime;

+  UInt64 userFreq = UserFreq;

+  UInt64 globalTime = GlobalTime;

+  UInt64 globalFreq = GlobalFreq;

   NormalizeVals(userTime, userFreq);

   NormalizeVals(globalFreq, globalTime);

   if (userFreq == 0)

@@ -421,19 +507,19 @@
   return userTime * globalFreq * 1000000 / userFreq / globalTime;

 }

 

-UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)

+UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const

 {

-  UInt64 userTime = info.UserTime;

-  UInt64 userFreq = info.UserFreq;

-  UInt64 globalTime = info.GlobalTime;

-  UInt64 globalFreq = info.GlobalFreq;

+  UInt64 userTime = UserTime;

+  UInt64 userFreq = UserFreq;

+  UInt64 globalTime = GlobalTime;

+  UInt64 globalFreq = GlobalFreq;

   NormalizeVals(userFreq, userTime);

   NormalizeVals(globalTime, globalFreq);

   if (globalFreq == 0)

     globalFreq = 1;

   if (userTime == 0)

     userTime = 1;

-  return userFreq * globalTime / globalFreq *  rating / userTime;

+  return userFreq * globalTime / globalFreq * rating / userTime;

 }

 

 static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)

@@ -445,35 +531,101 @@
   return value * freq / elTime;

 }

 

-UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)

+UInt64 CBenchInfo::GetSpeed(UInt64 numCommands) const

 {

-  UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);

-  UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits));

-  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;

+  return MyMultDiv64(numCommands, GlobalTime, GlobalFreq);

+}

+

+struct CBenchProps

+{

+  bool LzmaRatingMode;

+  

+  UInt32 EncComplex;

+  UInt32 DecComplexCompr;

+  UInt32 DecComplexUnc;

+

+  CBenchProps(): LzmaRatingMode(false) {}

+  void SetLzmaCompexity();

+

+  UInt64 GeComprCommands(UInt64 unpackSize)

+  {

+    return unpackSize * EncComplex;

+  }

+

+  UInt64 GeDecomprCommands(UInt64 packSize, UInt64 unpackSize)

+  {

+    return (packSize * DecComplexCompr + unpackSize * DecComplexUnc);

+  }

+

+  UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size);

+  UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations);

+};

+

+void CBenchProps::SetLzmaCompexity()

+{

+  EncComplex = 1200;

+  DecComplexUnc = 4;

+  DecComplexCompr = 190;

+  LzmaRatingMode = true;

+}

+

+UInt64 CBenchProps::GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size)

+{

+  if (dictSize < (1 << kBenchMinDicLogSize))

+    dictSize = (1 << kBenchMinDicLogSize);

+  UInt64 encComplex = EncComplex;

+  if (LzmaRatingMode)

+  {

+    UInt64 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits);

+    encComplex = 870 + ((t * t * 5) >> (2 * kSubBits));

+  }

+  UInt64 numCommands = (UInt64)size * encComplex;

   return MyMultDiv64(numCommands, elapsedTime, freq);

 }

 

-UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)

+UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)

 {

-  UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations;

+  UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations;

   return MyMultDiv64(numCommands, elapsedTime, freq);

 }

 

+UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size)

+{

+  CBenchProps props;

+  props.SetLzmaCompexity();

+  return props.GetCompressRating(dictSize, elapsedTime, freq, size);

+}

+

+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)

+{

+  CBenchProps props;

+  props.SetLzmaCompexity();

+  return props.GetDecompressRating(elapsedTime, freq, outSize, inSize, numIterations);

+}

+

 struct CEncoderInfo;

 

 struct CEncoderInfo

 {

   #ifndef _7ZIP_ST

   NWindows::CThread thread[2];

+  UInt32 NumDecoderSubThreads;

   #endif

-  CMyComPtr<ICompressCoder> encoder;

+  CMyComPtr<ICompressCoder> _encoder;

+  CMyComPtr<ICompressFilter> _encoderFilter;

   CBenchProgressInfo *progressInfoSpec[2];

   CMyComPtr<ICompressProgressInfo> progressInfo[2];

-  UInt32 NumIterations;

+  UInt64 NumIterations;

   #ifdef USE_ALLOCA

   size_t AllocaSize;

   #endif

 

+  Byte _key[32];

+  Byte _iv[16];

+  Byte _psw[16];

+  bool CheckCrc_Enc;

+  bool CheckCrc_Dec;

+

   struct CDecoderInfo

   {

     CEncoderInfo *Encoder;

@@ -485,35 +637,58 @@
   };

   CDecoderInfo decodersInfo[2];

 

-  CMyComPtr<ICompressCoder> decoders[2];

+  CMyComPtr<ICompressCoder> _decoders[2];

+  CMyComPtr<ICompressFilter> _decoderFilter;

+

   HRESULT Results[2];

   CBenchmarkOutStream *outStreamSpec;

   CMyComPtr<ISequentialOutStream> outStream;

   IBenchCallback *callback;

+  IBenchPrintCallback *printCallback;

   UInt32 crc;

   UInt32 kBufferSize;

   UInt32 compressedSize;

   CBenchRandomGenerator rg;

+  CBenchBuffer rgCopy; // it must be 16-byte aligned !!!

   CBenchmarkOutStream *propStreamSpec;

   CMyComPtr<ISequentialOutStream> propStream;

-  HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);

+

+  // for decode

+  COneMethodInfo _method;

+  UInt32 _uncompressedDataSize;

+

+  HRESULT Init(

+      const COneMethodInfo &method,

+      UInt32 uncompressedDataSize,

+      unsigned generateDictBits,

+      CBaseRandomGenerator *rg);

   HRESULT Encode();

   HRESULT Decode(UInt32 decoderIndex);

 

-  CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}

+  CEncoderInfo():

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

     CEncoderInfo *encoder = (CEncoderInfo *)param;

-    #ifdef USE_ALLOCA

-    alloca(encoder->AllocaSize);

-    #endif

-    HRESULT res = encoder->Encode();

-    encoder->Results[0] = res;

+    try

+    {

+      #ifdef USE_ALLOCA

+      alloca(encoder->AllocaSize);

+      #endif

+      res = encoder->Encode();

+      encoder->Results[0] = res;

+    }

+    catch(...)

+    {

+      res = E_FAIL;

+    }

     if (res != S_OK)

       encoder->progressInfoSpec[0]->Status->SetResult(res);

-

     return 0;

   }

   static THREAD_FUNC_DECL DecodeThreadFunction(void *param)

@@ -550,16 +725,34 @@
   #endif

 };

 

-HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)

+static const UInt32 k_LZMA  = 0x030101;

+

+HRESULT CEncoderInfo::Init(

+    const COneMethodInfo &method,

+    UInt32 uncompressedDataSize,

+    unsigned generateDictBits,

+    CBaseRandomGenerator *rgLoc)

 {

   rg.Set(rgLoc);

-  kBufferSize = dictionarySize + kAdditionalSize;

-  UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;

+  kBufferSize = uncompressedDataSize;

+  UInt32 kCompressedBufferSize =

+      kBufferSize + kCompressedAdditionalSize;

+      // (kBufferSize - kBufferSize / 4) + kCompressedAdditionalSize;

   if (!rg.Alloc(kBufferSize))

     return E_OUTOFMEMORY;

-  rg.Generate();

+  if (generateDictBits == 0)

+    rg.GenerateSimpleRandom();

+  else

+    rg.Generate(generateDictBits);

   crc = CrcCalc(rg.Buffer, rg.BufferSize);

 

+  if (_encoderFilter)

+  {

+    if (!rgCopy.Alloc(rg.BufferSize))

+      return E_OUTOFMEMORY;

+  }

+

+

   outStreamSpec = new CBenchmarkOutStream;

   if (!outStreamSpec->Alloc(kCompressedBufferSize))

     return E_OUTOFMEMORY;

@@ -574,48 +767,130 @@
   }

   if (!propStreamSpec->Alloc(kMaxLzmaPropSize))

     return E_OUTOFMEMORY;

-  propStreamSpec->Init();

+  propStreamSpec->Init(true, false);

   

-  PROPID propIDs[] =

+ 

+  CMyComPtr<IUnknown> coder;

+  if (_encoderFilter)

+    coder = _encoderFilter;

+  else

+    coder = _encoder;

   {

-    NCoderPropID::kDictionarySize,

-    NCoderPropID::kNumThreads

-  };

-  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);

-  PROPVARIANT props[kNumProps];

-  props[0].vt = VT_UI4;

-  props[0].ulVal = dictionarySize;

-

-  props[1].vt = VT_UI4;

-  props[1].ulVal = numThreads;

-

-  {

-    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

-    RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));

-    if (!setCoderProperties)

-      return E_FAIL;

-    RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps));

-

-    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

-    encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);

-    if (writeCoderProperties)

+    CMyComPtr<ICompressSetCoderProperties> scp;

+    coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);

+    if (scp)

     {

-      RINOK(writeCoderProperties->WriteCoderProperties(propStream));

+      UInt64 reduceSize = uncompressedDataSize;

+      RINOK(method.SetCoderProps(scp, &reduceSize));

     }

+    else

+    {

+      if (method.AreThereNonOptionalProps())

+        return E_INVALIDARG;

+    }

+

+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProps;

+    coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps);

+    if (writeCoderProps)

+    {

+      RINOK(writeCoderProps->WriteCoderProperties(propStream));

+    }

+

+    {

+      CMyComPtr<ICryptoSetPassword> sp;

+      coder.QueryInterface(IID_ICryptoSetPassword, &sp);

+      if (sp)

+      {

+        RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));

+

+        // 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)

+        {

+          _encoderFilter->Init();

+          _encoderFilter->Filter(temp, sizeof(temp));

+        }

+        else

+        {

+          RINOK(_encoder->Code(inStream, outStream, 0, 0, NULL));

+        }

+      }

+    }

+

   }

   return S_OK;

 }

 

 HRESULT CEncoderInfo::Encode()

 {

+  CBenchInfo &bi = progressInfoSpec[0]->BenchInfo;

+  bi.UnpackSize = 0;

+  bi.PackSize = 0;

+  CMyComPtr<ICryptoProperties> cp;

+  CMyComPtr<IUnknown> coder;

+  if (_encoderFilter)

+    coder = _encoderFilter;

+  else

+    coder = _encoder;

+  coder.QueryInterface(IID_ICryptoProperties, &cp);

   CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

   CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

-  inStreamSpec->Init(rg.Buffer, rg.BufferSize);

-  outStreamSpec->Init();

+  UInt64 prev = 0;

 

-  RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));

-  compressedSize = outStreamSpec->Pos;

-  encoder.Release();

+  UInt32 crcPrev = 0;

+

+  if (cp)

+  {

+    RINOK(cp->SetKey(_key, sizeof(_key)));

+    RINOK(cp->SetInitVector(_iv, sizeof(_iv)));

+  }

+

+  for (UInt64 i = 0; i < NumIterations; i++)

+  {

+    if (printCallback && bi.UnpackSize - prev > (1 << 20))

+    {

+      RINOK(printCallback->CheckBreak());

+      prev = bi.UnpackSize;

+    }

+    

+    bool isLast = (i == NumIterations - 1);

+    bool calcCrc = ((isLast || (i & 0x7F) == 0 || CheckCrc_Enc) && NumIterations != 1);

+    outStreamSpec->Init(isLast, calcCrc);

+    

+    if (_encoderFilter)

+    {

+      memcpy(rgCopy.Buffer, rg.Buffer, rg.BufferSize);

+      _encoderFilter->Init();

+      _encoderFilter->Filter(rgCopy.Buffer, (UInt32)rg.BufferSize);

+      RINOK(WriteStream(outStream, rgCopy.Buffer, rg.BufferSize));

+    }

+    else

+    {

+      inStreamSpec->Init(rg.Buffer, rg.BufferSize);

+      RINOK(_encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));

+    }

+

+    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.PackSize += compressedSize;

+  }

+  _encoder.Release();

+  _encoderFilter.Release();

   return S_OK;

 }

 

@@ -623,11 +898,20 @@
 {

   CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

   CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

-  CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];

+  CMyComPtr<ICompressCoder> &decoder = _decoders[decoderIndex];

+  CMyComPtr<IUnknown> coder;

+  if (_decoderFilter)

+  {

+    if (decoderIndex != 0)

+      return E_FAIL;

+    coder = _decoderFilter;

+  }

+  else

+    coder = decoder;

 

-  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;

-  decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);

-  if (!compressSetDecoderProperties)

+  CMyComPtr<ICompressSetDecoderProperties2> setDecProps;

+  coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps);

+  if (!setDecProps && propStreamSpec->Pos != 0)

     return E_FAIL;

 

   CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;

@@ -637,24 +921,87 @@
   pi->BenchInfo.UnpackSize = 0;

   pi->BenchInfo.PackSize = 0;

 

-  for (UInt32 j = 0; j < NumIterations; j++)

+  #ifndef _7ZIP_ST

   {

+    CMyComPtr<ICompressSetCoderMt> setCoderMt;

+    coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);

+    if (setCoderMt)

+    {

+      RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads));

+    }

+  }

+  #endif

+

+  CMyComPtr<ICompressSetCoderProperties> scp;

+  coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);

+  if (scp)

+  {

+    UInt64 reduceSize = _uncompressedDataSize;

+    RINOK(_method.SetCoderProps(scp, &reduceSize));

+  }

+

+  CMyComPtr<ICryptoProperties> cp;

+  coder.QueryInterface(IID_ICryptoProperties, &cp);

+  

+  if (setDecProps)

+  {

+    RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));

+  }

+

+  {

+    CMyComPtr<ICryptoSetPassword> sp;

+    coder.QueryInterface(IID_ICryptoSetPassword, &sp);

+    if (sp)

+    {

+      RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));

+    }

+  }

+

+  UInt64 prev = 0;

+  

+  if (cp)

+  {

+    RINOK(cp->SetKey(_key, sizeof(_key)));

+    RINOK(cp->SetInitVector(_iv, sizeof(_iv)));

+  }

+

+  for (UInt64 i = 0; i < NumIterations; i++)

+  {

+    if (printCallback && pi->BenchInfo.UnpackSize - prev > (1 << 20))

+    {

+      RINOK(printCallback->CheckBreak());

+      prev = pi->BenchInfo.UnpackSize;

+    }

+

     inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);

     crcOutStreamSpec->Init();

     

-    RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));

     UInt64 outSize = kBufferSize;

-    RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));

-    if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)

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

+    }

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

+static const UInt32 kNumThreadsMax = (1 << 12);

 

 struct CBenchEncoders

 {

@@ -663,45 +1010,87 @@
   ~CBenchEncoders() { delete []encoders; }

 };

 

-HRESULT LzmaBench(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)

+static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands)

 {

-  UInt32 numEncoderThreads =

-    #ifndef _7ZIP_ST

-    (numThreads > 1 ? numThreads / 2 : 1);

-    #else

-    1;

-    #endif

-  UInt32 numSubDecoderThreads =

-    #ifndef _7ZIP_ST

-    (numThreads > 1 ? 2 : 1);

-    #else

-    1;

-    #endif

-  if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)

-  {

+  if (numCommands < (1 << 4))

+    numCommands = (1 << 4);

+  UInt64 res = complexInCommands / numCommands;

+  return (res == 0 ? 1 : res);

+}

+

+static HRESULT MethodBench(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    UInt64 complexInCommands,

+    bool oldLzmaBenchMode,

+    UInt32 numThreads,

+    const COneMethodInfo &method2,

+    UInt32 uncompressedDataSize,

+    unsigned generateDictBits,

+    IBenchPrintCallback *printCallback,

+    IBenchCallback *callback,

+    CBenchProps *benchProps)

+{

+  COneMethodInfo method = method2;

+  UInt64 methodId;

+  UInt32 numInStreams, numOutStreams;

+  if (!FindMethod(

+      EXTERNAL_CODECS_LOC_VARS

+      method.MethodName, methodId, numInStreams, numOutStreams))

+    return E_NOTIMPL;

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

     return E_INVALIDARG;

-  }

+

+  UInt32 numEncoderThreads = 1;

+  UInt32 numSubDecoderThreads = 1;

+  

+  #ifndef _7ZIP_ST

+    numEncoderThreads = numThreads;

+

+    if (oldLzmaBenchMode && methodId == k_LZMA)

+    {

+      bool fixedNumber;

+      UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber);

+      if (!fixedNumber && numThreads == 1)

+        method.AddNumThreadsProp(1);

+      if (numThreads > 1 && numLzmaThreads > 1)

+      {

+        numEncoderThreads = numThreads / 2;

+        numSubDecoderThreads = 2;

+      }

+    }

+  #endif

 

   CBenchEncoders encodersSpec(numEncoderThreads);

   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;

 

-    const UInt32 kLzmaId = 0x030101;

-    RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));

-    if (!encoder.encoder)

+    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.

+

+    encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ;

+    encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ;

+

+    memset(encoder._iv, 0, sizeof(encoder._iv));

+    memset(encoder._key, 0, sizeof(encoder._key));

+    memset(encoder._psw, 0, sizeof(encoder._psw));

+

     for (UInt32 j = 0; j < numSubDecoderThreads; j++)

     {

-      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));

-      if (!encoder.decoders[j])

+      CMyComPtr<ICompressCoder2> coder2de;

+      CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j];

+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,

+        encoder._decoderFilter, decoder, coder2de, false, false));

+      if (!encoder._decoderFilter && !decoder)

         return E_NOTIMPL;

     }

   }

@@ -710,7 +1099,10 @@
   rg.Init();

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

   {

-    RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));

+    CEncoderInfo &encoder = encoders[i];

+    encoder._method = method;

+    encoder._uncompressedDataSize = uncompressedDataSize;

+    RINOK(encoders[i].Init(method, uncompressedDataSize, generateDictBits, &rg));

   }

 

   CBenchProgressStatus status;

@@ -720,16 +1112,21 @@
   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

+    encoder.NumIterations = GetNumIterations(benchProps->GeComprCommands(uncompressedDataSize), complexInCommands);

+

     for (int j = 0; j < 2; j++)

     {

-      encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;

-      encoder.progressInfoSpec[j]->Status = &status;

+      CBenchProgressInfo *spec = new CBenchProgressInfo;

+      encoder.progressInfoSpec[j] = spec;

+      encoder.progressInfo[j] = spec;

+      spec->Status = &status;

     }

     if (i == 0)

     {

-      encoder.progressInfoSpec[0]->callback = callback;

-      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;

-      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);

+      CBenchProgressInfo *bpi = encoder.progressInfoSpec[0];

+      bpi->Callback = callback;

+      bpi->BenchInfo.NumIterations = numEncoderThreads;

+      bpi->SetStartTime();

     }

 

     #ifndef _7ZIP_ST

@@ -756,10 +1153,10 @@
 

   CBenchInfo info;

 

-  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);

+  encoders[0].progressInfoSpec[0]->SetFinishTime(info);

   info.UnpackSize = 0;

   info.PackSize = 0;

-  info.NumIterations = 1; // progressInfoSpec->NumIterations;

+  info.NumIterations = encoders[0].NumIterations;

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

   {

     CEncoderInfo &encoder = encoders[i];

@@ -776,16 +1173,23 @@
   for (i = 0; i < numEncoderThreads; i++)

   {

     CEncoderInfo &encoder = encoders[i];

-    encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;

 

     if (i == 0)

     {

-      encoder.progressInfoSpec[0]->callback = callback;

-      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;

-      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);

+      encoder.NumIterations = GetNumIterations(benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize), complexInCommands);

+      CBenchProgressInfo *bpi = encoder.progressInfoSpec[0];

+      bpi->Callback = callback;

+      bpi->BenchInfo.NumIterations = numDecoderThreads;

+      bpi->SetStartTime();

     }

+    else

+      encoder.NumIterations = encoders[0].NumIterations;

 

     #ifndef _7ZIP_ST

+    {

+      int numSubThreads = method.Get_NumThreads();

+      encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : numSubThreads;

+    }

     if (numDecoderThreads > 1)

     {

       for (UInt32 j = 0; j < numSubDecoderThreads; j++)

@@ -818,7 +1222,7 @@
   RINOK(res);

   #endif

   RINOK(status.Res);

-  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);

+  encoders[0].progressInfoSpec[0]->SetFinishTime(info);

   #ifndef _7ZIP_ST

   #ifdef UNDER_CE

   if (numDecoderThreads > 1)

@@ -872,23 +1276,122 @@
     GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;

 }

 

-static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)

+static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations,

+    const UInt32 *checkSum, IHasher *hf,

+    IBenchPrintCallback *callback)

 {

-  for (UInt32 i = 0; i < numCycles; i++)

-    if (CrcCalc(data, size) != crcBase)

-      return false;

-  return true;

+  Byte hash[64];

+  UInt64 i;

+  for (i = 0; i < sizeof(hash); i++)

+    hash[i] = 0;

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

+  {

+    if (callback && (i & 0xFF) == 0)

+    {

+      RINOK(callback->CheckBreak());

+    }

+    hf->Init();

+    hf->Update(data, size);

+    hf->Final(hash);

+    UInt32 hashSize = hf->GetDigestSize();

+    if (hashSize > sizeof(hash))

+      return S_FALSE;

+    UInt32 sum = 0;

+    for (UInt32 j = 0; j < hashSize; j += 4)

+      sum ^= GetUi32(hash + j);

+    if (checkSum && sum != *checkSum)

+    {

+      // printf(" %08X ", sum);

+      return S_FALSE;

+    }

+  }

+  return S_OK;

+}

+

+UInt32 g_BenchCpuFreqTemp = 1;

+

+#define YY1 sum += val; sum ^= val;

+#define YY3 YY1 YY1 YY1 YY1

+#define YY5 YY3 YY3 YY3 YY3

+#define YY7 YY5 YY5 YY5 YY5

+static const UInt32 kNumFreqCommands = 128;

+

+static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val)

+{

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

+  {

+    YY7

+  }

+  return sum;

 }

 

 #ifndef _7ZIP_ST

+

+struct CFreqInfo

+{

+  NWindows::CThread Thread;

+  IBenchPrintCallback *Callback;

+  HRESULT CallbackRes;

+  UInt32 ValRes;

+  UInt32 Size;

+  UInt64 NumIterations;

+

+  void Wait()

+  {

+    Thread.Wait();

+    Thread.Close();

+  }

+};

+

+static THREAD_FUNC_DECL FreqThreadFunction(void *param)

+{

+  CFreqInfo *p = (CFreqInfo *)param;

+

+  UInt32 sum = g_BenchCpuFreqTemp;

+  for (UInt64 k = p->NumIterations; k > 0; k--)

+  {

+    p->CallbackRes = p->Callback->CheckBreak();

+    if (p->CallbackRes != S_OK)

+      return 0;

+    sum = CountCpuFreq(sum, p->Size, g_BenchCpuFreqTemp);

+  }

+  p->ValRes = sum;

+  return 0;

+}

+

+struct CFreqThreads

+{

+  CFreqInfo *Items;

+  UInt32 NumThreads;

+

+  CFreqThreads(): Items(0), NumThreads(0) {}

+  void WaitAll()

+  {

+    for (UInt32 i = 0; i < NumThreads; i++)

+      Items[i].Wait();

+    NumThreads = 0;

+  }

+  ~CFreqThreads()

+  {

+    WaitAll();

+    delete []Items;

+  }

+};

+

 struct CCrcInfo

 {

   NWindows::CThread Thread;

+  IBenchPrintCallback *Callback;

+  HRESULT CallbackRes;

+

   const Byte *Data;

   UInt32 Size;

-  UInt32 NumCycles;

-  UInt32 Crc;

-  bool Res;

+  UInt64 NumIterations;

+  bool CheckSumDefined;

+  UInt32 CheckSum;

+  CMyComPtr<IHasher> Hasher;

+  HRESULT Res;

+

   void Wait()

   {

     Thread.Wait();

@@ -899,14 +1402,17 @@
 static THREAD_FUNC_DECL CrcThreadFunction(void *param)

 {

   CCrcInfo *p = (CCrcInfo *)param;

-  p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);

+  p->Res = CrcBig(p->Data, p->Size, p->NumIterations,

+      p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher,

+      p->Callback);

   return 0;

 }

 

 struct CCrcThreads

 {

-  UInt32 NumThreads;

   CCrcInfo *Items;

+  UInt32 NumThreads;

+

   CCrcThreads(): Items(0), NumThreads(0) {}

   void WaitAll()

   {

@@ -920,6 +1426,7 @@
     delete []Items;

   }

 };

+

 #endif

 

 static UInt32 CrcCalc1(const Byte *buf, UInt32 size)

@@ -966,11 +1473,444 @@
   return true;

 }

 

-HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)

+struct CBenchMethod

+{

+  unsigned DictBits;

+  UInt32 EncComplex;

+  UInt32 DecComplexCompr;

+  UInt32 DecComplexUnc;

+  const char *Name;

+};

+

+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" }

+};

+

+struct CBenchHash

+{

+  UInt32 Complex;

+  UInt32 CheckSum;

+  const char *Name;

+};

+

+static const CBenchHash g_Hash[] =

+{

+  {   558, 0x8F8FEDAB, "CRC32:4" },

+  {   339, 0x8F8FEDAB, "CRC32:8" },

+  {   512, 0xDF1C17CC, "CRC64" },

+  { 11900, 0x2D79FF2E, "SHA256" },

+  {  5230, 0x4C25132B, "SHA1" }

+};

+

+struct CTotalBenchRes

+{

+  UInt64 NumIterations;

+  UInt64 Rating;

+  UInt64 Usage;

+  UInt64 RPU;

+  void Init() { NumIterations = 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);

+  }

+};

+

+static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size)

+{

+  char s[128];

+  int startPos = (int)sizeof(s) - 32;

+  memset(s, ' ', startPos);

+  ConvertUInt64ToString(value, s + startPos);

+  // if (withSpace)

+  {

+    startPos--;

+    size++;

+  }

+  int len = (int)strlen(s + startPos);

+  if (size > len)

+  {

+    startPos -= (size - len);

+    if (startPos < 0)

+      startPos = 0;

+  }

+  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 int kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating;

+static const int kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec;

+

+

+static void PrintRating(IBenchPrintCallback &f, UInt64 rating, int size)

+{

+  PrintNumber(f, (rating + 500000) / 1000000, size);

+}

+

+

+static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, int size)

+{

+  PrintNumber(f, (val * 100 + divider / 2) / divider, size);

+}

+

+static void PrintChars(IBenchPrintCallback &f, char c, int size)

+{

+  char s[256];

+  memset(s, (Byte)c, size);

+  s[size] = 0;

+  f.Print(s);

+}

+

+static void PrintSpaces(IBenchPrintCallback &f, int size)

+{

+  PrintChars(f, ' ', size);

+}

+

+static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq)

+{

+  PrintNumber(f, (usage + 5000) / 10000, kFieldSize_Usage);

+  PrintRating(f, rpu, kFieldSize_RU);

+  PrintRating(f, rating, kFieldSize_Rating);

+  if (showFreq)

+  {

+    if (cpuFreq == 0)

+      PrintSpaces(f, kFieldSize_EUAndEffec);

+    else

+    {

+      UInt64 ddd = cpuFreq * usage / 100;

+      if (ddd == 0)

+        ddd = 1;

+      PrintPercents(f, (rating * 10000), ddd, kFieldSize_EU);

+      PrintPercents(f, rating, cpuFreq, kFieldSize_Effec);

+    }

+  }

+}

+

+static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res)

+{

+  UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations);

+  if (f)

+  {

+    if (speed != 0)

+      PrintNumber(*f, speed / 1024, kFieldSize_Speed);

+    else

+      PrintSpaces(*f, 1 + kFieldSize_Speed);

+  }

+  UInt64 usage = info.GetUsage();

+  UInt64 rpu = info.GetRatingPerUsage(rating);

+  if (f)

+  {

+    PrintResults(*f, usage, rpu, rating, showFreq, cpuFreq);

+  }

+

+  if (res)

+  {

+    res->NumIterations++;

+    res->RPU += rpu;

+    res->Rating += rating;

+    res->Usage += usage;

+  }

+}

+

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

+}

+

+static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)

+{

+  f.Print("RAM ");

+  f.Print(sizeString);

+  PrintNumber(f, (size >> 20), 6);

+  f.Print(" MB,  # ");

+  f.Print(threadsString);

+  PrintNumber(f, numThreads, 3);

+  f.NewLine();

+}

+

+struct CBenchCallbackToPrint: public IBenchCallback

+{

+  CBenchProps BenchProps;

+  CTotalBenchRes EncodeRes;

+  CTotalBenchRes DecodeRes;

+  IBenchPrintCallback *_file;

+  UInt32 DictSize;

+

+  bool Use2Columns;

+  int NameFieldSize;

+

+  bool ShowFreq;

+  UInt64 CpuFreq;

+

+  CBenchCallbackToPrint(): Use2Columns(false), NameFieldSize(0), ShowFreq(false), CpuFreq(0) {}

+

+  void Init() { EncodeRes.Init(); DecodeRes.Init(); }

+  void Print(const char *s);

+  void NewLine();

+  

+  HRESULT SetFreq(bool showFreq, UInt64 cpuFreq);

+  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);

+  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);

+};

+

+HRESULT CBenchCallbackToPrint::SetFreq(bool showFreq, UInt64 cpuFreq)

+{

+  ShowFreq = showFreq;

+  CpuFreq = cpuFreq;

+  return S_OK;

+}

+

+HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final)

+{

+  RINOK(_file->CheckBreak());

+  if (final)

+  {

+    UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations);

+    PrintResults(_file, info, rating, ShowFreq, CpuFreq, &EncodeRes);

+  }

+  return S_OK;

+}

+

+static const char *kSep = "  | ";

+

+HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final)

+{

+  RINOK(_file->CheckBreak());

+  if (final)

+  {

+    UInt64 rating = BenchProps.GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);

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

+  }

+  return S_OK;

+}

+

+void CBenchCallbackToPrint::Print(const char *s)

+{

+  _file->Print(s);

+}

+

+void CBenchCallbackToPrint::NewLine()

+{

+  _file->NewLine();

+}

+

+void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size)

+{

+  f.Print(s);

+  int numSpaces = size - MyStringLen(s);

+  if (numSpaces > 0)

+    PrintSpaces(f, numSpaces);

+}

+

+void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size)

+{

+  int numSpaces = size - MyStringLen(s);

+  if (numSpaces > 0)

+    PrintSpaces(f, numSpaces);

+  f.Print(s);

+}

+

+static HRESULT TotalBench(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    UInt64 complexInCommands,

+    UInt32 numThreads, bool forceUnpackSize, UInt32 unpackSize, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback)

+{

+  for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)

+  {

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

+

+    UInt32 unpackSize2 = unpackSize;

+    if (!forceUnpackSize && bench.DictBits == 0)

+      unpackSize2 = kFilterUnpackSize;

+

+    HRESULT res = MethodBench(

+        EXTERNAL_CODECS_LOC_VARS

+        complexInCommands,

+        false, numThreads, method, unpackSize2, bench.DictBits,

+        printCallback, callback, &callback->BenchProps);

+    if (res == E_NOTIMPL)

+    {

+      // callback->Print(" ---");

+      // we need additional empty line as line for decompression results

+      if (!callback->Use2Columns)

+        callback->NewLine();

+    }

+    else

+    {

+      RINOK(res);

+    }

+    callback->NewLine();

+  }

+  return S_OK;

+}

+

+

+static HRESULT FreqBench(

+    UInt64 complexInCommands,

+    UInt32 numThreads,

+    IBenchPrintCallback *_file,

+    bool showFreq,

+    UInt64 &cpuFreq,

+    UInt32 &res)

+{

+  res = 0;

+  cpuFreq = 0;

+

+  UInt32 bufferSize = 1 << 20;

+  UInt32 complexity = kNumFreqCommands;

+  if (numThreads == 0)

+    numThreads = 1;

+

+  #ifdef _7ZIP_ST

+  numThreads = 1;

+  #endif

+

+  UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize);

+  UInt64 numIterations = complexInCommands / complexity / bsize;

+  if (numIterations == 0)

+    numIterations = 1;

+

+  CBenchInfoCalc progressInfoSpec;

+

+  #ifndef _7ZIP_ST

+  CFreqThreads threads;

+  if (numThreads > 1)

+  {

+    threads.Items = new CFreqInfo[numThreads];

+    UInt32 i;

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

+    {

+      CFreqInfo &info = threads.Items[i];

+      info.Callback = _file;

+      info.CallbackRes = S_OK;

+      info.NumIterations = numIterations;

+      info.Size = bufferSize;

+    }

+    progressInfoSpec.SetStartTime();

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

+    {

+      CFreqInfo &info = threads.Items[i];

+      RINOK(info.Thread.Create(FreqThreadFunction, &info));

+      threads.NumThreads++;

+    }

+    threads.WaitAll();

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

+    {

+      RINOK(threads.Items[i].CallbackRes);

+    }

+  }

+  else

+  #endif

+  {

+    progressInfoSpec.SetStartTime();

+    UInt32 sum = g_BenchCpuFreqTemp;

+    for (UInt64 k = numIterations; k > 0; k--)

+    {

+      RINOK(_file->CheckBreak());

+      sum = CountCpuFreq(sum, bufferSize, g_BenchCpuFreqTemp);

+    }

+    res += sum;

+  }

+  CBenchInfo info;

+  progressInfoSpec.SetFinishTime(info);

+

+  info.UnpackSize = 0;

+  info.PackSize = 0;

+  info.NumIterations = 1;

+

+  if (_file)

+  {

+    {

+      UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity;

+      UInt64 rating = info.GetSpeed(numCommands);

+      cpuFreq = rating / numThreads;

+      PrintResults(_file, info, rating, showFreq, showFreq ? cpuFreq : 0, NULL);

+    }

+    RINOK(_file->CheckBreak());

+  }

+

+  return S_OK;

+}

+

+

+

+static HRESULT CrcBench(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    UInt64 complexInCommands,

+    UInt32 numThreads, UInt32 bufferSize,

+    UInt64 &speed,

+    UInt32 complexity,

+    const UInt32 *checkSum,

+    const COneMethodInfo &method,

+    IBenchPrintCallback *_file,

+    CTotalBenchRes *encodeRes,

+    bool showFreq, UInt64 cpuFreq)

 {

   if (numThreads == 0)

     numThreads = 1;

 

+  #ifdef _7ZIP_ST

+  numThreads = 1;

+  #endif

+

+  UString methodName = method.MethodName;

+  // methodName.RemoveChar(L'-');

+  CMethodId hashID;

+  if (!FindHashMethod(

+      EXTERNAL_CODECS_LOC_VARS

+      methodName, hashID))

+    return E_NOTIMPL;

+

   CBenchBuffer buffer;

   size_t totalSize = (size_t)bufferSize * numThreads;

   if (totalSize / numThreads != bufferSize)

@@ -980,9 +1920,13 @@
 

   Byte *buf = buffer.Buffer;

   CBaseRandomGenerator RG;

-  UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1;

+  UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize);

+  UInt64 numIterations = complexInCommands * 256 / complexity / bsize;

+  if (numIterations == 0)

+    numIterations = 1;

 

-  UInt64 timeVal;

+  CBenchInfoCalc progressInfoSpec;

+

   #ifndef _7ZIP_ST

   CCrcThreads threads;

   if (numThreads > 1)

@@ -992,13 +1936,32 @@
     for (i = 0; i < numThreads; i++)

     {

       CCrcInfo &info = threads.Items[i];

+      UString name;

+      RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher));

+      if (!info.Hasher)

+        return E_NOTIMPL;

+      CMyComPtr<ICompressSetCoderProperties> scp;

+      info.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);

+      if (scp)

+      {

+        UInt64 reduceSize = 1;

+        RINOK(method.SetCoderProps(scp, &reduceSize));

+      }

+

       Byte *data = buf + (size_t)bufferSize * i;

+      info.Callback = _file;

       info.Data = data;

-      info.NumCycles = numCycles;

+      info.NumIterations = numIterations;

       info.Size = bufferSize;

-      info.Crc = RandGenCrc(data, bufferSize, RG);

+      /* info.Crc = */ RandGenCrc(data, bufferSize, RG);

+      info.CheckSumDefined = false;

+      if (checkSum)

+      {

+        info.CheckSum = *checkSum;

+        info.CheckSumDefined = (checkSum && (i == 0));

+      }

     }

-    timeVal = GetTimeCount();

+    progressInfoSpec.SetStartTime();

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

     {

       CCrcInfo &info = threads.Items[i];

@@ -1007,22 +1970,575 @@
     }

     threads.WaitAll();

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

-      if (!threads.Items[i].Res)

-        return S_FALSE;

+    {

+      RINOK(threads.Items[i].Res);

+    }

   }

   else

   #endif

   {

-    UInt32 crc = RandGenCrc(buf, bufferSize, RG);

-    timeVal = GetTimeCount();

-    if (!CrcBig(buf, bufferSize, numCycles, crc))

-      return S_FALSE;

+    /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG);

+    progressInfoSpec.SetStartTime();

+    CMyComPtr<IHasher> hasher;

+    UString name;

+    RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher));

+    if (!hasher)

+      return E_NOTIMPL;

+    CMyComPtr<ICompressSetCoderProperties> scp;

+    hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);

+    if (scp)

+    {

+      UInt64 reduceSize = 1;

+      RINOK(method.SetCoderProps(scp, &reduceSize));

+    }

+    RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file));

   }

-  timeVal = GetTimeCount() - timeVal;

-  if (timeVal == 0)

-    timeVal = 1;

+  CBenchInfo info;

+  progressInfoSpec.SetFinishTime(info);

 

-  UInt64 size = (UInt64)numCycles * totalSize;

-  speed = MyMultDiv64(size, timeVal, GetFreq());

+  UInt64 unpSize = numIterations * bufferSize;

+  UInt64 unpSizeThreads = unpSize * numThreads;

+  info.UnpackSize = unpSizeThreads;

+  info.PackSize = unpSizeThreads;

+  info.NumIterations = 1;

+

+  if (_file)

+  {

+    {

+      UInt64 numCommands = unpSizeThreads * complexity / 256;

+      UInt64 rating = info.GetSpeed(numCommands);

+      PrintResults(_file, info, rating, showFreq, cpuFreq, encodeRes);

+    }

+    RINOK(_file->CheckBreak());

+  }

+

+  speed = info.GetSpeed(unpSizeThreads);

+

+  return S_OK;

+}

+

+static HRESULT TotalBench_Hash(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    UInt64 complexInCommands,

+    UInt32 numThreads, UInt32 bufSize,

+    IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback,

+    CTotalBenchRes *encodeRes,

+    bool showFreq, UInt64 cpuFreq)

+{

+  for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)

+  {

+    const CBenchHash &bench = g_Hash[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));

+

+    UInt64 speed;

+    HRESULT res = CrcBench(

+        EXTERNAL_CODECS_LOC_VARS

+        complexInCommands,

+        numThreads, bufSize,

+        speed,

+        bench.Complex, &bench.CheckSum, method,

+        printCallback, encodeRes, showFreq, cpuFreq);

+    if (res == E_NOTIMPL)

+    {

+      // callback->Print(" ---");

+    }

+    else

+    {

+      RINOK(res);

+    }

+    callback->NewLine();

+  }

+  return S_OK;

+}

+

+struct CTempValues

+{

+  UInt64 *Values;

+  CTempValues(UInt32 num) { Values = new UInt64[num]; }

+  ~CTempValues() { delete []Values; }

+};

+

+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)

+{

+  const wchar_t *end;

+  UInt64 result = ConvertStringToUInt64(s, &end);

+  if (*end != 0 || s.IsEmpty())

+    prop = s;

+  else if (result <= (UInt32)0xFFFFFFFF)

+    prop = (UInt32)result;

+  else

+    prop = result;

+}

+

+static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads)

+{

+  if (i < 2)

+    return i + 1;

+  i -= 1;

+  UInt32 num = (UInt32)(2 + (i & 1)) << (i >> 1);

+  return (num <= numThreads) ? num : numThreads;

+}

+

+static bool AreSameMethodNames(const char *fullName, const wchar_t *shortName)

+{

+  for (;;)

+  {

+    wchar_t c2 = *shortName++;

+    if (c2 == 0)

+      return true;

+    char c1 = *fullName++;

+    if ((unsigned char)MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))

+      return false;

+  }

+}

+

+HRESULT Bench(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    IBenchPrintCallback *printCallback,

+    IBenchCallback *benchCallback,

+    const CObjectVector<CProperty> &props,

+    UInt32 numIterations,

+    bool multiDict)

+{

+  if (!CrcInternalTest())

+    return S_FALSE;

+

+  UInt32 numCPUs = 1;

+  UInt64 ramSize = (UInt64)512 << 20;

+  #ifndef _7ZIP_ST

+  numCPUs = NSystem::GetNumberOfProcessors();

+  #endif

+  #if !defined(_7ZIP_ST) || defined(_WIN32)

+  ramSize = NSystem::GetRamSize();

+  #endif

+  UInt32 numThreads = numCPUs;

+

+  UInt32 testTime = kComplexInSeconds;

+

+  COneMethodInfo method;

+  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 (!property.Value.IsEmpty())

+      ParseNumberString(property.Value, propVariant);

+    if (name.IsEqualTo("testtime"))

+    {

+      RINOK(ParsePropToUInt32(L"", propVariant, testTime));

+      continue;

+    }

+    if (name.IsPrefixedBy(L"mt"))

+    {

+      #ifndef _7ZIP_ST

+      RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads));

+      #endif

+      continue;

+    }

+    RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));

+  }

+

+  if (printCallback)

+  {

+    printCallback->Print("CPU Freq:");

+  }

+

+  UInt64 complexInCommands = kComplexInCommands;

+

+  if (printCallback)

+  {

+    UInt64 numMilCommands = (1 << 6);

+

+    for (int jj = 0;; jj++)

+    {

+      UInt64 start = ::GetTimeCount();

+      UInt32 sum = (UInt32)start;

+      sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp);

+      start = ::GetTimeCount() - start;

+      if (start == 0)

+        start = 1;

+      UInt64 freq = GetFreq();

+      UInt64 mipsVal = numMilCommands * freq / start;

+      if (printCallback)

+        PrintNumber(*printCallback, mipsVal, 5 + ((sum >> 31) & 1));

+      if (jj >= 3)

+      {

+        SetComplexCommands(testTime, mipsVal * 1000000, complexInCommands);

+        if (jj >= 8 || start >= freq)

+          break;

+        // break; // change it

+        numMilCommands <<= 1;

+      }

+    }

+  }

+  if (printCallback)

+  {

+    printCallback->NewLine();

+    printCallback->NewLine();

+    PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs);

+  }

+

+  if (numThreads < 1 || numThreads > kNumThreadsMax)

+    return E_INVALIDARG;

+

+  UInt32 dict;

+  bool dictIsDefined = method.Get_DicSize(dict);

+

+  if (method.MethodName.IsEmpty())

+    method.MethodName = L"LZMA";

+

+  if (benchCallback)

+  {

+    CBenchProps benchProps;

+    benchProps.SetLzmaCompexity();

+    UInt32 dictSize = method.Get_Lzma_DicSize();

+    UInt32 uncompressedDataSize = kAdditionalSize + dictSize;

+    return MethodBench(

+        EXTERNAL_CODECS_LOC_VARS

+        complexInCommands,

+        true, numThreads,

+        method, uncompressedDataSize,

+        kOldLzmaDictBits, printCallback, benchCallback, &benchProps);

+  }

+

+  UString methodName = method.MethodName;

+  if (methodName.IsEqualToNoCase(L"CRC"))

+    methodName = L"crc32";

+  method.MethodName = methodName;

+  CMethodId hashID;

+  if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID))

+  {

+    if (!printCallback)

+      return S_FALSE;

+    IBenchPrintCallback &f = *printCallback;

+    if (!dictIsDefined)

+      dict = (1 << 24);

+

+

+    // methhodName.RemoveChar(L'-');

+    UInt32 complexity = 10000;

+    const UInt32 *checkSum = NULL;

+    {

+      for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)

+      {

+        const CBenchHash &h = g_Hash[i];

+        if (AreSameMethodNames(h.Name, methodName))

+        {

+          complexity = h.Complex;

+          checkSum = &h.CheckSum;

+          if (strcmp(h.Name, "CRC32:4") != 0)

+            break;

+        }

+      }

+    }

+

+    f.NewLine();

+    f.Print("Size");

+    const int kFieldSize_CrcSpeed = 6;

+    unsigned numThreadsTests = 0;

+    for (;;)

+    {

+      UInt32 t = GetNumThreadsNext(numThreadsTests, numThreads);

+      PrintNumber(f, t, kFieldSize_CrcSpeed);

+      numThreadsTests++;

+      if (t >= numThreads)

+        break;

+    }

+    f.NewLine();

+    f.NewLine();

+    CTempValues speedTotals(numThreadsTests);

+    {

+      for (unsigned ti = 0; ti < numThreadsTests; ti++)

+        speedTotals.Values[ti] = 0;

+    }

+    

+    UInt64 numSteps = 0;

+    for (UInt32 i = 0; i < numIterations; i++)

+    {

+      for (unsigned pow = 10; pow < 32; pow++)

+      {

+        UInt32 bufSize = (UInt32)1 << pow;

+        if (bufSize > dict)

+          break;

+        char s[16];

+        ConvertUInt32ToString(pow, s);

+        int pos = MyStringLen(s);

+        s[pos++] = ':';

+        s[pos++] = ' ';

+        s[pos] = 0;

+        f.Print(s);

+

+        for (unsigned ti = 0; ti < numThreadsTests; ti++)

+        {

+          RINOK(f.CheckBreak());

+          UInt32 t = GetNumThreadsNext(ti, numThreads);

+          UInt64 speed = 0;

+          RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands,

+              t, bufSize, speed, complexity,

+              (pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0));

+          PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed);

+          speedTotals.Values[ti] += speed;

+        }

+        f.NewLine();

+        numSteps++;

+      }

+    }

+    if (numSteps != 0)

+    {

+      f.NewLine();

+      f.Print("Avg:");

+      for (unsigned ti = 0; ti < numThreadsTests; ti++)

+      {

+        PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), kFieldSize_CrcSpeed);

+      }

+      f.NewLine();

+    }

+    return S_OK;

+  }

+

+  bool use2Columns = false;

+

+  CBenchCallbackToPrint callback;

+  callback.Init();

+  callback._file = printCallback;

+

+  if (!dictIsDefined)

+  {

+    int dicSizeLog;

+    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)

+      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)

+        break;

+    dict = (1 << dicSizeLog);

+  }

+

+  IBenchPrintCallback &f = *printCallback;

+  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dict), "Benchmark threads:   ", numThreads);

+

+  bool totalBenchMode = (method.MethodName == L"*");

+  f.NewLine();

+

+  if (totalBenchMode)

+  {

+    callback.NameFieldSize = kFieldSize_Name;

+    use2Columns = false;

+  }

+  else

+  {

+    callback.NameFieldSize = kFieldSize_SmallName;

+    use2Columns = true;

+  }

+  callback.Use2Columns = use2Columns;

+

+  bool showFreq = false;

+  UInt64 cpuFreq = 0;

+

+  if (totalBenchMode)

+  {

+    showFreq = true;

+  }

+

+  int fileldSize = kFieldSize_TotalSize;

+  if (showFreq)

+    fileldSize += kFieldSize_EUAndEffec;

+

+  if (use2Columns)

+  {

+    PrintSpaces(f, callback.NameFieldSize);

+    PrintRight(f, "Compressing", fileldSize);

+    f.Print(kSep);

+    PrintRight(f, "Decompressing", fileldSize);

+  }

+  f.NewLine();

+  PrintLeft(f, totalBenchMode ? "Method" : "Dict", callback.NameFieldSize);

+

+  int j;

+

+  for (j = 0; j < 2; j++)

+  {

+    PrintRight(f, "Speed", kFieldSize_Speed + 1);

+    PrintRight(f, "Usage", kFieldSize_Usage + 1);

+    PrintRight(f, "R/U", kFieldSize_RU + 1);

+    PrintRight(f, "Rating", kFieldSize_Rating + 1);

+    if (showFreq)

+    {

+      PrintRight(f, "E/U", kFieldSize_EU + 1);

+      PrintRight(f, "Effec", kFieldSize_Effec + 1);

+    }

+    if (!use2Columns)

+      break;

+    if (j == 0)

+      f.Print(kSep);

+  }

+  

+  f.NewLine();

+  PrintSpaces(f, callback.NameFieldSize);

+  

+  for (j = 0; j < 2; j++)

+  {

+    PrintRight(f, "KB/s", kFieldSize_Speed + 1);

+    PrintRight(f, "%", kFieldSize_Usage + 1);

+    PrintRight(f, "MIPS", kFieldSize_RU + 1);

+    PrintRight(f, "MIPS", kFieldSize_Rating + 1);

+    if (showFreq)

+    {

+      PrintRight(f, "%", kFieldSize_EU + 1);

+      PrintRight(f, "%", kFieldSize_Effec + 1);

+    }

+    if (!use2Columns)

+      break;

+    if (j == 0)

+      f.Print(kSep);

+  }

+  

+  f.NewLine();

+  f.NewLine();

+

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

+      {

+        PrintLeft(f, "CPU", kFieldSize_Name);

+        UInt32 resVal;

+        RINOK(FreqBench(complexInCommands, numThreads, printCallback, freqTest == kNumCpuTests - 1, cpuFreq, resVal));

+        callback.NewLine();

+

+        if (freqTest == kNumCpuTests - 1)

+          SetComplexCommands(testTime, cpuFreq, complexInCommands);

+      }

+      callback.NewLine();

+

+      callback.SetFreq(true, cpuFreq);

+      res = TotalBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, dictIsDefined, dict, printCallback, &callback);

+      RINOK(res);

+

+      res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads,

+          1 << kNumHashDictBits, printCallback, &callback, &callback.EncodeRes, true, cpuFreq);

+      RINOK(res);

+

+      callback.NewLine();

+      {

+        PrintLeft(f, "CPU", kFieldSize_Name);

+        UInt32 resVal;

+        UInt64 cpuFreqLastTemp = cpuFreq;

+        RINOK(FreqBench(complexInCommands, numThreads, printCallback, false, cpuFreqLastTemp, resVal));

+        callback.NewLine();

+      }

+    }

+  }

+  else

+  {

+    bool needSetComplexity = true;

+    if (!methodName.IsEqualToNoCase(L"LZMA"))

+    {

+      for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)

+      {

+        const CBenchMethod &h = g_Bench[i];

+        AString s = h.Name;

+        if (AreSameMethodNames(h.Name, methodName))

+        {

+          callback.BenchProps.EncComplex = h.EncComplex;

+          callback.BenchProps.DecComplexCompr = h.DecComplexCompr;

+          callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;

+          needSetComplexity = false;

+          break;

+        }

+      }

+    }

+    if (needSetComplexity)

+      callback.BenchProps.SetLzmaCompexity();

+

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

+  {

+    const unsigned kStartDicLog = 22;

+    unsigned pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;

+    if (!multiDict)

+      pow = 31;

+    while (((UInt32)1 << pow) > dict && pow > 0)

+      pow--;

+    for (; ((UInt32)1 << pow) <= dict; pow++)

+    {

+      char s[16];

+      ConvertUInt32ToString(pow, s);

+      unsigned pos = MyStringLen(s);

+      s[pos++] = ':';

+      s[pos] = 0;

+      PrintLeft(f, s, kFieldSize_SmallName);

+      callback.DictSize = (UInt32)1 << pow;

+

+      COneMethodInfo method2 = method;

+

+      if (StringsAreEqualNoCase_Ascii(method2.MethodName, L"LZMA"))

+      {

+        // We add dictionary size property.

+        // method2 can have two different dictionary size properties.

+        // And last property is main.

+        NCOM::CPropVariant propVariant = (UInt32)pow;

+        RINOK(method2.ParseMethodFromPROPVARIANT(L"d", propVariant));

+      }

+

+      UInt32 uncompressedDataSize = callback.DictSize;

+      if (uncompressedDataSize >= (1 << 18))

+        uncompressedDataSize += kAdditionalSize;

+

+      HRESULT res = MethodBench(

+          EXTERNAL_CODECS_LOC_VARS

+          complexInCommands,

+          true, numThreads,

+          method2, uncompressedDataSize,

+          kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps);

+      f.NewLine();

+      RINOK(res);

+      if (!multiDict)

+        break;

+    }

+  }

+  }

+

+  PrintChars(f, '-', callback.NameFieldSize + fileldSize);

+  

+  if (use2Columns)

+  {

+    f.Print(kSep);

+    PrintChars(f, '-', fileldSize);

+  }

+  f.NewLine();

+  if (use2Columns)

+  {

+    PrintLeft(f, "Avr:", callback.NameFieldSize);

+    PrintTotals(f, showFreq, cpuFreq, callback.EncodeRes);

+    f.Print(kSep);

+    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
old mode 100755
new mode 100644
index f6e8064..6af2942
--- a/CPP/7zip/UI/Common/Bench.h
+++ b/CPP/7zip/UI/Common/Bench.h
@@ -4,6 +4,7 @@
 #define __7ZIP_BENCH_H

 

 #include "../../Common/CreateCoder.h"

+#include "../../UI/Common/Property.h"

 

 struct CBenchInfo

 {

@@ -13,30 +14,42 @@
   UInt64 UserFreq;

   UInt64 UnpackSize;

   UInt64 PackSize;

-  UInt32 NumIterations;

+  UInt64 NumIterations;

+  

   CBenchInfo(): NumIterations(0) {}

+  UInt64 GetUsage() const;

+  UInt64 GetRatingPerUsage(UInt64 rating) const;

+  UInt64 GetSpeed(UInt64 numCommands) const;

 };

 

 struct IBenchCallback

 {

+  virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0;

   virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;

   virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;

 };

 

-UInt64 GetUsage(const CBenchInfo &benchOnfo);

-UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating);

-UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size);

-UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations);

-

-HRESULT LzmaBench(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback);

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

 

 UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);

 

-bool CrcInternalTest();

-HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed);

+struct IBenchPrintCallback

+{

+  virtual void Print(const char *s) = 0;

+  virtual void NewLine() = 0;

+  virtual HRESULT CheckBreak() = 0;

+};

+

+HRESULT Bench(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    IBenchPrintCallback *printCallback,

+    IBenchCallback *benchCallback,

+    const CObjectVector<CProperty> &props,

+    UInt32 numIterations,

+    bool multiDict

+    );

 

 #endif

diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
old mode 100755
new mode 100644
index 5c46500..b568c06
--- a/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/CPP/7zip/UI/Common/DefaultName.cpp
@@ -7,13 +7,13 @@
 static UString GetDefaultName3(const UString &fileName,

     const UString &extension, const UString &addSubExtension)

 {

-  int extLength = extension.Length();

-  int fileNameLength = fileName.Length();

+  int extLength = extension.Len();

+  int fileNameLength = fileName.Len();

   if (fileNameLength > extLength + 1)

   {

     int dotPos = fileNameLength - (extLength + 1);

     if (fileName[dotPos] == '.')

-      if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)

+      if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1)))

         return fileName.Left(dotPos) + addSubExtension;

   }

   int dotPos = fileName.ReverseFind(L'.');

diff --git a/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h
old mode 100755
new mode 100644
index 3989a1f..4484c3b
--- a/CPP/7zip/UI/Common/DefaultName.h
+++ b/CPP/7zip/UI/Common/DefaultName.h
@@ -1,9 +1,9 @@
 // DefaultName.h

 

-#ifndef __DEFAULTNAME_H

-#define __DEFAULTNAME_H

+#ifndef __DEFAULT_NAME_H

+#define __DEFAULT_NAME_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

 

 UString GetDefaultName2(const UString &fileName,

     const UString &extension, const UString &addSubExtension);

diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
old mode 100755
new mode 100644
index e10d6b9..6a429ab
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -3,8 +3,12 @@
 #ifndef __DIR_ITEM_H

 #define __DIR_ITEM_H

 

-#include "Common/MyString.h"

-#include "Common/Types.h"

+#include "../../../Common/MyString.h"

+

+#include "../../../Windows/FileFind.h"

+

+#include "../../Common/UniqBlocks.h"

+

 #include "../../Archive/IArchive.h"

 

 struct CDirItem

@@ -14,11 +18,23 @@
   FILETIME ATime;

   FILETIME MTime;

   UString Name;

+  

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  // UString ShortName;

+  CByteBuffer ReparseData;

+  CByteBuffer ReparseData2; // fixed (reduced) absolute links

+

+  bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }

+  #endif

+  

   UInt32 Attrib;

   int PhyParent;

   int LogParent;

+  int SecureIndex;

+

+  bool IsAltStream;

   

-  CDirItem(): PhyParent(-1), LogParent(-1) {}

+  CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}

   bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }

 };

 

@@ -29,24 +45,64 @@
   CIntVector LogParents;

 

   UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;

+

+  void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);

+

 public:

   CObjectVector<CDirItem> Items;

 

+  bool SymLinks;

+

+  bool ScanAltStreams;

+  FStringVector ErrorPaths;

+  CRecordVector<DWORD> ErrorCodes;

+  UInt64 TotalSize;

+

+

+  #ifndef UNDER_CE

+  void 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)

+

+  CUniqBlocks SecureBlocks;

+  CByteBuffer TempSecureBuf;

+  bool _saclEnabled;

+  bool ReadSecure;

+  

+  void AddSecurityItem(const FString &path, int &secureIndex);

+

+  #endif

+

+  CDirItems();

+

   int GetNumFolders() const { return Prefixes.Size(); }

-  UString GetPhyPath(int index) const;

-  UString GetLogPath(int index) const;

+  UString GetPhyPath(unsigned index) const;

+  UString GetLogPath(unsigned index) const;

 

-  int AddPrefix(int phyParent, int logParent, const UString &prefix);

+  unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);

   void DeleteLastPrefix();

-

-  void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,

-    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);

-

-  void EnumerateDirItems2(

-    const UString &phyPrefix,

+  void EnumerateItems2(

+    const FString &phyPrefix,

     const UString &logPrefix,

-    const UStringVector &filePaths,

-    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);

+    const FStringVector &filePaths,

+    FStringVector *requestedPaths);

+

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  void FillFixedReparse();

+  #endif

 

   void ReserveDown();

 };

@@ -57,13 +113,14 @@
   FILETIME MTime;

   UString Name;

   bool IsDir;

+  bool IsAltStream;

   bool SizeDefined;

   bool MTimeDefined;

   bool Censored;

   UInt32 IndexInServer;

   int TimeType;

   

-  CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}

+  CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}

 };

 

 #endif

diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
old mode 100755
new mode 100644
index 61ecaba..198a6ae
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -2,14 +2,25 @@
 

 #include "StdAfx.h"

 

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileIO.h"

+#include "../../../Windows/FileName.h"

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+#define _USE_SECURITY_CODE

+#include "../../../Windows/SecurityUtils.h"

+#endif

+

 #include "EnumDirItems.h"

 

 using namespace NWindows;

 using namespace NFile;

 using namespace NName;

 

-void AddDirFileInfo(int phyParent, int logParent,

-    const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems)

+void AddDirFileInfo(int phyParent, int logParent, int secureIndex,

+    const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems)

 {

   CDirItem di;

   di.Size = fi.Size;

@@ -17,41 +28,46 @@
   di.ATime = fi.ATime;

   di.MTime = fi.MTime;

   di.Attrib = fi.Attrib;

+  di.IsAltStream = fi.IsAltStream;

   di.PhyParent = phyParent;

   di.LogParent = logParent;

-  di.Name = fi.Name;

+  di.SecureIndex = secureIndex;

+  di.Name = fs2us(fi.Name);

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  // di.ShortName = fs2us(fi.ShortName);

+  #endif

   dirItems.Add(di);

 }

 

 UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const

 {

   UString path;

-  int len = name.Length();

+  unsigned len = name.Len();

   int i;

   for (i = index; i >= 0; i = parents[i])

-    len += Prefixes[i].Length();

-  int totalLen = len;

+    len += Prefixes[i].Len();

+  unsigned totalLen = len;

   wchar_t *p = path.GetBuffer(len);

   p[len] = 0;

-  len -= name.Length();

-  memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t));

+  len -= name.Len();

+  memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t));

   for (i = index; i >= 0; i = parents[i])

   {

     const UString &s = Prefixes[i];

-    len -= s.Length();

-    memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t));

+    len -= s.Len();

+    memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t));

   }

   path.ReleaseBuffer(totalLen);

   return path;

 }

 

-UString CDirItems::GetPhyPath(int index) const

+UString CDirItems::GetPhyPath(unsigned index) const

 {

   const CDirItem &di = Items[index];

   return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);

 }

 

-UString CDirItems::GetLogPath(int index) const

+UString CDirItems::GetLogPath(unsigned index) const

 {

   const CDirItem &di = Items[index];

   return GetPrefixesPath(LogParents, di.LogParent, di.Name);

@@ -65,7 +81,7 @@
   Items.ReserveDown();

 }

 

-int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)

+unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)

 {

   PhyParents.Add(phyParent);

   LogParents.Add(logParent);

@@ -79,159 +95,437 @@
   Prefixes.DeleteBack();

 }

 

-void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,

-    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)

+bool InitLocalPrivileges();

+

+CDirItems::CDirItems():

+    SymLinks(false),

+    TotalSize(0)

+    #ifdef _USE_SECURITY_CODE

+    , ReadSecure(false)

+    #endif

 {

-  NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard);

+  #ifdef _USE_SECURITY_CODE

+  _saclEnabled = InitLocalPrivileges();

+  #endif

+}

+

+#ifdef _USE_SECURITY_CODE

+

+void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)

+{

+  secureIndex = -1;

+

+  SECURITY_INFORMATION securInfo =

+      DACL_SECURITY_INFORMATION |

+      GROUP_SECURITY_INFORMATION |

+      OWNER_SECURITY_INFORMATION;

+  if (_saclEnabled)

+    securInfo |= SACL_SECURITY_INFORMATION;

+

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

+    if (secureSize > TempSecureBuf.Size())

+      errorCode = ERROR_INVALID_FUNCTION;

+  }

+  else

+  {

+    errorCode = GetLastError();

+    if (errorCode == ERROR_INSUFFICIENT_BUFFER)

+    {

+      if (secureSize <= TempSecureBuf.Size())

+        errorCode = ERROR_INVALID_FUNCTION;

+      else

+      {

+        TempSecureBuf.Alloc(secureSize);

+        res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);

+        if (res)

+        {

+          if (secureSize != TempSecureBuf.Size())

+            errorCode = ERROR_INVALID_FUNCTION;;

+        }

+        else

+          errorCode = GetLastError();

+      }

+    }

+  }

+  if (res)

+  {

+    secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize);

+    return;

+  }

+  if (errorCode == 0)

+    errorCode = ERROR_INVALID_FUNCTION;

+  AddError(path, errorCode);

+}

+

+#endif

+

+void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)

+{

+  NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);

   for (;;)

   {

-    NFind::CFileInfoW fi;

+    NFind::CFileInfo fi;

     bool found;

     if (!enumerator.Next(fi, found))

     {

-      errorCodes.Add(::GetLastError());

-      errorPaths.Add(phyPrefix);

+      AddError(phyPrefix);

       return;

     }

     if (!found)

       break;

-    AddDirFileInfo(phyParent, logParent, fi, Items);

+

+    int secureIndex = -1;

+    #ifdef _USE_SECURITY_CODE

+    if (ReadSecure)

+      AddSecurityItem(phyPrefix + fi.Name, secureIndex);

+    #endif

+    

+    AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items);

+    

     if (fi.IsDir())

     {

-      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;

-      int parent = AddPrefix(phyParent, logParent, name2);

-      EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes);

+      const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;

+      unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2));

+      EnumerateDir(parent, parent, phyPrefix + name2);

     }

   }

 }

 

-void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix,

-    const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)

+void CDirItems::EnumerateItems2(

+    const FString &phyPrefix,

+    const UString &logPrefix,

+    const FStringVector &filePaths,

+    FStringVector *requestedPaths)

 {

-  int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix);

+  int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix));

   int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);

 

-  for (int i = 0; i < filePaths.Size(); i++)

+  FOR_VECTOR (i, filePaths)

   {

-    const UString &filePath = filePaths[i];

-    NFind::CFileInfoW fi;

-    const UString phyPath = phyPrefix + filePath;

+    const FString &filePath = filePaths[i];

+    NFind::CFileInfo fi;

+    const FString phyPath = phyPrefix + filePath;

     if (!fi.Find(phyPath))

     {

-      errorCodes.Add(::GetLastError());

-      errorPaths.Add(phyPath);

+      AddError(phyPath);

       continue;

     }

-    int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter);

-    UString phyPrefixCur;

+    if (requestedPaths)

+      requestedPaths->Add(phyPath);

+

+    int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR);

+    FString phyPrefixCur;

     int phyParentCur = phyParent;

     if (delimiter >= 0)

     {

-      phyPrefixCur = filePath.Left(delimiter + 1);

-      phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur);

+      phyPrefixCur.SetFrom(filePath, delimiter + 1);

+      phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));

     }

-    AddDirFileInfo(phyParentCur, logParent, fi, Items);

+

+    int secureIndex = -1;

+    #ifdef _USE_SECURITY_CODE

+    if (ReadSecure)

+      AddSecurityItem(phyPath, secureIndex);

+    #endif

+

+    AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items);

+    

     if (fi.IsDir())

     {

-      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;

-      int parent = AddPrefix(phyParentCur, logParent, name2);

-      EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes);

+      const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;

+      unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));

+      EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2);

     }

   }

   ReserveDown();

 }

 

-static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,

-    int phyParent, int logParent, const UString &phyPrefix,

-    const UStringVector &addArchivePrefix,

-    CDirItems &dirItems,

-    bool enterToSubFolders,

-    IEnumDirItemCallback *callback,

-    UStringVector &errorPaths,

-    CRecordVector<DWORD> &errorCodes);

 

-static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode,

-    int phyParent, int logParent, const UString &curFolderName,

-    const UString &phyPrefix,

+

+

+

+

+static HRESULT EnumerateDirItems(

+    const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const FString &phyPrefix,

     const UStringVector &addArchivePrefix,

     CDirItems &dirItems,

     bool enterToSubFolders,

-    IEnumDirItemCallback *callback,

-    UStringVector &errorPaths,

-    CRecordVector<DWORD> &errorCodes)

-  

+    IEnumDirItemCallback *callback);

+

+static HRESULT EnumerateDirItems_Spec(

+    const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const FString &curFolderName,

+    const FString &phyPrefix,

+    const UStringVector &addArchivePrefix,

+    CDirItems &dirItems,

+    bool enterToSubFolders,

+    IEnumDirItemCallback *callback)

 {

-  const UString name2 = curFolderName + (wchar_t)kDirDelimiter;

-  int parent = dirItems.AddPrefix(phyParent, logParent, name2);

-  int numItems = dirItems.Items.Size();

-  HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2,

-    addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes);

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

   if (numItems == dirItems.Items.Size())

     dirItems.DeleteLastPrefix();

   return res;

 }

 

+#ifndef UNDER_CE

 

-static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,

-    int phyParent, int logParent, const UString &phyPrefix,

+static void EnumerateAltStreams(

+    const NFind::CFileInfo &fi,

+    const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const FString &phyPrefix,

+    const UStringVector &addArchivePrefix,  // prefix from curNode

+    CDirItems &dirItems)

+{

+  const FString fullPath = phyPrefix + fi.Name;

+  NFind::CStreamEnumerator enumerator(fullPath);

+  for (;;)

+  {

+    NFind::CStreamInfo si;

+    bool found;

+    if (!enumerator.Next(si, found))

+    {

+      dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL);

+      break;

+    }

+    if (!found)

+      break;

+    if (si.IsMainStream())

+      continue;

+    UStringVector addArchivePrefixNew = addArchivePrefix;

+    UString reducedName = si.GetReducedName();

+    addArchivePrefixNew.Back() += reducedName;

+    if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true))

+      continue;

+    NFind::CFileInfo fi2 = fi;

+    fi2.Name += us2fs(reducedName);

+    fi2.Size = si.Size;

+    fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;

+    fi2.IsAltStream = true;

+    AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items);

+    dirItems.TotalSize += fi2.Size;

+  }

+}

+

+void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,

+    const FString &phyPrefix)

+{

+  if (!SymLinks || !fi.HasReparsePoint())

+    return;

+  const FString path = phyPrefix + fi.Name;

+  CByteBuffer &buf = dirItem.ReparseData;

+  if (NIO::GetReparseData(path, buf))

+  {

+    CReparseAttr attr;

+    if (attr.Parse(buf, buf.Size()))

+      return;

+  }

+  AddError(path);

+  buf.Free();

+}

+

+#endif

+

+static HRESULT EnumerateForItem(

+    NFind::CFileInfo &fi,

+    const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const FString &phyPrefix,

     const UStringVector &addArchivePrefix,  // prefix from curNode

     CDirItems &dirItems,

     bool enterToSubFolders,

-    IEnumDirItemCallback *callback,

-    UStringVector &errorPaths,

-    CRecordVector<DWORD> &errorCodes)

+    IEnumDirItemCallback *callback)

+{

+  const UString name = fs2us(fi.Name);

+  bool enterToSubFolders2 = enterToSubFolders;

+  UStringVector addArchivePrefixNew = addArchivePrefix;

+  addArchivePrefixNew.Add(name);

+  {

+    UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);

+    if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))

+      return S_OK;

+  }

+  int dirItemIndex = -1;

+  

+  if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))

+  {

+    int secureIndex = -1;

+    #ifdef _USE_SECURITY_CODE

+    if (dirItems.ReadSecure)

+      dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex);

+    #endif

+    

+    dirItemIndex = dirItems.Items.Size();

+    AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);

+    dirItems.TotalSize += fi.Size;

+    if (fi.IsDir())

+      enterToSubFolders2 = true;

+  }

+

+  #ifndef UNDER_CE

+  if (dirItems.ScanAltStreams)

+  {

+    EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,

+        addArchivePrefixNew, dirItems);

+  }

+

+  if (dirItemIndex >= 0)

+  {

+    CDirItem &dirItem = dirItems.Items[dirItemIndex];

+    dirItems.SetLinkInfo(dirItem, fi, phyPrefix);

+    if (dirItem.ReparseData.Size() != 0)

+      return S_OK;

+  }

+  #endif

+  

+  if (!fi.IsDir())

+    return S_OK;

+  

+  const NWildcard::CCensorNode *nextNode = 0;

+  if (addArchivePrefix.IsEmpty())

+  {

+    int index = curNode.FindSubNode(name);

+    if (index >= 0)

+      nextNode = &curNode.SubNodes[index];

+  }

+  if (!enterToSubFolders2 && nextNode == 0)

+    return S_OK;

+  

+  addArchivePrefixNew = addArchivePrefix;

+  if (nextNode == 0)

+  {

+    nextNode = &curNode;

+    addArchivePrefixNew.Add(name);

+  }

+  

+  return EnumerateDirItems_Spec(

+      *nextNode, phyParent, logParent, fi.Name, phyPrefix,

+      addArchivePrefixNew,

+      dirItems,

+      enterToSubFolders2, callback);

+}

+

+

+static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)

+{

+  FOR_VECTOR (i, curNode.IncludeItems)

+  {

+    const NWildcard::CItem &item = curNode.IncludeItems[i];

+    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,

+       and wildcard mode is disabled, we can ignore wildcard in name */

+    /*

+    if (!item.WildcardParsing)

+      continue;

+    */

+    if (DoesNameContainWildcard(name))

+      return false;

+  }

+  return true;

+}

+

+

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

 {

   if (!enterToSubFolders)

     if (curNode.NeedCheckSubDirs())

       enterToSubFolders = true;

   if (callback)

-    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));

+    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));

 

   // try direct_names case at first

   if (addArchivePrefix.IsEmpty() && !enterToSubFolders)

   {

-    // check that all names are direct

-    int i;

-    for (i = 0; i < curNode.IncludeItems.Size(); i++)

-    {

-      const NWildcard::CItem &item = curNode.IncludeItems[i];

-      if (item.Recursive || item.PathParts.Size() != 1)

-        break;

-      const UString &name = item.PathParts.Front();

-      if (name.IsEmpty() || DoesNameContainWildCard(name))

-        break;

-    }

-    if (i == curNode.IncludeItems.Size())

+    if (CanUseFsDirect(curNode))

     {

       // all names are direct (no wildcards)

       // so we don't need file_system's dir enumerator

       CRecordVector<bool> needEnterVector;

+      unsigned i;

+

       for (i = 0; i < curNode.IncludeItems.Size(); i++)

       {

         const NWildcard::CItem &item = curNode.IncludeItems[i];

         const UString &name = item.PathParts.Front();

-        const UString fullPath = phyPrefix + name;

-        NFind::CFileInfoW fi;

+        const FString fullPath = phyPrefix + us2fs(name);

+        NFind::CFileInfo fi;

+        #ifdef _WIN32

+        if (phyPrefix.IsEmpty() && item.IsDriveItem())

+        {

+          fi.SetAsDir();

+          fi.Name = fullPath;

+        }

+        else

+        #endif

         if (!fi.Find(fullPath))

         {

-          errorCodes.Add(::GetLastError());

-          errorPaths.Add(fullPath);

+          dirItems.AddError(fullPath);

           continue;

         }

         bool isDir = fi.IsDir();

         if (isDir && !item.ForDir || !isDir && !item.ForFile)

         {

-          errorCodes.Add((DWORD)E_FAIL);

-          errorPaths.Add(fullPath);

+          dirItems.AddError(fullPath, (DWORD)E_FAIL);

           continue;

         }

         {

           UStringVector pathParts;

-          pathParts.Add(fi.Name);

+          pathParts.Add(fs2us(fi.Name));

           if (curNode.CheckPathToRoot(false, pathParts, !isDir))

             continue;

         }

-        AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);

+        

+        int secureIndex = -1;

+        #ifdef _USE_SECURITY_CODE

+        if (dirItems.ReadSecure)

+          dirItems.AddSecurityItem(fullPath, secureIndex);

+        #endif

+

+        AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);

+

+        #ifndef UNDER_CE

+        {

+          CDirItem &dirItem = dirItems.Items.Back();

+          dirItems.SetLinkInfo(dirItem, fi, phyPrefix);

+          if (dirItem.ReparseData.Size() != 0)

+            continue;

+        }

+        #endif

+

+        dirItems.TotalSize += fi.Size;

+

+        #ifndef UNDER_CE

+        if (dirItems.ScanAltStreams)

+        {

+          UStringVector pathParts;

+          pathParts.Add(fs2us(fi.Name));

+          EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,

+              pathParts, dirItems);

+        }

+        #endif

+

         if (!isDir)

           continue;

         

@@ -252,110 +546,212 @@
         }

 

         RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,

-            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));

+            addArchivePrefixNew, dirItems, true, callback));

       }

+      

       for (i = 0; i < curNode.SubNodes.Size(); i++)

       {

         if (i < needEnterVector.Size())

           if (!needEnterVector[i])

             continue;

         const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];

-        const UString fullPath = phyPrefix + nextNode.Name;

-        NFind::CFileInfoW fi;

+        const FString fullPath = phyPrefix + us2fs(nextNode.Name);

+        NFind::CFileInfo fi;

+        #ifdef _WIN32

+        if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name))

+        {

+          fi.SetAsDir();

+          fi.Name = fullPath;

+        }

+        else

+        #endif

         if (!fi.Find(fullPath))

         {

           if (!nextNode.AreThereIncludeItems())

             continue;

-          errorCodes.Add(::GetLastError());

-          errorPaths.Add(fullPath);

+          dirItems.AddError(fullPath);

           continue;

         }

         if (!fi.IsDir())

         {

-          errorCodes.Add((DWORD)E_FAIL);

-          errorPaths.Add(fullPath);

+          dirItems.AddError(fullPath, (DWORD)E_FAIL);

           continue;

         }

 

         RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,

-            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));

+            UStringVector(), dirItems, false, callback));

       }

+

       return S_OK;

     }

   }

 

+  #ifdef _WIN32

+  #ifndef UNDER_CE

 

-  NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard));

-  for (int ttt = 0; ; ttt++)

+  // scan drives, if wildcard is "*:\"

+

+  if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0)

   {

-    NFind::CFileInfoW fi;

+    unsigned i;

+    for (i = 0; i < curNode.IncludeItems.Size(); i++)

+    {

+      const NWildcard::CItem &item = curNode.IncludeItems[i];

+      if (item.PathParts.Size() < 1)

+        break;

+      const UString &name = item.PathParts.Front();

+      if (name.Len() != 2 || name[1] != ':')

+        break;

+      if (item.PathParts.Size() == 1)

+        if (item.ForFile || !item.ForDir)

+          break;

+      if (NWildcard::IsDriveColonName(name))

+        continue;

+      if (name[0] != '*' && name[0] != '?')

+        break;

+    }

+    if (i == curNode.IncludeItems.Size())

+    {

+      FStringVector driveStrings;

+      NFind::MyGetLogicalDriveStrings(driveStrings);

+      for (i = 0; i < driveStrings.Size(); i++)

+      {

+        FString driveName = driveStrings[i];

+        if (driveName.Len() < 3 || driveName.Back() != '\\')

+          return E_FAIL;

+        driveName.DeleteBack();

+        NFind::CFileInfo fi;

+        fi.SetAsDir();

+        fi.Name = driveName;

+

+        RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,

+            addArchivePrefix, dirItems, enterToSubFolders, callback));

+      }

+      return S_OK;

+    }

+  }

+  

+  #endif

+  #endif

+

+  NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);

+  for (unsigned ttt = 0; ; ttt++)

+  {

+    NFind::CFileInfo fi;

     bool found;

     if (!enumerator.Next(fi, found))

     {

-      errorCodes.Add(::GetLastError());

-      errorPaths.Add(phyPrefix);

+      dirItems.AddError(phyPrefix);

       break;

     }

     if (!found)

       break;

 

     if (callback && (ttt & 0xFF) == 0xFF)

-      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));

-    const UString &name = fi.Name;

-    bool enterToSubFolders2 = enterToSubFolders;

-    UStringVector addArchivePrefixNew = addArchivePrefix;

-    addArchivePrefixNew.Add(name);

-    {

-      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);

-      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))

-        continue;

-    }

-    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))

-    {

-      AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);

-      if (fi.IsDir())

-        enterToSubFolders2 = true;

-    }

-    if (!fi.IsDir())

-      continue;

+      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));

 

-    const NWildcard::CCensorNode *nextNode = 0;

-    if (addArchivePrefix.IsEmpty())

-    {

-      int index = curNode.FindSubNode(name);

-      if (index >= 0)

-        nextNode = &curNode.SubNodes[index];

-    }

-    if (!enterToSubFolders2 && nextNode == 0)

-      continue;

-

-    addArchivePrefixNew = addArchivePrefix;

-    if (nextNode == 0)

-    {

-      nextNode = &curNode;

-      addArchivePrefixNew.Add(name);

-    }

-

-    RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix,

-        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));

+    RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,

+          addArchivePrefix, dirItems, enterToSubFolders, callback));

   }

   return S_OK;

 }

 

 HRESULT EnumerateItems(

     const NWildcard::CCensor &censor,

+    const NWildcard::ECensorPathMode pathMode,

+    const UString &addPathPrefix,

     CDirItems &dirItems,

-    IEnumDirItemCallback *callback,

-    UStringVector &errorPaths,

-    CRecordVector<DWORD> &errorCodes)

+    IEnumDirItemCallback *callback)

 {

-  for (int i = 0; i < censor.Pairs.Size(); i++)

+  FOR_VECTOR (i, censor.Pairs)

   {

     const NWildcard::CPair &pair = censor.Pairs[i];

     int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);

-    RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false,

-        callback, errorPaths, errorCodes));

+    int logParent = -1;

+    

+    if (pathMode == NWildcard::k_AbsPath)

+      logParent = phyParent;

+    else

+    {

+      if (!addPathPrefix.IsEmpty())

+        logParent = dirItems.AddPrefix(-1, -1, addPathPrefix);

+    }

+    

+    RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),

+        dirItems,

+        false, // enterToSubFolders

+        callback));

   }

   dirItems.ReserveDown();

+

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  dirItems.FillFixedReparse();

+  #endif

+

   return S_OK;

 }

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+void CDirItems::FillFixedReparse()

+{

+  /* imagex/WIM reduces absolute pathes in links (raparse data),

+     if we archive non root folder. We do same thing here */

+

+  if (!SymLinks)

+    return;

+  

+  FOR_VECTOR(i, Items)

+  {

+    CDirItem &item = Items[i];

+    if (item.ReparseData.Size() == 0)

+      continue;

+    

+    CReparseAttr attr;

+    if (!attr.Parse(item.ReparseData, item.ReparseData.Size()))

+      continue;

+    if (attr.IsRelative())

+      continue;

+

+    const UString &link = attr.GetPath();

+    if (!IsDrivePath(link))

+      continue;

+    // maybe we need to support networks paths also ?

+

+    FString fullPathF;

+    if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF))

+      continue;

+    UString fullPath = fs2us(fullPathF);

+    const UString logPath = GetLogPath(i);

+    if (logPath.Len() >= fullPath.Len())

+      continue;

+    if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0)

+      continue;

+    

+    const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());

+    if (prefix.Back() != WCHAR_PATH_SEPARATOR)

+      continue;

+

+    unsigned rootPrefixSize = GetRootPrefixSize(prefix);

+    if (rootPrefixSize == 0)

+      continue;

+    if (rootPrefixSize == prefix.Len())

+      continue; // simple case: paths are from root

+

+    if (link.Len() <= prefix.Len())

+      continue;

+

+    if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0)

+      continue;

+

+    UString newLink = prefix.Left(rootPrefixSize);

+    newLink += link.Ptr(prefix.Len());

+

+    CByteBuffer data;

+    if (!FillLinkData(data, newLink, attr.IsSymLink()))

+      continue;

+    item.ReparseData2 = data;

+  }

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
old mode 100755
new mode 100644
index 835ae02..1739716
--- a/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -3,23 +3,25 @@
 #ifndef __ENUM_DIR_ITEMS_H

 #define __ENUM_DIR_ITEMS_H

 

-#include "Common/Wildcard.h"

-#include "Windows/FileFind.h"

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileFind.h"

+

 #include "DirItem.h"

 

-void AddDirFileInfo(int phyParent, int logParent,

-    const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems);

+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, const wchar_t *path) = 0;

+  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,

-    UStringVector &errorPaths,

-    CRecordVector<DWORD> &errorCodes);

+    IEnumDirItemCallback *callback);

 

 #endif

diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
old mode 100755
new mode 100644
index 2f5a293..4bbf2b3
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -2,11 +2,13 @@
 

 #include "StdAfx.h"

 

-#include <stdio.h>

+#include "../../../../C/Sort.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/PropVariant.h"

-#include "Windows/PropVariantConversions.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/PropVariant.h"

+#include "../../../Windows/PropVariantConv.h"

 

 #include "../Common/ExtractingFilePath.h"

 

@@ -14,135 +16,251 @@
 #include "SetProperties.h"

 

 using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

 

 static HRESULT DecompressArchive(

-    const CArc &arc,

+    CCodecs *codecs,

+    const CArchiveLink &arcLink,

     UInt64 packSize,

     const NWildcard::CCensorNode &wildcardCensor,

     const CExtractOptions &options,

+    bool calcCrc,

     IExtractCallbackUI *callback,

-    CArchiveExtractCallback *extractCallbackSpec,

+    CArchiveExtractCallback *ecs,

     UString &errorMessage,

     UInt64 &stdInProcessed)

 {

+  const CArc &arc = arcLink.Arcs.Back();

   stdInProcessed = 0;

   IInArchive *archive = arc.Archive;

   CRecordVector<UInt32> realIndices;

+  

+  UStringVector removePathParts;

+

+  FString outDir = options.OutputDir;

+  UString replaceName = arc.DefaultName;

+  

+  if (arcLink.Arcs.Size() > 1)

+  {

+    // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".

+    // So it extracts different archives to one folder.

+    // We will use top level archive name

+    const CArc &arc0 = arcLink.Arcs[0];

+    if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe"))

+      replaceName = arc0.DefaultName;

+  }

+

+  outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName)));

+

+  bool elimIsPossible = false;

+  UString elimPrefix; // only pure name without dir delimiter

+  FString outDirReduced = outDir;

+  

+  if (options.ElimDup.Val)

+  {

+    UString dirPrefix;

+    SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);

+    if (!elimPrefix.IsEmpty())

+    {

+      if (IsCharDirLimiter(elimPrefix.Back()))

+        elimPrefix.DeleteBack();

+      if (!elimPrefix.IsEmpty())

+      {

+        outDirReduced = us2fs(dirPrefix);

+        elimIsPossible = true;

+      }

+    }

+  }

+

   if (!options.StdInMode)

   {

     UInt32 numItems;

     RINOK(archive->GetNumberOfItems(&numItems));

     

+    UString filePath;

+

     for (UInt32 i = 0; i < numItems; i++)

     {

-      UString filePath;

       RINOK(arc.GetItemPath(i, filePath));

+

+      if (elimIsPossible && options.ElimDup.Val)

+      {

+        if (!IsPath1PrefixedByPath2(filePath, elimPrefix))

+          elimIsPossible = false;

+        else

+        {

+          wchar_t c = filePath[elimPrefix.Len()];

+          if (c != 0 && !IsCharDirLimiter(c))

+            elimIsPossible = false;

+        }

+      }

+

       bool isFolder;

-      RINOK(IsArchiveItemFolder(archive, i, isFolder));

-      if (!wildcardCensor.CheckPath(filePath, !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;

       realIndices.Add(i);

     }

+    

     if (realIndices.Size() == 0)

     {

       callback->ThereAreNoFiles();

-      return S_OK;

+      return callback->ExtractResult(S_OK);

     }

   }

 

-  UStringVector removePathParts;

+  if (elimIsPossible)

+    outDir = outDirReduced;

 

-  UString outDir = options.OutputDir;

-  outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));

   #ifdef _WIN32

   // GetCorrectFullFsPath doesn't like "..".

   // outDir.TrimRight();

   // outDir = GetCorrectFullFsPath(outDir);

   #endif

 

-  if (!outDir.IsEmpty())

-    if (!NFile::NDirectory::CreateComplexDirectory(outDir))

+  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 ") + outDir;

+      errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir);

       return res;

     }

 

-  extractCallbackSpec->Init(

+  ecs->Init(

+      options.NtOptions,

       options.StdInMode ? &wildcardCensor : NULL,

       &arc,

       callback,

-      options.StdOutMode, options.TestMode, options.CalcCrc,

+      options.StdOutMode, options.TestMode,

       outDir,

       removePathParts,

       packSize);

 

-  #if !defined(_7ZIP_ST) && !defined(_SFX)

-  RINOK(SetProperties(archive, options.Properties));

+  

+  #ifdef SUPPORT_LINKS

+  

+  if (!options.StdInMode &&

+      !options.TestMode &&

+      options.NtOptions.HardLinks.Val)

+  {

+    RINOK(ecs->PrepareHardLinks(&realIndices));

+  }

+    

   #endif

 

+  

   HRESULT result;

-  Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;

+  Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;

   if (options.StdInMode)

   {

-    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);

+    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);

     NCOM::CPropVariant prop;

     if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)

-      if (prop.vt == VT_UI8 || prop.vt == VT_UI4)

-        stdInProcessed = ConvertPropVariantToUInt64(prop);

+      ConvertPropVariantToUInt64(prop, stdInProcessed);

   }

   else

-    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);

-

+    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);

+  if (result == S_OK && !options.StdInMode)

+    result = ecs->SetDirsTimes();

   return callback->ExtractResult(result);

 }

 

-HRESULT DecompressArchives(

-    CCodecs *codecs, const CIntVector &formatIndices,

+/* v9.31: BUG was fixed:

+   Sorted list for file paths was sorted with case insensitive compare function.

+   But FindInSorted function did binary search via case sensitive compare function */

+

+int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name)

+{

+  unsigned left = 0, right = fileName.Size();

+  while (left != right)

+  {

+    unsigned mid = (left + right) / 2;

+    const UString &midValue = fileName[mid];

+    int compare = CompareFileNames(name, midValue);

+    if (compare == 0)

+      return mid;

+    if (compare < 0)

+      right = mid;

+    else

+      left = mid + 1;

+  }

+  return -1;

+}

+

+HRESULT Extract(

+    CCodecs *codecs,

+    const CObjectVector<COpenType> &types,

+    const CIntVector &excludedFormats,

     UStringVector &arcPaths, UStringVector &arcPathsFull,

     const NWildcard::CCensorNode &wildcardCensor,

     const CExtractOptions &options,

     IOpenCallbackUI *openCallback,

     IExtractCallbackUI *extractCallback,

+    #ifndef _SFX

+    IHashCalc *hash,

+    #endif

     UString &errorMessage,

     CDecompressStat &stat)

 {

   stat.Clear();

-  int i;

   UInt64 totalPackSize = 0;

-  CRecordVector<UInt64> archiveSizes;

+  CRecordVector<UInt64> arcSizes;

 

-  int numArcs = options.StdInMode ? 1 : arcPaths.Size();

+  unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();

 

+  unsigned i;

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

   {

-    NFile::NFind::CFileInfoW fi;

+    NFind::CFileInfo fi;

     fi.Size = 0;

     if (!options.StdInMode)

     {

-      const UString &arcPath = arcPaths[i];

+      const FString &arcPath = us2fs(arcPaths[i]);

       if (!fi.Find(arcPath))

         throw "there is no such archive";

       if (fi.IsDir())

         throw "can't decompress folder";

     }

-    archiveSizes.Add(fi.Size);

+    arcSizes.Add(fi.Size);

     totalPackSize += fi.Size;

   }

-  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;

-  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);

+

+  CBoolArr skipArcs(numArcs);

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

+    skipArcs[i] = false;

+

+  CArchiveExtractCallback *ecs = new CArchiveExtractCallback;

+  CMyComPtr<IArchiveExtractCallback> ec(ecs);

   bool multi = (numArcs > 1);

-  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);

+  ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode);

+  #ifndef _SFX

+  ecs->SetHashMethods(hash);

+  #endif

+

   if (multi)

   {

     RINOK(extractCallback->SetTotal(totalPackSize));

   }

+

+  UInt64 totalPackProcessed = 0;

+  bool thereAreNotOpenArcs = false;

+  

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

   {

+    if (skipArcs[i])

+      continue;

+

     const UString &arcPath = arcPaths[i];

-    NFile::NFind::CFileInfoW fi;

+    NFind::CFileInfo fi;

     if (options.StdInMode)

     {

       fi.Size = 0;

@@ -150,7 +268,7 @@
     }

     else

     {

-      if (!fi.Find(arcPath) || fi.IsDir())

+      if (!fi.Find(us2fs(arcPath)) || fi.IsDir())

         throw "there is no such archive";

     }

 

@@ -159,16 +277,17 @@
     #endif

 

     RINOK(extractCallback->BeforeOpen(arcPath));

-    CArchiveLink archiveLink;

+    CArchiveLink arcLink;

 

-    CIntVector formatIndices2 = formatIndices;

+    CObjectVector<COpenType> types2 = types;

+    /*

     #ifndef _SFX

-    if (formatIndices.IsEmpty())

+    if (types.IsEmpty())

     {

       int pos = arcPath.ReverseFind(L'.');

       if (pos >= 0)

       {

-        UString s = arcPath.Mid(pos + 1);

+        UString s = arcPath.Ptr(pos + 1);

         int index = codecs->FindFormatForExtension(s);

         if (index >= 0 && s == L"001")

         {

@@ -176,18 +295,31 @@
           pos = s.ReverseFind(L'.');

           if (pos >= 0)

           {

-            int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));

-            if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)

+            int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));

+            if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0

             {

-              formatIndices2.Add(index2);

-              formatIndices2.Add(index);

+              types2.Add(index2);

+              types2.Add(index);

             }

           }

         }

       }

     }

     #endif

-    HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);

+    */

+

+    COpenOptions op;

+    #ifndef _SFX

+    op.props = &options.Properties;

+    #endif

+    op.codecs = codecs;

+    op.types = &types2;

+    op.excludedFormats = &excludedFormats;

+    op.stdInMode = options.StdInMode;

+    op.stream = NULL;

+    op.filePath = arcPath;

+    HRESULT result = arcLink.Open2(op, openCallback);

+

     if (result == E_ABORT)

       return result;

 

@@ -196,68 +328,148 @@
     crypted = openCallback->Open_WasPasswordAsked();

     #endif

 

-    RINOK(extractCallback->OpenResult(arcPath, result, crypted));

-    if (result != S_OK)

-      continue;

+    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+      result = S_FALSE;

 

-    if (!options.StdInMode)

-    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)

+    // arcLink.Set_ErrorsText();

+    RINOK(extractCallback->OpenResult(arcPath, result, crypted));

+

+

     {

-      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);

-      if (index >= 0 && index > i)

+      FOR_VECTOR (r, arcLink.Arcs)

       {

-        arcPaths.Delete(index);

-        arcPathsFull.Delete(index);

-        totalPackSize -= archiveSizes[index];

-        archiveSizes.Delete(index);

-        numArcs = arcPaths.Size();

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

+        }

       }

     }

-    if (archiveLink.VolumePaths.Size() != 0)

+

+    if (result != S_OK)

     {

-      totalPackSize += archiveLink.VolumesSize;

-      RINOK(extractCallback->SetTotal(totalPackSize));

+      thereAreNotOpenArcs = true;

+      if (!options.StdInMode)

+      {

+        NFind::CFileInfo fi;

+        if (fi.Find(us2fs(arcPath)))

+          if (!fi.IsDir())

+            totalPackProcessed += fi.Size;

+      }

+      continue;

+    }

+

+    if (!options.StdInMode)

+    {

+      // numVolumes += arcLink.VolumePaths.Size();

+      // arcLink.VolumesSize;

+

+      // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);

+      // numArcs = arcPaths.Size();

+      if (arcLink.VolumePaths.Size() != 0)

+      {

+        Int64 correctionSize = arcLink.VolumesSize;

+        FOR_VECTOR (v, arcLink.VolumePaths)

+        {

+          int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);

+          if (index >= 0)

+          {

+            if ((unsigned)index > i)

+            {

+              skipArcs[index] = true;

+              correctionSize -= arcSizes[index];

+            }

+          }

+        }

+        if (correctionSize != 0)

+        {

+          Int64 newPackSize = (Int64)totalPackSize + correctionSize;

+          if (newPackSize < 0)

+            newPackSize = 0;

+          totalPackSize = newPackSize;

+          RINOK(extractCallback->SetTotal(totalPackSize));

+        }

+      }

     }

 

     #ifndef _NO_CRYPTO

+    bool passwordIsDefined;

     UString password;

-    RINOK(openCallback->Open_GetPasswordIfAny(password));

-    if (!password.IsEmpty())

+    RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password));

+    if (passwordIsDefined)

     {

       RINOK(extractCallback->SetPassword(password));

     }

     #endif

 

-    for (int v = 0; v < archiveLink.Arcs.Size(); v++)

+    FOR_VECTOR (k, arcLink.Arcs)

     {

-      const UString &s = archiveLink.Arcs[v].ErrorMessage;

-      if (!s.IsEmpty())

+      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 = archiveLink.Arcs.Back();

+    CArc &arc = arcLink.Arcs.Back();

     arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);

     arc.MTime = fi.MTime;

 

     UInt64 packProcessed;

-    RINOK(DecompressArchive(arc,

-        fi.Size + archiveLink.VolumesSize,

-        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));

+    bool calcCrc =

+        #ifndef _SFX

+          (hash != NULL);

+        #else

+          false;

+        #endif

+

+    RINOK(DecompressArchive(

+        codecs,

+        arcLink,

+        fi.Size + arcLink.VolumesSize,

+        wildcardCensor,

+        options,

+        calcCrc,

+        extractCallback, ecs, errorMessage, packProcessed));

     if (!options.StdInMode)

-      packProcessed = fi.Size + archiveLink.VolumesSize;

-    extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;

-    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;

+      packProcessed = fi.Size + arcLink.VolumesSize;

+    totalPackProcessed += packProcessed;

+    ecs->LocalProgressSpec->InSize += packProcessed;

+    ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;

     if (!errorMessage.IsEmpty())

       return E_FAIL;

   }

-  stat.NumFolders = extractCallbackSpec->NumFolders;

-  stat.NumFiles = extractCallbackSpec->NumFiles;

-  stat.UnpackSize = extractCallbackSpec->UnpackSize;

-  stat.CrcSum = extractCallbackSpec->CrcSum;

 

+  if (multi || thereAreNotOpenArcs)

+  {

+    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 = extractCallbackSpec->LocalProgressSpec->InSize;

+  stat.PackSize = ecs->LocalProgressSpec->InSize;

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
old mode 100755
new mode 100644
index 70926d7..d42514d
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -3,7 +3,7 @@
 #ifndef __EXTRACT_H

 #define __EXTRACT_H

 

-#include "Windows/FileFind.h"

+#include "../../../Windows/FileFind.h"

 

 #include "../../Archive/IArchive.h"

 

@@ -14,21 +14,37 @@
 

 #include "../Common/LoadCodecs.h"

 

-struct CExtractOptions

+struct CExtractOptionsBase

+{

+  CBoolPair ElimDup;

+  

+  bool PathMode_Force;

+  bool OverwriteMode_Force;

+  NExtract::NPathMode::EEnum PathMode;

+  NExtract::NOverwriteMode::EEnum OverwriteMode;

+  

+  FString OutputDir;

+  CExtractNtOptions NtOptions;

+

+  CExtractOptionsBase():

+      PathMode_Force(false),

+      OverwriteMode_Force(false),

+      PathMode(NExtract::NPathMode::kFullPaths),

+      OverwriteMode(NExtract::NOverwriteMode::kAsk)

+      {}

+};

+

+struct CExtractOptions: public CExtractOptionsBase

 {

   bool StdInMode;

   bool StdOutMode;

   bool YesToAll;

   bool TestMode;

-  bool CalcCrc;

-  NExtract::NPathMode::EEnum PathMode;

-  NExtract::NOverwriteMode::EEnum OverwriteMode;

-  UString OutputDir;

   

   // bool ShowDialog;

   // bool PasswordEnabled;

   // UString Password;

-  #if !defined(_7ZIP_ST) && !defined(_SFX)

+  #ifndef _SFX

   CObjectVector<CProperty> Properties;

   #endif

 

@@ -37,13 +53,10 @@
   #endif

 

   CExtractOptions():

+      TestMode(false),

       StdInMode(false),

       StdOutMode(false),

-      YesToAll(false),

-      TestMode(false),

-      CalcCrc(false),

-      PathMode(NExtract::NPathMode::kFullPathnames),

-      OverwriteMode(NExtract::NOverwriteMode::kAskBefore)

+      YesToAll(false)

       {}

 };

 

@@ -51,25 +64,30 @@
 {

   UInt64 NumArchives;

   UInt64 UnpackSize;

+  UInt64 AltStreams_UnpackSize;

   UInt64 PackSize;

   UInt64 NumFolders;

   UInt64 NumFiles;

-  UInt32 CrcSum;

+  UInt64 NumAltStreams;

 

   void Clear()

   {

-    NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0;

-    CrcSum = 0;

+    NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;

   }

 };

 

-HRESULT DecompressArchives(

-    CCodecs *codecs, const CIntVector &formatIndices,

+HRESULT Extract(

+    CCodecs *codecs,

+    const CObjectVector<COpenType> &types,

+    const CIntVector &excludedFormats,

     UStringVector &archivePaths, UStringVector &archivePathsFull,

     const NWildcard::CCensorNode &wildcardCensor,

     const CExtractOptions &options,

     IOpenCallbackUI *openCallback,

     IExtractCallbackUI *extractCallback,

+    #ifndef _SFX

+    IHashCalc *hash,

+    #endif

     UString &errorMessage,

     CDecompressStat &stat);

 

diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
old mode 100755
new mode 100644
index 44c4053..719aaad
--- a/CPP/7zip/UI/Common/ExtractMode.h
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -5,27 +5,29 @@
 

 namespace NExtract {

   

-  namespace NPathMode

+namespace NPathMode

+{

+  enum EEnum

   {

-    enum EEnum

-    {

-      kFullPathnames,

-      kCurrentPathnames,

-      kNoPathnames

-    };

-  }

-  

-  namespace NOverwriteMode

+    kFullPaths,

+    kCurPaths,

+    kNoPaths,

+    kAbsPaths

+  };

+}

+

+namespace NOverwriteMode

+{

+  enum EEnum

   {

-    enum EEnum

-    {

-      kAskBefore,

-      kWithoutPrompt,

-      kSkipExisting,

-      kAutoRename,

-      kAutoRenameExisting

-    };

-  }

+    kAsk,

+    kOverwrite,

+    kSkip,

+    kRename,

+    kRenameExisting

+  };

+}

+

 }

 

 #endif

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
old mode 100755
new mode 100644
index 604148a..e6947f2
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -2,26 +2,44 @@
 

 #include "StdAfx.h"

 

-#include "../../../../C/Types.h"

+#include "../../../Common/Wildcard.h"

 

-#include "Common/Wildcard.h"

+#include "../../../Windows/FileName.h"

 

 #include "ExtractingFilePath.h"

 

-static UString ReplaceIncorrectChars(const UString &s)

+static UString ReplaceIncorrectChars(const UString &s, bool repaceColon)

 {

   #ifdef _WIN32

   UString res;

-  for (int i = 0; i < s.Length(); i++)

+  bool beforeColon = true;

   {

-    wchar_t c = s[i];

-    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')

-      c = '_';

-    res += c;

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

+    }

   }

-  res.TrimRight();

-  while (!res.IsEmpty() && res[res.Length() - 1] == '.')

-    res.Delete(res.Length() - 1);

+  if (beforeColon)

+  {

+    for (int i = res.Len() - 1; i >= 0; i--)

+    {

+      wchar_t c = res[i];

+      if (c != '.' && c != ' ')

+        break;

+      res.ReplaceOneCharAtPos(i, '_');

+    }

+  }

   return res;

   #else

   return s;

@@ -29,27 +47,28 @@
 }

 

 #ifdef _WIN32

+

 static const wchar_t *g_ReservedNames[] =

 {

   L"CON", L"PRN", L"AUX", L"NUL"

 };

 

-static bool CheckTail(const UString &name, int len)

+static bool CheckTail(const UString &name, unsigned len)

 {

   int dotPos = name.Find(L'.');

   if (dotPos < 0)

-    dotPos = name.Length();

+    dotPos = name.Len();

   UString s = name.Left(dotPos);

   s.TrimRight();

-  return (s.Length() != len);

+  return s.Len() != len;

 }

 

 static bool CheckNameNum(const UString &name, const wchar_t *reservedName)

 {

-  int len = MyStringLen(reservedName);

-  if (name.Length() <= len)

+  unsigned len = MyStringLen(reservedName);

+  if (name.Len() <= len)

     return true;

-  if (name.Left(len).CompareNoCase(reservedName) != 0)

+  if (MyStringCompareNoCase_N(name, reservedName, len) != 0)

     return true;

   wchar_t c = name[len];

   if (c < L'0' || c > L'9')

@@ -59,13 +78,13 @@
 

 static bool IsSupportedName(const UString &name)

 {

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

+  for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)

   {

     const wchar_t *reservedName = g_ReservedNames[i];

-    int len = MyStringLen(reservedName);

-    if (name.Length() < len)

+    unsigned len = MyStringLen(reservedName);

+    if (name.Len() < len)

       continue;

-    if (name.Left(len).CompareNoCase(reservedName) != 0)

+    if (MyStringCompareNoCase_N(name, reservedName, len) != 0)

       continue;

     if (!CheckTail(name, len))

       return false;

@@ -74,21 +93,34 @@
     return false;

   return CheckNameNum(name, L"LPT");

 }

+

 #endif

 

-static UString GetCorrectFileName(const UString &path)

+static UString GetCorrectFileName(const UString &path, bool repaceColon)

 {

   if (path == L".." || path == L".")

     return UString();

-  return ReplaceIncorrectChars(path);

+  return ReplaceIncorrectChars(path, repaceColon);

 }

 

-void MakeCorrectPath(UStringVector &pathParts)

+void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon)

 {

-  for (int i = 0; i < pathParts.Size();)

+  for (unsigned i = 0; i < pathParts.Size();)

   {

     UString &s = pathParts[i];

-    s = GetCorrectFileName(s);

+    #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

@@ -105,7 +137,7 @@
 UString MakePathNameFromParts(const UStringVector &parts)

 {

   UString result;

-  for (int i = 0; i < parts.Size(); i++)

+  FOR_VECTOR (i, parts)

   {

     if (i != 0)

       result += WCHAR_PATH_SEPARATOR;

@@ -114,13 +146,29 @@
   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);

+  UString res = GetCorrectFileName(path, true);

   #ifdef _WIN32

   if (!IsSupportedName(res))

     res = (UString)L"_" + res;

   #endif

+  if (res.IsEmpty())

+    res = k_EmptyReplaceName;

   return res;

 }

   

@@ -128,14 +176,14 @@
 {

   UStringVector parts;

   SplitPathToParts(path, parts);

-  for (int i = 0; i < parts.Size(); i++)

+  FOR_VECTOR (i, parts)

   {

     UString &s = parts[i];

     #ifdef _WIN32

-    while (!s.IsEmpty() && s[s.Length() - 1] == '.')

-      s.Delete(s.Length() - 1);

+    while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' '))

+      s.DeleteBack();

     if (!IsSupportedName(s))

-      s = (UString)L"_" + s;

+      s.InsertAtFront(L'_');

     #endif

   }

   return MakePathNameFromParts(parts);

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
old mode 100755
new mode 100644
index 54bdc72..8d36312
--- a/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -3,11 +3,19 @@
 #ifndef __EXTRACTING_FILE_PATH_H

 #define __EXTRACTING_FILE_PATH_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

 

 UString MakePathNameFromParts(const UStringVector &parts);

-void MakeCorrectPath(UStringVector &pathParts);

+

+/* 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);

+

 UString GetCorrectFsPath(const UString &path);

 UString GetCorrectFullFsPath(const UString &path);

 

+void Correct_IfEmptyLastPart(UStringVector &parts);

+

 #endif

diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
new file mode 100644
index 0000000..4ecf6a3
--- /dev/null
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -0,0 +1,361 @@
+// HashCalc.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/Alloc.h"

+

+#include "../../../Common/StringToInt.h"

+

+#include "../../Common/FileStreams.h"

+#include "../../Common/StreamUtils.h"

+

+#include "EnumDirItems.h"

+#include "HashCalc.h"

+

+using namespace NWindows;

+

+class CHashMidBuf

+{

+  void *_data;

+public:

+  CHashMidBuf(): _data(0) {}

+  operator void *() { return _data; }

+  bool Alloc(size_t size)

+  {

+    if (_data != 0)

+      return false;

+    _data = ::MidAlloc(size);

+    return _data != 0;

+  }

+  ~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";

+

+HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)

+{

+  UStringVector names = hashMethods;

+  if (names.IsEmpty())

+    names.Add(k_DefaultHashMethod);

+

+  CRecordVector<CMethodId> ids;

+  CObjectVector<COneMethodInfo> methods;

+  

+  unsigned i;

+  for (i = 0; i < names.Size(); i++)

+  {

+    COneMethodInfo m;

+    RINOK(m.ParseMethodFromString(names[i]));

+

+    if (m.MethodName.IsEmpty())

+      m.MethodName = k_DefaultHashMethod;

+    

+    if (m.MethodName == L"*")

+    {

+      CRecordVector<CMethodId> tempMethods;

+      GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);

+      methods.Clear();

+      ids.Clear();

+      FOR_VECTOR (t, tempMethods)

+      {

+        int index = ids.AddToUniqueSorted(tempMethods[t]);

+        if (ids.Size() != methods.Size())

+          methods.Insert(index, m);

+      }

+      break;

+    }

+    else

+    {

+      // m.MethodName.RemoveChar(L'-');

+      CMethodId id;

+      if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))

+        return E_NOTIMPL;

+      int index = ids.AddToUniqueSorted(id);

+      if (ids.Size() != methods.Size())

+        methods.Insert(index, m);

+    }

+  }

+

+  for (i = 0; i < ids.Size(); i++)

+  {

+    CMyComPtr<IHasher> hasher;

+    UString name;

+    RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));

+    if (!hasher)

+      throw "Can't create hasher";

+    const COneMethodInfo &m = methods[i];

+    {

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

+      return E_NOTIMPL;

+    CHasherState &h = Hashers.AddNew();

+    h.Hasher = hasher;

+    h.Name = name;

+    h.DigestSize = digestSize;

+    for (int i = 0; i < k_HashCalc_NumGroups; i++)

+      memset(h.Digests[i], 0, digestSize);

+  }

+  return S_OK;

+}

+

+void CHashBundle::InitForNewFile()

+{

+  CurSize = 0;

+  FOR_VECTOR (i, Hashers)

+  {

+    CHasherState &h = Hashers[i];

+    h.Hasher->Init();

+    memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize);

+  }

+}

+

+void CHashBundle::Update(const void *data, UInt32 size)

+{

+  CurSize += size;

+  FOR_VECTOR (i, Hashers)

+    Hashers[i].Hasher->Update(data, size);

+}

+

+void CHashBundle::SetSize(UInt64 size)

+{

+  CurSize = size;

+}

+

+static void AddDigests(Byte *dest, const Byte *src, UInt32 size)

+{

+  unsigned next = 0;

+  for (UInt32 i = 0; i < size; i++)

+  {

+    next += (unsigned)dest[i] + (unsigned)src[i];

+    dest[i] = (Byte)next;

+    next >>= 8;

+  }

+}

+

+void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)

+{

+  if (isDir)

+    NumDirs++;

+  else if (isAltStream)

+  {

+    NumAltStreams++;

+    AltStreamsSize += CurSize;

+  }

+  else

+  {

+    NumFiles++;

+    FilesSize += CurSize;

+  }

+

+  Byte pre[16];

+  memset(pre, 0, sizeof(pre));

+  if (isDir)

+    pre[0] = 1;

+  

+  FOR_VECTOR (i, Hashers)

+  {

+    CHasherState &h = Hashers[i];

+    if (!isDir)

+    {

+      h.Hasher->Final(h.Digests[0]);

+      if (!isAltStream)

+        AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize);

+    }

+

+    h.Hasher->Init();

+    h.Hasher->Update(pre, sizeof(pre));

+    h.Hasher->Update(h.Digests[0], h.DigestSize);

+    

+    for (unsigned k = 0; k < path.Len(); k++)

+    {

+      wchar_t c = path[k];

+      Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };

+      h.Hasher->Update(temp, 2);

+    }

+  

+    Byte tempDigest[k_HashCalc_DigestSize_Max];

+    h.Hasher->Final(tempDigest);

+    if (!isAltStream)

+      AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize);

+    AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize);

+  }

+}

+

+

+HRESULT HashCalc(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const NWildcard::CCensor &censor,

+    const CHashOptions &options,

+    UString &errorInfo,

+    IHashCallbackUI *callback)

+{

+  CDirItems dirItems;

+

+  UInt64 numErrors = 0;

+  UInt64 totalBytes = 0;

+  if (options.StdInMode)

+  {

+    CDirItem di;

+    di.Size = (UInt64)(Int64)-1;

+    di.Attrib = 0;

+    di.MTime.dwLowDateTime = 0;

+    di.MTime.dwHighDateTime = 0;

+    di.CTime = di.ATime = di.MTime;

+    dirItems.Items.Add(di);

+  }

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

+    if (res != S_OK)

+    {

+      if (res != E_ABORT)

+        errorInfo = L"Scanning error";

+      return res;

+    }

+    RINOK(callback->FinishScanning());

+  }

+

+  unsigned i;

+  CHashBundle hb;

+  RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));

+  hb.Init();

+  hb.NumErrors = numErrors;

+  

+  if (options.StdInMode)

+  {

+    RINOK(callback->SetNumFiles(1));

+  }

+  else

+  {

+    RINOK(callback->SetTotal(totalBytes));

+  }

+

+  const UInt32 kBufSize = 1 << 15;

+  CHashMidBuf buf;

+  if (!buf.Alloc(kBufSize))

+    return E_OUTOFMEMORY;

+

+  UInt64 completeValue = 0;

+

+  RINOK(callback->BeforeFirstFile(hb));

+

+  for (i = 0; i < dirItems.Items.Size(); i++)

+  {

+    CMyComPtr<ISequentialInStream> inStream;

+    UString path;

+    bool isDir = false;

+    bool isAltStream = false;

+    if (options.StdInMode)

+    {

+      inStream = new CStdInFileStream;

+    }

+    else

+    {

+      CInFileStream *inStreamSpec = new CInFileStream;

+      inStream = inStreamSpec;

+      const CDirItem &dirItem = dirItems.Items[i];

+      isDir = dirItem.IsDir();

+      isAltStream = dirItem.IsAltStream;

+      path = dirItems.GetLogPath(i);

+      if (!isDir)

+      {

+        UString phyPath = dirItems.GetPhyPath(i);

+        if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite))

+        {

+          HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());

+          hb.NumErrors++;

+          if (res != S_FALSE)

+            return res;

+          continue;

+        }

+      }

+    }

+    RINOK(callback->GetStream(path, isDir));

+    UInt64 fileSize = 0;

+

+    hb.InitForNewFile();

+    if (!isDir)

+    {

+      for (UInt32 step = 0;; step++)

+      {

+        if ((step & 0xFF) == 0)

+          RINOK(callback->SetCompleted(&completeValue));

+        UInt32 size;

+        RINOK(inStream->Read(buf, kBufSize, &size));

+        if (size == 0)

+          break;

+        hb.Update(buf, size);

+        fileSize += size;

+        completeValue += size;

+      }

+    }

+    hb.Final(isDir, isAltStream, path);

+    RINOK(callback->SetOperationResult(fileSize, hb, !isDir));

+    RINOK(callback->SetCompleted(&completeValue));

+  }

+  return callback->AfterLastFile(hb);

+}

+

+

+static inline char GetHex(Byte value)

+{

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+void AddHashHexToString(char *dest, const Byte *data, UInt32 size)

+{

+  dest[size * 2] = 0;

+  if (!data)

+  {

+    for (UInt32 i = 0; i < size; i++)

+    {

+      dest[0] = ' ';

+      dest[1] = ' ';

+      dest += 2;

+    }

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

+    dest += step;

+  }

+}

diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
new file mode 100644
index 0000000..01ee2ce
--- /dev/null
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -0,0 +1,107 @@
+// HashCalc.h

+

+#ifndef __HASH_CALC_H

+#define __HASH_CALC_H

+

+#include "../../../Common/Wildcard.h"

+

+#include "../../Common/CreateCoder.h"

+#include "../../Common/MethodProps.h"

+

+#include "Property.h"

+

+const unsigned k_HashCalc_DigestSize_Max = 64;

+

+const unsigned k_HashCalc_NumGroups = 4;

+

+enum

+{

+  k_HashCalc_Index_Current,

+  k_HashCalc_Index_DataSum,

+  k_HashCalc_Index_NamesSum,

+  k_HashCalc_Index_StreamsSum

+};

+

+struct CHasherState

+{

+  CMyComPtr<IHasher> Hasher;

+  UString Name;

+  UInt32 DigestSize;

+  Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];

+};

+

+struct IHashCalc

+{

+  virtual void InitForNewFile() = 0;

+  virtual void Update(const void *data, UInt32 size) = 0;

+  virtual void SetSize(UInt64 size) = 0;

+  virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;

+};

+

+struct CHashBundle: public IHashCalc

+{

+  CObjectVector<CHasherState> Hashers;

+

+  UInt64 NumFiles;

+  UInt64 NumDirs;

+  UInt64 NumAltStreams;

+  UInt64 FilesSize;

+  UInt64 AltStreamsSize;

+  UInt64 NumErrors;

+

+  UInt64 CurSize;

+

+  HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);

+  

+  void Init()

+  {

+    NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;

+  }

+

+  void InitForNewFile();

+  void Update(const void *data, UInt32 size);

+  void SetSize(UInt64 size);

+  void Final(bool isDir, bool isAltStream, const UString &path);

+};

+

+#define INTERFACE_IHashCallbackUI(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 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 SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \

+  virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \

+

+struct IHashCallbackUI

+{

+  INTERFACE_IHashCallbackUI(=0)

+};

+

+struct CHashOptions

+{

+  UStringVector Methods;

+  bool OpenShareForWrite;

+  bool StdInMode;

+  bool AltStreamsMode;

+  NWildcard::ECensorPathMode PathMode;

+ 

+  CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {};

+};

+

+HRESULT HashCalc(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const NWildcard::CCensor &censor,

+    const CHashOptions &options,

+    UString &errorInfo,

+    IHashCallbackUI *callback);

+

+void AddHashHexToString(char *dest, const Byte *data, UInt32 size);

+

+#endif

diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
old mode 100755
new mode 100644
index 5aff92f..debfc08
--- a/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -1,9 +1,10 @@
 // IFileExtractCallback.h

 

-#ifndef __IFILEEXTRACTCALLBACK_H

-#define __IFILEEXTRACTCALLBACK_H

+#ifndef __I_FILE_EXTRACT_CALLBACK_H

+#define __I_FILE_EXTRACT_CALLBACK_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

+

 #include "../../IDecl.h"

 

 namespace NOverwriteAnswer

@@ -35,12 +36,37 @@
 {

   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

 };

 

+

+#define INTERFACE_IGetProp(x) \

+  STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \

+

+DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)

+{

+  INTERFACE_IGetProp(PURE)

+};

+

+#define INTERFACE_IFolderExtractToStreamCallback(x) \

+  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; \

+

+DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)

+{

+  INTERFACE_IFolderExtractToStreamCallback(PURE)

+};

+

+

 #endif

diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
old mode 100755
new mode 100644
index 67a0cc7..acbd7e8
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -2,18 +2,27 @@
 

 #include "StdAfx.h"

 

-#include "LoadCodecs.h"

+#include "../../../../C/7zVersion.h"

 

 #include "../../../Common/MyCom.h"

+#include "../../../Common/StringToInt.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/PropVariant.h"

+

+#include "LoadCodecs.h"

+

+using namespace NWindows;

+

 #ifdef NEW_FOLDER_INTERFACE

 #include "../../../Common/StringToInt.h"

 #endif

-#include "../../../Windows/PropVariant.h"

 

 #include "../../ICoder.h"

 #include "../../Common/RegisterArc.h"

 

 #ifdef EXTERNAL_CODECS

+

 #include "../../../Windows/FileFind.h"

 #include "../../../Windows/DLL.h"

 #ifdef NEW_FOLDER_INTERFACE

@@ -22,177 +31,73 @@
 #endif

 

 #ifdef _WIN32

-#include "Windows/Registry.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/Registry.h"

 #endif

 

-using namespace NWindows;

 using namespace NFile;

 

 #ifdef _WIN32

 extern HINSTANCE g_hInstance;

 #endif

 

-static CSysString GetLibraryFolderPrefix()

-{

-  #ifdef _WIN32

-  TCHAR fullPath[MAX_PATH + 1];

-  ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);

-  CSysString path = fullPath;

-  int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

-  return path.Left(pos + 1);

-  #else

-  return CSysString(); // FIX IT

-  #endif

-}

-

-#define kCodecsFolderName TEXT("Codecs")

-#define kFormatsFolderName TEXT("Formats")

-static const TCHAR *kMainDll = TEXT("7z.dll");

+#define kCodecsFolderName FTEXT("Codecs")

+#define kFormatsFolderName FTEXT("Formats")

+static CFSTR kMainDll = FTEXT("7z.dll");

 

 #ifdef _WIN32

+

 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");

-static LPCTSTR kProgramPathValue = TEXT("Path");

-static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)

+static LPCWSTR kProgramPathValue = L"Path";

+static LPCWSTR kProgramPath2Value = L"Path"

+  #ifdef _WIN64

+  L"64";

+  #else

+  L"32";

+  #endif

+

+static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)

 {

   NRegistry::CKey key;

-  if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)

-    if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)

+  if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)

+  {

+    UString pathU;

+    if (key.QueryValue(value, pathU) == ERROR_SUCCESS)

     {

+      path = us2fs(pathU);

       NName::NormalizeDirPathPrefix(path);

-      return true;

+      return NFind::DoesFileExist(path + kMainDll);

     }

+  }

   return false;

 }

 

-#endif

+#endif // _WIN32

 

-CSysString GetBaseFolderPrefixFromRegistry()

-{

-  CSysString moduleFolderPrefix = GetLibraryFolderPrefix();

-  #ifdef _WIN32

-  if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&

-      !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&

-      !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))

-  {

-    CSysString path;

-    if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))

-      return path;

-    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))

-      return path;

-  }

-  #endif

-  return moduleFolderPrefix;

-}

-

-typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);

-typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);

-typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);

-typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);

-typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);

-typedef UInt32 (WINAPI *SetLargePageModeFunc)();

+#endif // EXTERNAL_CODECS

 

 

-static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,

-    PROPID propId, CLSID &clsId, bool &isAssigned)

-{

-  NWindows::NCOM::CPropVariant prop;

-  isAssigned = false;

-  RINOK(getMethodProperty(index, propId, &prop));

-  if (prop.vt == VT_BSTR)

-  {

-    isAssigned = true;

-    clsId = *(const GUID *)prop.bstrVal;

-  }

-  else if (prop.vt != VT_EMPTY)

-    return E_FAIL;

-  return S_OK;

-}

-

-HRESULT CCodecs::LoadCodecs()

-{

-  CCodecLib &lib = Libs.Back();

-  lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty");

-  if (lib.GetMethodProperty == NULL)

-    return S_OK;

-

-  UInt32 numMethods = 1;

-  GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods");

-  if (getNumberOfMethodsFunc != NULL)

-  {

-    RINOK(getNumberOfMethodsFunc(&numMethods));

-  }

-

-  for(UInt32 i = 0; i < numMethods; i++)

-  {

-    CDllCodecInfo info;

-    info.LibIndex = Libs.Size() - 1;

-    info.CodecIndex = i;

-

-    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));

-    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));

-

-    Codecs.Add(info);

-  }

-  return S_OK;

-}

-

-static HRESULT ReadProp(

-    GetHandlerPropertyFunc getProp,

-    GetHandlerPropertyFunc2 getProp2,

-    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)

-{

-  if (getProp2)

-    return getProp2(index, propID, &prop);;

-  return getProp(propID, &prop);

-}

-

-static HRESULT ReadBoolProp(

-    GetHandlerPropertyFunc getProp,

-    GetHandlerPropertyFunc2 getProp2,

-    UInt32 index, PROPID propID, bool &res)

-{

-  NCOM::CPropVariant prop;

-  RINOK(ReadProp(getProp, getProp2, index, propID, prop));

-  if (prop.vt == VT_BOOL)

-    res = VARIANT_BOOLToBool(prop.boolVal);

-  else if (prop.vt != VT_EMPTY)

-    return E_FAIL;

-  return S_OK;

-}

-

-static HRESULT ReadStringProp(

-    GetHandlerPropertyFunc getProp,

-    GetHandlerPropertyFunc2 getProp2,

-    UInt32 index, PROPID propID, UString &res)

-{

-  NCOM::CPropVariant prop;

-  RINOK(ReadProp(getProp, getProp2, index, propID, prop));

-  if (prop.vt == VT_BSTR)

-    res = prop.bstrVal;

-  else if (prop.vt != VT_EMPTY)

-    return E_FAIL;

-  return S_OK;

-}

-

-#endif

-

-static const unsigned int kNumArcsMax = 48;

-static unsigned int g_NumArcs = 0;

+static const unsigned kNumArcsMax = 48;

+static unsigned g_NumArcs = 0;

 static const CArcInfo *g_Arcs[kNumArcsMax];

-void RegisterArc(const CArcInfo *arcInfo)

+

+void RegisterArc(const CArcInfo *arcInfo) throw()

 {

   if (g_NumArcs < kNumArcsMax)

-    g_Arcs[g_NumArcs++] = arcInfo;

+  {

+    g_Arcs[g_NumArcs] = arcInfo;

+    g_NumArcs++;

+  }

 }

 

 static void SplitString(const UString &srcString, UStringVector &destStrings)

 {

   destStrings.Clear();

   UString s;

-  int len = srcString.Length();

+  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' ')

@@ -210,14 +115,20 @@
     destStrings.Add(s);

 }

 

-void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)

+int CArcInfoEx::FindExtension(const UString &ext) const

+{

+  FOR_VECTOR (i, Exts)

+    if (ext.IsEqualToNoCase(Exts[i].Ext))

+      return i;

+  return -1;

+}

+

+void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)

 {

   UStringVector exts, addExts;

-  if (ext != 0)

-    SplitString(ext, exts);

-  if (addExt != 0)

-    SplitString(addExt, addExts);

-  for (int i = 0; i < exts.Size(); i++)

+  SplitString(ext, exts);

+  SplitString(addExt, addExts);

+  FOR_VECTOR (i, exts)

   {

     CArcExtInfo extInfo;

     extInfo.Ext = exts[i];

@@ -231,61 +142,275 @@
   }

 }

 

+#ifndef _SFX

+

+static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)

+{

+  signatures.Clear();

+  while (size > 0)

+  {

+    unsigned len = *data++;

+    size--;

+    if (len > size)

+      return false;

+    signatures.AddNew().CopyFrom(data, len);

+    data += len;

+    size -= len;

+  }

+  return true;

+}

+

+#endif // _SFX

+

 #ifdef EXTERNAL_CODECS

 

+static FString GetBaseFolderPrefixFromRegistry()

+{

+  FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();

+  #ifdef _WIN32

+  if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&

+      !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&

+      !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))

+  {

+    FString path;

+    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPath2Value, path)) return path;

+    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;

+    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPathValue,  path)) return path;

+    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue,  path)) return path;

+  }

+  #endif

+  return moduleFolderPrefix;

+}

+

+static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,

+    PROPID propId, CLSID &clsId, bool &isAssigned)

+{

+  NCOM::CPropVariant prop;

+  isAssigned = false;

+  RINOK(getMethodProperty(index, propId, &prop));

+  if (prop.vt == VT_BSTR)

+  {

+    if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))

+      return E_FAIL;

+    isAssigned = true;

+    clsId = *(const GUID *)prop.bstrVal;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+HRESULT CCodecs::LoadCodecs()

+{

+  CCodecLib &lib = Libs.Back();

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

+    {

+      RINOK(getNumberOfMethodsFunc(&numMethods));

+    }

+    for (UInt32 i = 0; i < numMethods; i++)

+    {

+      CDllCodecInfo info;

+      info.LibIndex = Libs.Size() - 1;

+      info.CodecIndex = i;

+      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));

+      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));

+      Codecs.Add(info);

+    }

+  }

+

+  Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");

+  if (getHashers)

+  {

+    RINOK(getHashers(&lib.Hashers));

+    if (lib.Hashers)

+    {

+      UInt32 numMethods = lib.Hashers->GetNumHashers();

+      for (UInt32 i = 0; i < numMethods; i++)

+      {

+        CDllHasherInfo info;

+        info.LibIndex = Libs.Size() - 1;

+        info.HasherIndex = i;

+        Hashers.Add(info);

+      }

+    }

+  }

+  return S_OK;

+}

+

+static HRESULT GetProp(

+    Func_GetHandlerProperty getProp,

+    Func_GetHandlerProperty2 getProp2,

+    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)

+{

+  if (getProp2)

+    return getProp2(index, propID, &prop);;

+  return getProp(propID, &prop);

+}

+

+static HRESULT GetProp_Bool(

+    Func_GetHandlerProperty getProp,

+    Func_GetHandlerProperty2 getProp2,

+    UInt32 index, PROPID propID, bool &res)

+{

+  res = false;

+  NCOM::CPropVariant prop;

+  RINOK(GetProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_BOOL)

+    res = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT GetProp_UInt32(

+    Func_GetHandlerProperty getProp,

+    Func_GetHandlerProperty2 getProp2,

+    UInt32 index, PROPID propID, UInt32 &res, bool &defined)

+{

+  res = 0;

+  defined = false;

+  NCOM::CPropVariant prop;

+  RINOK(GetProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_UI4)

+  {

+    res = prop.ulVal;

+    defined = true;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT GetProp_String(

+    Func_GetHandlerProperty getProp,

+    Func_GetHandlerProperty2 getProp2,

+    UInt32 index, PROPID propID, UString &res)

+{

+  res.Empty();

+  NCOM::CPropVariant prop;

+  RINOK(GetProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_BSTR)

+    res = prop.bstrVal;

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT GetProp_RawData(

+    Func_GetHandlerProperty getProp,

+    Func_GetHandlerProperty2 getProp2,

+    UInt32 index, PROPID propID, CByteBuffer &bb)

+{

+  bb.Free();

+  NCOM::CPropVariant prop;

+  RINOK(GetProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_BSTR)

+  {

+    UINT len = ::SysStringByteLen(prop.bstrVal);

+    bb.CopyFrom((const Byte *)prop.bstrVal, len);

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static const UInt32 kArcFlagsPars[] =

+{

+  NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,

+  NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,

+  NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure

+};

+

 HRESULT CCodecs::LoadFormats()

 {

   const NDLL::CLibrary &lib = Libs.Back().Lib;

-  GetHandlerPropertyFunc getProp = 0;

-  GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");

-  if (getProp2 == NULL)

+  

+  Func_GetHandlerProperty getProp = NULL;

+  Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2");

+  Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc");

+  

+  UInt32 numFormats = 1;

+

+  if (getProp2)

   {

-    getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");

-    if (getProp == NULL)

+    Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats");

+    if (getNumberOfFormats)

+    {

+      RINOK(getNumberOfFormats(&numFormats));

+    }

+  }

+  else

+  {

+    getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty");

+    if (!getProp)

       return S_OK;

   }

-

-  UInt32 numFormats = 1;

-  GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");

-  if (getNumberOfFormats != NULL)

-  {

-    RINOK(getNumberOfFormats(&numFormats));

-  }

-  if (getProp2 == NULL)

-    numFormats = 1;

-

-  for(UInt32 i = 0; i < numFormats; i++)

+  

+  for (UInt32 i = 0; i < numFormats; i++)

   {

     CArcInfoEx item;

     item.LibIndex = Libs.Size() - 1;

     item.FormatIndex = i;

 

-    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));

+    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name));

 

-    NCOM::CPropVariant prop;

-    if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)

-      continue;

-    if (prop.vt != VT_BSTR)

-      continue;

-    item.ClassID = *(const GUID *)prop.bstrVal;

-    prop.Clear();

+    {

+      NCOM::CPropVariant prop;

+      if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)

+        continue;

+      if (prop.vt != VT_BSTR)

+        continue;

+      if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))

+        return E_FAIL;

+      item.ClassID = *(const GUID *)prop.bstrVal;

+      prop.Clear();

+    }

 

     UString ext, addExt;

-    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));

-    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));

+    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext));

+    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt));

     item.AddExts(ext, addExt);

 

-    ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);

-    if (item.UpdateEnabled)

-      ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);

-    

-    if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)

-      if (prop.vt == VT_BSTR)

+    GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);

+    bool flags_Defined = false;

+    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined));

+    item.NewInterface = flags_Defined;

+    if (!flags_Defined) // && item.UpdateEnabled

+    {

+      // support for DLL version before 9.31:

+      for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2)

       {

-        UINT len = ::SysStringByteLen(prop.bstrVal);

-        item.StartSignature.SetCapacity(len);

-        memmove(item.StartSignature, prop.bstrVal, len);

+        bool val = false;

+        GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);

+        if (val)

+          item.Flags |= kArcFlagsPars[j + 1];

       }

+    }

+    

+    CByteBuffer sig;

+    RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));

+    if (sig.Size() != 0)

+      item.Signatures.Add(sig);

+    else

+    {

+      RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig));

+      ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);

+    }

+

+    bool signatureOffset_Defined;

+    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined));

+    

+    // bool version_Defined;

+    // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));

+

+    if (getIsArc)

+      getIsArc(i, &item.IsArcFunc);

+

     Formats.Add(item);

   }

   return S_OK;

@@ -294,25 +419,26 @@
 #ifdef NEW_FOLDER_INTERFACE

 void CCodecIcons::LoadIcons(HMODULE m)

 {

-  UString iconTypes = MyLoadStringW(m, kIconTypesResId);

+  UString iconTypes;

+  MyLoadString(m, kIconTypesResId, iconTypes);

   UStringVector pairs;

   SplitString(iconTypes, pairs);

-  for (int i = 0; i < pairs.Size(); i++)

+  FOR_VECTOR (i, pairs)

   {

     const UString &s = pairs[i];

     int pos = s.Find(L':');

     CIconPair iconPair;

     iconPair.IconIndex = -1;

     if (pos < 0)

-      pos = s.Length();

+      pos = s.Len();

     else

     {

-      UString num = s.Mid(pos + 1);

+      UString num = s.Ptr(pos + 1);

       if (!num.IsEmpty())

       {

         const wchar_t *end;

-        iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);

-        if (*end != L'\0')

+        iconPair.IconIndex = ConvertStringToUInt32(num, &end);

+        if (*end != 0)

           continue;

       }

     }

@@ -324,10 +450,10 @@
 bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const

 {

   iconIndex = -1;

-  for (int i = 0; i < IconPairs.Size(); i++)

+  FOR_VECTOR (i, IconPairs)

   {

     const CIconPair &pair = IconPairs[i];

-    if (ext.CompareNoCase(pair.Ext) == 0)

+    if (ext.IsEqualToNoCase(pair.Ext))

     {

       iconIndex = pair.IconIndex;

       return true;

@@ -335,7 +461,8 @@
   }

   return false;

 }

-#endif

+

+#endif // EXTERNAL_CODECS

 

 #ifdef _7ZIP_LARGE_PAGES

 extern "C"

@@ -344,7 +471,7 @@
 }

 #endif

 

-HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)

+HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)

 {

   if (needCheckDll)

   {

@@ -354,9 +481,7 @@
   }

   Libs.Add(CCodecLib());

   CCodecLib &lib = Libs.Back();

-  #ifdef NEW_FOLDER_INTERFACE

   lib.Path = dllPath;

-  #endif

   bool used = false;

   HRESULT res = S_OK;

   if (lib.Lib.Load(dllPath))

@@ -368,23 +493,31 @@
     #ifdef _7ZIP_LARGE_PAGES

     if (g_LargePageSize != 0)

     {

-      SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");

-      if (setLargePageMode != 0)

+      Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode");

+      if (setLargePageMode)

         setLargePageMode();

     }

     #endif

 

-    lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");

-    if (lib.CreateObject != 0)

+    if (CaseSensitiveChange)

     {

-      int startSize = Codecs.Size();

+      Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive");

+      if (setCaseSensitive)

+        setCaseSensitive(CaseSensitive ? 1 : 0);

+    }

+

+    lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject");

+    if (lib.CreateObject)

+    {

+      unsigned startSize = Codecs.Size() + Hashers.Size();

       res = LoadCodecs();

-      used = (Codecs.Size() != startSize);

+      used = (startSize != Codecs.Size() + Hashers.Size());

       if (res == S_OK)

       {

         startSize = Formats.Size();

         res = LoadFormats();

-        used = used || (Formats.Size() != startSize);

+        if (startSize != Formats.Size())

+          used = true;

       }

     }

   }

@@ -393,9 +526,9 @@
   return res;

 }

 

-HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)

+HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)

 {

-  NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));

+  NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK);

   NFile::NFind::CFileInfo fi;

   while (enumerator.Next(fi))

   {

@@ -408,46 +541,63 @@
 

 #endif

 

-#ifndef _SFX

-static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)

-{

-  bb.SetCapacity(size);

-  memmove((Byte *)bb, data, size);

-}

-#endif

-

 HRESULT CCodecs::Load()

 {

   #ifdef NEW_FOLDER_INTERFACE

-  InternalIcons.LoadIcons(g_hInstance);

+    InternalIcons.LoadIcons(g_hInstance);

   #endif

 

   Formats.Clear();

+  

   #ifdef EXTERNAL_CODECS

-  Codecs.Clear();

+    Codecs.Clear();

+    Hashers.Clear();

   #endif

+  

   for (UInt32 i = 0; i < g_NumArcs; i++)

   {

     const CArcInfo &arc = *g_Arcs[i];

     CArcInfoEx item;

-    item.Name = arc.Name;

+    

+    item.Name.SetFromAscii(arc.Name);

     item.CreateInArchive = arc.CreateInArchive;

-    item.CreateOutArchive = arc.CreateOutArchive;

-    item.AddExts(arc.Ext, arc.AddExt);

-    item.UpdateEnabled = (arc.CreateOutArchive != 0);

-    item.KeepName = arc.KeepName;

+    item.IsArcFunc = arc.IsArc;

+    item.Flags = arc.Flags;

+  

+    {

+      UString e, ae;

+      if (arc.Ext)

+        e.SetFromAscii(arc.Ext);

+      if (arc.AddExt)

+        ae.SetFromAscii(arc.AddExt);

+      item.AddExts(e, ae);

+    }

 

     #ifndef _SFX

-    SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);

+

+    item.CreateOutArchive = arc.CreateOutArchive;

+    item.UpdateEnabled = (arc.CreateOutArchive != NULL);

+    item.SignatureOffset = arc.SignatureOffset;

+    // item.Version = MY_VER_MIX;

+    item.NewInterface = true;

+    

+    if (arc.IsMultiSignature())

+      ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);

+    else

+      item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);

+    

     #endif

+

     Formats.Add(item);

   }

+  

   #ifdef EXTERNAL_CODECS

-  const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();

-  RINOK(LoadDll(baseFolder + kMainDll, false));

-  RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));

-  RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));

+    const FString baseFolder = GetBaseFolderPrefixFromRegistry();

+    RINOK(LoadDll(baseFolder + kMainDll, false));

+    RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));

+    RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));

   #endif

+  

   return S_OK;

 }

 

@@ -455,17 +605,22 @@
 

 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const

 {

-  int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);

-  int slashPos2 = arcPath.ReverseFind(L'.');

+  int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);

   int dotPos = arcPath.ReverseFind(L'.');

-  if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)

+  if (dotPos < 0 || dotPos < slashPos)

     return -1;

-  UString ext = arcPath.Mid(dotPos + 1);

-  for (int i = 0; i < Formats.Size(); i++)

+  const UString ext = arcPath.Ptr(dotPos + 1);

+  if (ext.IsEmpty())

+    return -1;

+  if (ext.IsEqualToNoCase(L"exe"))

+    return -1;

+  FOR_VECTOR (i, Formats)

   {

     const CArcInfoEx &arc = Formats[i];

+    /*

     if (!arc.UpdateEnabled)

       continue;

+    */

     if (arc.FindExtension(ext) >= 0)

       return i;

   }

@@ -476,7 +631,7 @@
 {

   if (ext.IsEmpty())

     return -1;

-  for (int i = 0; i < Formats.Size(); i++)

+  FOR_VECTOR (i, Formats)

     if (Formats[i].FindExtension(ext) >= 0)

       return i;

   return -1;

@@ -484,8 +639,8 @@
 

 int CCodecs::FindFormatForArchiveType(const UString &arcType) const

 {

-  for (int i = 0; i < Formats.Size(); i++)

-    if (Formats[i].Name.CompareNoCase(arcType) == 0)

+  FOR_VECTOR (i, Formats)

+    if (Formats[i].Name.IsEqualToNoCase(arcType))

       return i;

   return -1;

 }

@@ -493,12 +648,14 @@
 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const

 {

   formatIndices.Clear();

-  for (int pos = 0; pos < arcType.Length();)

+  for (unsigned pos = 0; pos < arcType.Len();)

   {

     int pos2 = arcType.Find('.', pos);

     if (pos2 < 0)

-      pos2 = arcType.Length();

+      pos2 = arcType.Len();

     const UString name = arcType.Mid(pos, pos2 - pos);

+    if (name.IsEmpty())

+      return false;

     int index = FindFormatForArchiveType(name);

     if (index < 0 && name != L"*")

     {

@@ -511,24 +668,39 @@
   return true;

 }

 

-#endif

+#endif // _SFX

+

 

 #ifdef EXTERNAL_CODECS

 

+// #define EXPORT_CODECS

+

 #ifdef EXPORT_CODECS

-extern unsigned int g_NumCodecs;

+

+extern unsigned g_NumCodecs;

 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);

 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);

-// STDAPI GetNumberOfMethods(UInt32 *numCodecs);

-#endif

+#define NUM_EXPORT_CODECS g_NumCodecs

+

+extern unsigned g_NumHashers;

+STDAPI CreateHasher(UInt32 index, IHasher **hasher);

+STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);

+#define NUM_EXPORT_HASHERS g_NumHashers

+

+#else // EXPORT_CODECS

+

+#define NUM_EXPORT_CODECS 0

+#define NUM_EXPORT_HASHERS 0

+

+#endif // EXPORT_CODECS

 

 STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)

 {

-  *numMethods =

-      #ifdef EXPORT_CODECS

-      g_NumCodecs +

-      #endif

-      Codecs.Size();

+  *numMethods = NUM_EXPORT_CODECS

+    #ifdef EXTERNAL_CODECS

+    + Codecs.Size()

+    #endif

+    ;

   return S_OK;

 }

 

@@ -539,27 +711,23 @@
     return GetMethodProperty(index, propID, value);

   #endif

 

-  const CDllCodecInfo &ci = Codecs[index

-      #ifdef EXPORT_CODECS

-      - g_NumCodecs

-      #endif

-      ];

+  #ifdef EXTERNAL_CODECS

+  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

 

-  if (propID == NMethodPropID::kDecoderIsAssigned)

+  if (propID == NMethodPropID::kDecoderIsAssigned ||

+      propID == NMethodPropID::kEncoderIsAssigned)

   {

-    NWindows::NCOM::CPropVariant propVariant;

-    propVariant = ci.DecoderIsAssigned;

-    propVariant.Detach(value);

-    return S_OK;

-  }

-  if (propID == NMethodPropID::kEncoderIsAssigned)

-  {

-    NWindows::NCOM::CPropVariant propVariant;

-    propVariant = ci.EncoderIsAssigned;

-    propVariant.Detach(value);

+    NCOM::CPropVariant prop;

+    prop = (propID == NMethodPropID::kDecoderIsAssigned) ?

+        ci.DecoderIsAssigned :

+        ci.EncoderIsAssigned;

+    prop.Detach(value);

     return S_OK;

   }

   return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);

+  #else

+  return E_FAIL;

+  #endif

 }

 

 STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)

@@ -568,14 +736,14 @@
   if (index < g_NumCodecs)

     return CreateCoder2(false, index, iid, coder);

   #endif

-  const CDllCodecInfo &ci = Codecs[index

-      #ifdef EXPORT_CODECS

-      - g_NumCodecs

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

   return S_OK;

+  #else

+  return E_FAIL;

+  #endif

 }

 

 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)

@@ -584,35 +752,53 @@
   if (index < g_NumCodecs)

     return CreateCoder2(true, index, iid, coder);

   #endif

-  const CDllCodecInfo &ci = Codecs[index

-      #ifdef EXPORT_CODECS

-      - g_NumCodecs

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

   return S_OK;

+  #else

+  return E_FAIL;

+  #endif

 }

 

-HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const

+

+STDMETHODIMP_(UInt32) CCodecs::GetNumHashers()

 {

-  for (int i = 0; i < Codecs.Size(); i++)

-  {

-    const CDllCodecInfo &codec = Codecs[i];

-    if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)

-      continue;

-    const CCodecLib &lib = Libs[codec.LibIndex];

-    UString res;

-    NWindows::NCOM::CPropVariant prop;

-    RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));

-    if (prop.vt == VT_BSTR)

-      res = prop.bstrVal;

-    else if (prop.vt != VT_EMPTY)

-      continue;

-    if (name.CompareNoCase(res) == 0)

-      return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);

-  }

-  return CLASS_E_CLASSNOTAVAILABLE;

+  return NUM_EXPORT_HASHERS

+    #ifdef EXTERNAL_CODECS

+    + Hashers.Size()

+    #endif

+    ;

+}

+

+STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumHashers)

+    return ::GetHasherProp(index, propID, value);

+  #endif

+

+  #ifdef EXTERNAL_CODECS

+  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

+  return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value);

+  #else

+  return E_FAIL;

+  #endif

+}

+

+STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumHashers)

+    return CreateHasher(index, hasher);

+  #endif

+  #ifdef EXTERNAL_CODECS

+  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

+  return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher);

+  #else

+  return E_FAIL;

+  #endif

 }

 

 int CCodecs::GetCodecLibIndex(UInt32 index)

@@ -622,11 +808,21 @@
     return -1;

   #endif

   #ifdef EXTERNAL_CODECS

-  const CDllCodecInfo &ci = Codecs[index

-      #ifdef EXPORT_CODECS

-      - g_NumCodecs

-      #endif

-      ];

+  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

+  return ci.LibIndex;

+  #else

+  return -1;

+  #endif

+}

+

+int CCodecs::GetHasherLibIndex(UInt32 index)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumHashers)

+    return -1;

+  #endif

+  #ifdef EXTERNAL_CODECS

+  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];

   return ci.LibIndex;

   #else

   return -1;

@@ -638,7 +834,7 @@
   #ifdef EXPORT_CODECS

   if (index < g_NumCodecs)

   {

-    NWindows::NCOM::CPropVariant prop;

+    NCOM::CPropVariant prop;

     if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)

       if (prop.vt != VT_EMPTY)

         return true;

@@ -646,11 +842,7 @@
   }

   #endif

   #ifdef EXTERNAL_CODECS

-  const CDllCodecInfo &ci = Codecs[index

-      #ifdef EXPORT_CODECS

-      - g_NumCodecs

-      #endif

-      ];

+  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];

   return ci.EncoderIsAssigned;

   #else

   return false;

@@ -659,8 +851,7 @@
 

 HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)

 {

-  UString s;

-  NWindows::NCOM::CPropVariant prop;

+  NCOM::CPropVariant prop;

   RINOK(GetProperty(index, NMethodPropID::kID, &prop));

   if (prop.vt != VT_UI8)

     return E_INVALIDARG;

@@ -671,11 +862,39 @@
 UString CCodecs::GetCodecName(UInt32 index)

 {

   UString s;

-  NWindows::NCOM::CPropVariant prop;

+  NCOM::CPropVariant prop;

   if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)

     if (prop.vt == VT_BSTR)

       s = prop.bstrVal;

   return s;

 }

 

-#endif

+UInt64 CCodecs::GetHasherId(UInt32 index)

+{

+  NCOM::CPropVariant prop;

+  RINOK(GetHasherProp(index, NMethodPropID::kID, &prop));

+  if (prop.vt != VT_UI8)

+    return 0;

+  return prop.uhVal.QuadPart;

+}

+

+UString CCodecs::GetHasherName(UInt32 index)

+{

+  UString s;

+  NCOM::CPropVariant prop;

+  if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)

+    if (prop.vt == VT_BSTR)

+      s = prop.bstrVal;

+  return s;

+}

+

+UInt32 CCodecs::GetHasherDigestSize(UInt32 index)

+{

+  NCOM::CPropVariant prop;

+  RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop));

+  if (prop.vt != VT_UI4)

+    return 0;

+  return prop.ulVal;

+}

+

+#endif // EXTERNAL_CODECS

diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
old mode 100755
new mode 100644
index 5630b59..eebb177
--- a/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -1,12 +1,13 @@
 // LoadCodecs.h

 

-#ifndef __LOADCODECS_H

-#define __LOADCODECS_H

+#ifndef __LOAD_CODECS_H

+#define __LOAD_CODECS_H

 

-#include "../../../Common/Types.h"

+#include "../../../Common/MyBuffer.h"

 #include "../../../Common/MyCom.h"

 #include "../../../Common/MyString.h"

-#include "../../../Common/Buffer.h"

+#include "../../../Common/ComTry.h"

+

 #include "../../ICoder.h"

 

 #ifdef EXTERNAL_CODECS

@@ -23,15 +24,19 @@
   UInt32 CodecIndex;

 };

 

-#include "../../Archive/IArchive.h"

+struct CDllHasherInfo

+{

+  int LibIndex;

+  UInt32 HasherIndex;

+};

 

-typedef IInArchive * (*CreateInArchiveP)();

-typedef IOutArchive * (*CreateOutArchiveP)();

+#include "../../Archive/IArchive.h"

 

 struct CArcExtInfo

 {

   UString Ext;

   UString AddExt;

+  

   CArcExtInfo() {}

   CArcExtInfo(const UString &ext): Ext(ext) {}

   CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}

@@ -40,37 +45,55 @@
 

 struct CArcInfoEx

 {

-  #ifdef EXTERNAL_CODECS

-  int LibIndex;

-  UInt32 FormatIndex;

-  CLSID ClassID;

-  #endif

-  bool UpdateEnabled;

-  CreateInArchiveP CreateInArchive;

-  CreateOutArchiveP CreateOutArchive;

+  UInt32 Flags;

+  

+  Func_CreateInArchive CreateInArchive;

+  Func_IsArc IsArcFunc;

+

   UString Name;

   CObjectVector<CArcExtInfo> Exts;

+  

   #ifndef _SFX

-  CByteBuffer StartSignature;

-  // CByteBuffer FinishSignature;

-  #ifdef NEW_FOLDER_INTERFACE

-  UStringVector AssociateExts;

+    Func_CreateOutArchive CreateOutArchive;

+    bool UpdateEnabled;

+    bool NewInterface;

+    // UInt32 Version;

+    UInt32 SignatureOffset;

+    CObjectVector<CByteBuffer> Signatures;

+    #ifdef NEW_FOLDER_INTERFACE

+      UStringVector AssociateExts;

+    #endif

   #endif

+  

+  #ifdef EXTERNAL_CODECS

+    int LibIndex;

+    UInt32 FormatIndex;

+    CLSID ClassID;

   #endif

-  bool KeepName;

+

+  bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }

+  bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }

+

+  bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }

+  bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }

+  bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }

+  bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }

+

+  bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }

+  bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }

+  bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }

+  bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }

+  bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }

+  

   UString GetMainExt() const

   {

     if (Exts.IsEmpty())

       return UString();

     return Exts[0].Ext;

   }

-  int FindExtension(const UString &ext) const

-  {

-    for (int i = 0; i < Exts.Size(); i++)

-      if (ext.CompareNoCase(Exts[i].Ext) == 0)

-        return i;

-    return -1;

-  }

+  int FindExtension(const UString &ext) const;

+  

+  /*

   UString GetAllExtensions() const

   {

     UString s;

@@ -82,25 +105,31 @@
     }

     return s;

   }

+  */

 

-  void AddExts(const wchar_t* ext, const wchar_t* addExt);

+  void AddExts(const UString &ext, const UString &addExt);

+

+  bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }

+  // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }

 

   CArcInfoEx():

-    #ifdef EXTERNAL_CODECS

-    LibIndex(-1),

-    #endif

-    UpdateEnabled(false),

-    CreateInArchive(0), CreateOutArchive(0),

-    KeepName(false)

-    #ifndef _SFX

-    #endif

+      Flags(0),

+      CreateInArchive(NULL),

+      IsArcFunc(NULL)

+      #ifndef _SFX

+      , CreateOutArchive(NULL)

+      , UpdateEnabled(false)

+      , NewInterface(false)

+      // , Version(0)

+      , SignatureOffset(0)

+      #endif

+      #ifdef EXTERNAL_CODECS

+      , LibIndex(-1)

+      #endif

   {}

 };

 

 #ifdef EXTERNAL_CODECS

-typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);

-typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);

-

 

 #ifdef NEW_FOLDER_INTERFACE

 struct CCodecIcons

@@ -117,24 +146,28 @@
 #endif

 

 struct CCodecLib

-#ifdef NEW_FOLDER_INTERFACE

-: public CCodecIcons

-#endif

+  #ifdef NEW_FOLDER_INTERFACE

+    : public CCodecIcons

+  #endif

 {

   NWindows::NDLL::CLibrary Lib;

-  GetMethodPropertyFunc GetMethodProperty;

-  CreateObjectFunc CreateObject;

+  FString Path;

+  Func_GetMethodProperty GetMethodProperty;

+  Func_CreateObject CreateObject;

+  CMyComPtr<IHashers> Hashers;

+  

   #ifdef NEW_FOLDER_INTERFACE

-  CSysString Path;

   void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }

   #endif

-  CCodecLib(): GetMethodProperty(0) {}

+  

+  CCodecLib(): GetMethodProperty(NULL) {}

 };

 #endif

 

 class CCodecs:

   #ifdef EXTERNAL_CODECS

   public ICompressCodecsInfo,

+  public IHashers,

   #else

   public IUnknown,

   #endif

@@ -143,7 +176,8 @@
 public:

   #ifdef EXTERNAL_CODECS

   CObjectVector<CCodecLib> Libs;

-  CObjectVector<CDllCodecInfo> Codecs;

+  CRecordVector<CDllCodecInfo> Codecs;

+  CRecordVector<CDllHasherInfo> Hashers;

 

   #ifdef NEW_FOLDER_INTERFACE

   CCodecIcons InternalIcons;

@@ -151,8 +185,8 @@
 

   HRESULT LoadCodecs();

   HRESULT LoadFormats();

-  HRESULT LoadDll(const CSysString &path, bool needCheckDll);

-  HRESULT LoadDllsFromFolder(const CSysString &folderPrefix);

+  HRESULT LoadDll(const FString &path, bool needCheckDll);

+  HRESULT LoadDllsFromFolder(const FString &folderPrefix);

 

   HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const

   {

@@ -162,6 +196,16 @@
 

 public:

   CObjectVector<CArcInfoEx> Formats;

+  bool CaseSensitiveChange;

+  bool CaseSensitive;

+

+  CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {}

+ 

+  const wchar_t *GetFormatNamePtr(int formatIndex)

+  {

+    return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;

+  }

+

   HRESULT Load();

   

   #ifndef _SFX

@@ -171,65 +215,89 @@
   bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;

   #endif

 

-  MY_UNKNOWN_IMP

-

   #ifdef EXTERNAL_CODECS

+

+  MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)

+    

   STDMETHOD(GetNumberOfMethods)(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);

-  #endif

+

+  STDMETHOD_(UInt32, GetNumHashers)();

+  STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);

+

+  #else

+

+  MY_UNKNOWN_IMP

+

+  #endif // EXTERNAL_CODECS

+

+  #ifdef EXTERNAL_CODECS

 

   int GetCodecLibIndex(UInt32 index);

   bool GetCodecEncoderIsAssigned(UInt32 index);

   HRESULT GetCodecId(UInt32 index, UInt64 &id);

   UString GetCodecName(UInt32 index);

 

-  HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const

+  int GetHasherLibIndex(UInt32 index);

+  UInt64 GetHasherId(UInt32 index);

+  UString GetHasherName(UInt32 index);

+  UInt32 GetHasherDigestSize(UInt32 index);

+

+  #endif

+

+  HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const

   {

     const CArcInfoEx &ai = Formats[formatIndex];

     #ifdef EXTERNAL_CODECS

     if (ai.LibIndex < 0)

     #endif

     {

+      COM_TRY_BEGIN

       archive = ai.CreateInArchive();

       return S_OK;

+      COM_TRY_END

     }

     #ifdef EXTERNAL_CODECS

     return CreateArchiveHandler(ai, (void **)&archive, false);

     #endif

   }

-  HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const

+  

+  #ifndef _SFX

+

+  HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const

   {

     const CArcInfoEx &ai = Formats[formatIndex];

     #ifdef EXTERNAL_CODECS

     if (ai.LibIndex < 0)

     #endif

     {

+      COM_TRY_BEGIN

       archive = ai.CreateOutArchive();

       return S_OK;

+      COM_TRY_END

     }

     #ifdef EXTERNAL_CODECS

     return CreateArchiveHandler(ai, (void **)&archive, true);

     #endif

   }

+  

   int FindOutFormatFromName(const UString &name) const

   {

-    for (int i = 0; i < Formats.Size(); i++)

+    FOR_VECTOR (i, Formats)

     {

       const CArcInfoEx &arc = Formats[i];

       if (!arc.UpdateEnabled)

         continue;

-      if (arc.Name.CompareNoCase(name) == 0)

+      if (arc.Name.IsEqualToNoCase(name))

         return i;

     }

     return -1;

   }

 

-  #ifdef EXTERNAL_CODECS

-  HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const;

-  #endif

-

+  #endif // _SFX

 };

 

 #endif

diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
old mode 100755
new mode 100644
index c489e0a..4632be8
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -2,27 +2,455 @@
 

 #include "StdAfx.h"

 

-#include "Common/Wildcard.h"

+// #define SHOW_DEBUG_INFO

 

-#include "Windows/FileDir.h"

-#include "Windows/PropVariant.h"

+#ifdef SHOW_DEBUG_INFO

+#include <stdio.h>

+#endif

+

+#include "../../../../C/CpuArch.h"

+

+#include "../../../Common/ComTry.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/StringToInt.h"

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileDir.h"

 

 #include "../../Common/FileStreams.h"

+#include "../../Common/LimitedStreams.h"

+#include "../../Common/ProgressUtils.h"

 #include "../../Common/StreamUtils.h"

 

+#include "../../Compress/CopyCoder.h"

+

 #include "DefaultName.h"

 #include "OpenArchive.h"

 

+#ifndef _SFX

+#include "SetProperties.h"

+#endif

+

+#ifdef SHOW_DEBUG_INFO

+#define PRF(x) x

+#else

+#define PRF(x)

+#endif

+

+// increase it, if you need to support larger SFX stubs

+static const UInt64 kMaxCheckStartPosition = 1 << 22;

+

+/*

+Open:

+  - formatIndex >= 0 (exact Format)

+       1) Open with main type. Archive handler is allowed to use archive start finder.

+          Warning, if there is tail.

+  

+  - formatIndex = -1 (Parser:0) (default)

+    - same as #1 but doesn't return Parser

+

+  - formatIndex = -2 (#1)

+    - file has supported extension (like a.7z)

+      Open with that main type (only starting from start of file).

+        - open OK:

+            - if there is no tail - return OK

+            - if there is tail:

+              - archive is not "Self Exe" - return OK with Warning, that there is tail

+              - archive is "Self Exe"

+                ignore "Self Exe" stub, and tries to open tail

+                  - tail can be open as archive - shows that archive and stub size property.

+                  - tail can't be open as archive - shows Parser ???

+        - open FAIL:

+           Try to open with all other types from offset 0 only.

+           If some open type is OK and physical archive size is uequal or larger

+           than file size, then return that archive with warning that can not be open as [extension type].

+           If extension was EXE, it will try to open as unknown_extension case

+    - file has unknown extension (like a.hhh)

+       It tries to open via parser code.

+         - if there is full archive or tail archive and unknown block or "Self Exe"

+           at front, it shows tail archive and stub size property.

+         - in another cases, if there is some archive inside file, it returns parser/

+         - in another cases, it retuens S_FALSE

+

+       

+  - formatIndex = -3 (#2)

+    - same as #1, but

+    - stub (EXE) + archive is open in Parser

+

+  - formatIndex = -4 (#3)

+    - returns only Parser. skip full file archive. And show other sub-archives

+

+  - formatIndex = -5 (#4)

+    - returns only Parser. skip full file archive. And show other sub-archives for each byte pos

+

+*/

+

+

+

+

 using namespace NWindows;

 

-// Static-SFX (for Linux) can be big.

-const UInt64 kMaxCheckStartPosition = 1 << 22;

+/*

+#ifdef _SFX

+#define OPEN_PROPS_PARAM

+#else

+#define OPEN_PROPS_PARAM  , props

+#endif

+*/

 

-HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)

+/*

+CArc::~CArc()

+{

+  GetRawProps.Release();

+  Archive.Release();

+  printf("\nCArc::~CArc()\n");

+}

+*/

+

+#ifndef _SFX

+

+namespace NArchive {

+namespace NParser {

+

+struct CParseItem

+{

+  UInt64 Offset;

+  UInt64 Size;

+  // UInt64 OkSize;

+  UString Name;

+  UString Extension;

+  FILETIME FileTime;

+  UString Comment;

+  UString ArcType;

+  

+  bool FileTime_Defined;

+  bool UnpackSize_Defined;

+  bool NumSubDirs_Defined;

+  bool NumSubFiles_Defined;

+

+  bool IsSelfExe;

+  bool IsNotArcType;

+  

+  UInt64 UnpackSize;

+  UInt64 NumSubDirs;

+  UInt64 NumSubFiles;

+

+  int FormatIndex;

+

+  bool LenIsUnknown;

+

+  CParseItem():

+      LenIsUnknown(false),

+      FileTime_Defined(false),

+      UnpackSize_Defined(false),

+      NumSubFiles_Defined(false),

+      NumSubDirs_Defined(false),

+      IsSelfExe(false),

+      IsNotArcType(false)

+      // OkSize(0)

+    {}

+

+  /*

+  bool IsEqualTo(const CParseItem &item) const

+  {

+    return Offset == item.Offset && Size == item.Size;

+  }

+  */

+

+  void NormalizeOffset()

+  {

+    if ((Int64)Offset < 0)

+    {

+      Size += Offset;

+      // OkSize += Offset;

+      Offset = 0;

+    }

+  }

+};

+

+class CHandler:

+  public IInArchive,

+  public IInArchiveGetStream,

+  public CMyUnknownImp

+{

+public:

+  CObjectVector<CParseItem> _items;

+  UInt64 _maxEndOffset;

+  CMyComPtr<IInStream> _stream;

+

+  MY_UNKNOWN_IMP2(

+    IInArchive,

+    IInArchiveGetStream)

+

+  INTERFACE_IInArchive(;)

+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);

+

+  UInt64 GetLastEnd() const

+  {

+    if (_items.IsEmpty())

+      return 0;

+    const CParseItem &back = _items.Back();

+    return back.Offset + back.Size;

+  }

+

+  void AddUnknownItem(UInt64 next);

+  int FindInsertPos(const CParseItem &item);

+  void AddItem(const CParseItem &item);

+  // void Init();

+  

+  CHandler()

+  {

+    _maxEndOffset = 0;

+  }

+};

+

+int CHandler::FindInsertPos(const CParseItem &item)

+{

+  unsigned left = 0, right = _items.Size();

+  while (left != right)

+  {

+    unsigned mid = (left + right) / 2;

+    const CParseItem & midItem = _items[mid];

+    if (item.Offset < midItem.Offset)

+      right = mid;

+    else if (item.Offset > midItem.Offset)

+      left = mid + 1;

+    else if (item.Size < midItem.Size)

+      right = mid;

+    else if (item.Size > midItem.Size)

+      left = mid + 1;

+    else

+    {

+      left = mid + 1;

+      // return -1;

+    }

+  }

+  return left;

+}

+

+void CHandler::AddUnknownItem(UInt64 next)

+{

+  /*

+  UInt64 prevEnd = 0;

+  if (!_items.IsEmpty())

+  {

+    const CParseItem &back = _items.Back();

+    prevEnd = back.Offset + back.Size;

+  }

+  */

+  if (_maxEndOffset < next)

+  {

+    CParseItem item2;

+    item2.Offset = _maxEndOffset;

+    item2.Size = next - _maxEndOffset;

+    _maxEndOffset = next;

+    _items.Add(item2);

+  }

+  else if (_maxEndOffset > next && !_items.IsEmpty())

+  {

+    CParseItem &back = _items.Back();

+    if (back.LenIsUnknown)

+    {

+      back.Size = next - back.Offset;

+      _maxEndOffset = next;

+    }

+  }

+}

+

+void CHandler::AddItem(const CParseItem &item)

+{

+  AddUnknownItem(item.Offset);

+  int pos = FindInsertPos(item);

+  if (pos >= 0)

+  {

+    _items.Insert(pos, item);

+    UInt64 next = item.Offset + item.Size;

+    if (_maxEndOffset < next)

+      _maxEndOffset = next;

+  }

+}

+

+/*

+static const STATPROPSTG kProps[] =

+{

+  { NULL, kpidPath, VT_BSTR},

+  { NULL, kpidSize, VT_UI8},

+  { NULL, kpidMTime, VT_FILETIME},

+  { NULL, kpidType, VT_BSTR},

+  { NULL, kpidComment, VT_BSTR},

+  { NULL, kpidOffset, VT_UI8},

+  { NULL, kpidUnpackSize, VT_UI8},

+//   { NULL, kpidNumSubDirs, VT_UI8},

+};

+*/

+

+static const Byte kProps[] =

+{

+  kpidPath,

+  kpidSize,

+  kpidMTime,

+  kpidType,

+  kpidComment,

+  kpidOffset,

+  kpidUnpackSize

+};

+

+IMP_IInArchive_Props

+IMP_IInArchive_ArcProps_NO

+

+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */)

+{

+  COM_TRY_BEGIN

+  {

+    Close();

+    _stream = stream;

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::Close()

+{

+  _items.Clear();

+  _stream.Release();

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)

+{

+  *numItems = _items.Size();

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NCOM::CPropVariant prop;

+

+  const CParseItem &item = _items[index];

+

+  switch (propID)

+  {

+    case kpidPath:

+    {

+      wchar_t sz[32];

+      ConvertUInt32ToString(index + 1, sz);

+      UString s = sz;

+      if (!item.Name.IsEmpty())

+      {

+        s += L'.';

+        s += item.Name;

+      }

+      if (!item.Extension.IsEmpty())

+      {

+        s += L'.';

+        s += item.Extension;

+      }

+      prop = s; break;

+    }

+    case kpidSize:

+    case kpidPackSize: prop = item.Size; break;

+    case kpidOffset: prop = item.Offset; break;

+    case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break;

+    case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break;

+    case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break;

+    case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;

+    case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;

+    case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,

+    Int32 testMode, IArchiveExtractCallback *extractCallback)

+{

+  COM_TRY_BEGIN

+  bool allFilesMode = (numItems == (UInt32)(Int32)-1);

+  if (allFilesMode)

+    numItems = _items.Size();

+  if (_stream && numItems == 0)

+    return S_OK;

+  UInt64 totalSize = 0;

+  UInt32 i;

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

+    totalSize += _items[allFilesMode ? i : indices[i]].Size;

+  extractCallback->SetTotal(totalSize);

+

+  totalSize = 0;

+  

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(extractCallback, false);

+

+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;

+  CMyComPtr<ISequentialInStream> inStream(streamSpec);

+  streamSpec->SetStream(_stream);

+

+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;

+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

+

+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();

+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

+

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

+  {

+    lps->InSize = totalSize;

+    lps->OutSize = totalSize;

+    RINOK(lps->SetCur());

+    CMyComPtr<ISequentialOutStream> realOutStream;

+    Int32 askMode = testMode ?

+        NExtract::NAskMode::kTest :

+        NExtract::NAskMode::kExtract;

+    Int32 index = allFilesMode ? i : indices[i];

+    const CParseItem &item = _items[index];

+

+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));

+    UInt64 unpackSize = item.Size;

+    totalSize += unpackSize;

+    bool skipMode = false;

+    if (!testMode && !realOutStream)

+      continue;

+    RINOK(extractCallback->PrepareOperation(askMode));

+

+    outStreamSpec->SetStream(realOutStream);

+    realOutStream.Release();

+    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);

+

+    Int32 opRes = NExtract::NOperationResult::kOK;

+    RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL));

+    streamSpec->Init(unpackSize);

+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));

+

+    if (outStreamSpec->GetRem() != 0)

+      opRes = NExtract::NOperationResult::kDataError;

+    outStreamSpec->ReleaseStream();

+    RINOK(extractCallback->SetOperationResult(opRes));

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+

+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)

+{

+  COM_TRY_BEGIN

+  const CParseItem &item = _items[index];

+  return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);

+  COM_TRY_END

+}

+

+}}

+

+#endif

+

+HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw()

 {

   NCOM::CPropVariant prop;

   result = false;

-  RINOK(archive->GetProperty(index, propID, &prop));

+  RINOK(arc->GetProperty(index, propID, &prop));

   if (prop.vt == VT_BOOL)

     result = VARIANT_BOOLToBool(prop.boolVal);

   else if (prop.vt != VT_EMPTY)

@@ -30,13 +458,211 @@
   return S_OK;

 }

 

-HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)

+HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw()

 {

-  return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);

+  return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);

+}

+

+HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw()

+{

+  return Archive_GetItemBoolProp(arc, index, kpidIsAux, result);

+}

+

+HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw()

+{

+  return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result);

+}

+

+HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw()

+{

+  return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);

+}

+

+static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result)

+{

+  NCOM::CPropVariant prop;

+  result = false;

+  RINOK(arc->GetArchiveProperty(propid, &prop));

+  if (prop.vt == VT_BOOL)

+    result = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)

+{

+  defined = false;

+  NCOM::CPropVariant prop;

+  RINOK(arc->GetArchiveProperty(propid, &prop));

+  switch (prop.vt)

+  {

+    case VT_UI4: result = prop.ulVal; defined = true; break;

+    case VT_I4: result = 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;

+    default: return E_FAIL;

+  }

+  return S_OK;

+}

+

+static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined)

+{

+  defined = false;

+  NCOM::CPropVariant prop;

+  RINOK(arc->GetArchiveProperty(propid, &prop));

+  switch (prop.vt)

+  {

+    case VT_UI4: result = prop.ulVal; defined = true; break;

+    case VT_I4: result = prop.lVal; defined = true; break;

+    case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break;

+    case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break;

+    case VT_EMPTY: break;

+    default: return E_FAIL;

+  }

+  return S_OK;

+}

+

+HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const

+{

+  if (!GetRawProps)

+    return E_FAIL;

+  UInt32 curIndex = index;

+  bool prevWasAltStream = false;

+  for (;;)

+  {

+    UString s;

+    

+    #ifdef MY_CPU_LE

+    const void *p;

+    UInt32 size;

+    UInt32 propType;

+    RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType));

+    if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)

+      s = (const wchar_t *)p;

+    else

+    #endif

+    {

+      NCOM::CPropVariant prop;

+      RINOK(Archive->GetProperty(curIndex, kpidName, &prop));

+      if (prop.vt == VT_BSTR)

+        s = prop.bstrVal;

+      else if (prop.vt == VT_EMPTY)

+        s = L"[Content]";

+      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 (parent == curParent)

+      return S_OK;

+    if (curParent == (UInt32)(Int32)-1)

+      return E_FAIL;

+    prevWasAltStream = (parentType == NParentType::kAltStream);

+    curIndex = curParent;

+  }

 }

 

 HRESULT CArc::GetItemPath(UInt32 index, UString &result) const

 {

+  #ifdef MY_CPU_LE

+  if (GetRawProps)

+  {

+    const void *p;

+    UInt32 size;

+    UInt32 propType;

+    if (!IsTree)

+    {

+      if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK &&

+          propType == NPropDataType::kUtf16z)

+      {

+        unsigned len = size / 2 - 1;

+        wchar_t *s = result.GetBuffer(len);

+        for (unsigned i = 0; i < len; i++)

+        {

+          wchar_t c = GetUi16(p);

+          p = (const void *)((const Byte *)p + 2);

+          #if WCHAR_PATH_SEPARATOR != L'/'

+          if (c == L'/')

+            c = WCHAR_PATH_SEPARATOR;

+          #endif

+          *s++ = c;

+        }

+        result.ReleaseBuffer(len);

+        if (len != 0)

+          return S_OK;

+      }

+    }

+    /*

+    else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&

+        p && propType == NPropDataType::kUtf16z)

+    {

+      UInt32 totalSize = size;

+      bool isOK = false;

+      {

+        UInt32 index2 = index;

+        for (;;)

+        {

+          UInt32 parent = (UInt32)(Int32)-1;

+          UInt32 parentType = 0;

+          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)

+            break;

+          if (parent == (UInt32)(Int32)-1)

+          {

+            isOK = true;

+            break;

+          }

+          index2 = parent;

+          UInt32 size2;

+          const void *p2;

+          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)

+            break;

+          totalSize += size2;

+        }

+      }

+

+      if (isOK)

+      {

+        wchar_t *sz = result.GetBuffer(totalSize / 2);

+        UInt32 pos = totalSize - size;

+        memcpy((Byte *)sz + pos, p, size - 2);

+        UInt32 index2 = index;

+        for (;;)

+        {

+          UInt32 parent = (UInt32)(Int32)-1;

+          UInt32 parentType = 0;

+          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)

+            break;

+          if (parent == (UInt32)(Int32)-1)

+            break;

+          index2 = parent;

+          UInt32 size2;

+          const void *p2;

+          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)

+            break;

+          pos -= size2;

+          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

+        return S_OK;

+      }

+    }

+    */

+  }

+  #endif

+  

   {

     NCOM::CPropVariant prop;

     RINOK(Archive->GetProperty(index, kpidPath, &prop));

@@ -47,6 +673,7 @@
     else

       return E_FAIL;

   }

+  

   if (result.IsEmpty())

   {

     result = DefaultName;

@@ -63,6 +690,61 @@
   return S_OK;

 }

 

+HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const

+{

+  RINOK(GetItemPath(index, result));

+  if (Ask_Deleted)

+  {

+    bool isDeleted = false;

+    RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted));

+    if (isDeleted)

+      result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR);

+  }

+  return S_OK;

+}

+

+#ifndef _SFX

+

+static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)

+{

+  NCOM::CPropVariant prop;

+  defined = false;

+  size = 0;

+  RINOK(archive->GetProperty(index, kpidSize, &prop));

+  switch (prop.vt)

+  {

+    case VT_UI1: size = prop.bVal; break;

+    case VT_UI2: size = prop.uiVal; break;

+    case VT_UI4: size = prop.ulVal; break;

+    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;

+    case VT_EMPTY: return S_OK;

+    default: return E_FAIL;

+  }

+  defined = true;

+  return S_OK;

+}

+

+#endif

+

+HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const

+{

+  NCOM::CPropVariant prop;

+  defined = false;

+  size = 0;

+  RINOK(Archive->GetProperty(index, kpidSize, &prop));

+  switch (prop.vt)

+  {

+    case VT_UI1: size = prop.bVal; break;

+    case VT_UI2: size = prop.uiVal; break;

+    case VT_UI4: size = prop.ulVal; break;

+    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;

+    case VT_EMPTY: return S_OK;

+    default: return E_FAIL;

+  }

+  defined = true;

+  return S_OK;

+}

+

 HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const

 {

   NCOM::CPropVariant prop;

@@ -85,6 +767,7 @@
 }

 

 #ifndef _SFX

+

 static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)

 {

   for (size_t i = 0; i < size; i++)

@@ -92,296 +775,2026 @@
       return false;

   return true;

 }

+

+static void MakeCheckOrder(CCodecs *codecs,

+    CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,

+    const Byte *data, size_t dataSize)

+{

+  for (unsigned i = 0; i < numTypes; i++)

+  {

+    int index = orderIndices[i];

+    if (index < 0)

+      continue;

+    const CArcInfoEx &ai = codecs->Formats[index];

+    if (ai.SignatureOffset != 0)

+    {

+      orderIndices2.Add(index);

+      orderIndices[i] = -1;

+      continue;

+    }

+

+    const CObjectVector<CByteBuffer> &sigs = ai.Signatures;

+    FOR_VECTOR (k, sigs)

+    {

+      const CByteBuffer &sig = sigs[k];

+      if (sig.Size() == 0 && dataSize == 0 ||

+          sig.Size() != 0 && sig.Size() <= dataSize &&

+          TestSignature(data, sig, sig.Size()))

+      {

+        orderIndices2.Add(index);

+        orderIndices[i] = -1;

+        break;

+      }

+    }

+  }

+}

+

 #endif

 

 #ifdef UNDER_CE

-static const int kNumHashBytes = 1;

-#define HASH_VAL(buf, pos) ((buf)[pos])

+  static const unsigned kNumHashBytes = 1;

+  #define HASH_VAL(buf, pos) ((buf)[pos])

 #else

-static const int kNumHashBytes = 2;

-#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))

+  static const unsigned kNumHashBytes = 2;

+  #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))

 #endif

 

 

-HRESULT CArc::OpenStream(

-    CCodecs *codecs,

-    int formatIndex,

-    IInStream *stream,

-    ISequentialInStream *seqStream,

-    IArchiveOpenCallback *callback)

+#ifndef _SFX

+

+static bool IsExeExt(const UString &ext)

 {

-  Archive.Release();

+  return ext.IsEqualToNoCase(L"exe");

+}

+

+static const char *k_PreArcFormats[] =

+{

+    "pe"

+  , "elf"

+  , "macho"

+  , "mub"

+  , "te"

+};

+

+static bool IsNameFromList(const UString &s, const char *names[], size_t num)

+{

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

+    if (StringsAreEqualNoCase_Ascii(s, names[i]))

+      return true;

+  return false;

+}

+

+

+static bool IsPreArcFormat(const CArcInfoEx &ai)

+{

+  if (ai.Flags_PreArc())

+    return true;

+  return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats));

+}

+

+static const char *k_Formats_with_simple_signuature[] =

+{

+    "7z"

+  , "xz"

+  , "rar"

+  , "bzip2"

+  , "gzip"

+  , "cab"

+  , "wim"

+  , "rpm"

+  , "vhd"

+  , "xar"

+};

+

+static bool IsNewStyleSignature(const CArcInfoEx &ai)

+{

+  // if (ai.Version >= 0x91F)

+  if (ai.NewInterface)

+    return true;

+  return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature));

+}

+

+class CArchiveOpenCallback_Offset:

+  public IArchiveOpenCallback,

+  #ifndef _NO_CRYPTO

+  public ICryptoGetTextPassword,

+  #endif

+  public CMyUnknownImp

+{

+public:

+  CMyComPtr<IArchiveOpenCallback> Callback;

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

+  #ifndef _NO_CRYPTO

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+  #endif

+};

+

+#ifndef _NO_CRYPTO

+STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)

+{

+  COM_TRY_BEGIN

+  if (GetTextPassword)

+    return GetTextPassword->CryptoGetTextPassword(password);

+  return E_NOTIMPL;

+  COM_TRY_END

+}

+#endif

+

+STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)

+{

+  if (!Callback)

+    return S_OK;

+  UInt64 value = Offset;

+  if (bytes)

+    value += *bytes;

+  return Callback->SetCompleted(&Files, &value);

+}

+

+#endif

+

+UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)

+{

+  if (isDefinedProp != NULL)

+    *isDefinedProp = false;

+

+  switch (prop.vt)

+  {

+    case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart;

+    case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal;

+    case VT_EMPTY: return 0;

+    default: throw 151199;

+  }

+}

+

+void CArcErrorInfo::ClearErrors()

+{

+  // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!!

+

+  ThereIsTail = false;

+  UnexpecedEnd = false;

+  IgnoreTail = false;

+  // NonZerosTail = false;

+  ErrorFlags_Defined = false;

+  ErrorFlags = 0;

+  WarningFlags = 0;

+  TailSize = 0;

+

   ErrorMessage.Empty();

+  WarningMessage.Empty();

+}

+

+HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)

+{

+  // OkPhySize_Defined = false;

+  PhySizeDefined = false;

+  PhySize = 0;

+  Offset = 0;

+  AvailPhySize = FileSize - startPos;

+

+  ErrorInfo.ClearErrors();

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop));

+    ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined);

+  }

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop));

+    ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop);

+  }

+

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidError, &prop));

+    if (prop.vt != VT_EMPTY)

+      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";

+  }

+  

+  if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())

+  {

+    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined));

+    /*

+    RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));

+    if (!OkPhySize_Defined)

+    {

+      OkPhySize_Defined = PhySizeDefined;

+      OkPhySize = PhySize;

+    }

+    */

+

+    bool offsetDefined;

+    RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined));

+

+    Int64 globalOffset = startPos + Offset;

+    AvailPhySize = FileSize - globalOffset;

+    if (PhySizeDefined)

+    {

+      UInt64 endPos = globalOffset + PhySize;

+      if (endPos < FileSize)

+      {

+        AvailPhySize = PhySize;

+        ErrorInfo.ThereIsTail = true;

+        ErrorInfo.TailSize = FileSize - endPos;

+      }

+      else if (endPos > FileSize)

+        ErrorInfo.UnexpecedEnd = true;

+    }

+  }

+

+  return S_OK;

+}

+

+/*

+static PrintNumber(const char *s, int n)

+{

+  char temp[100];

+  sprintf(temp, "%s %d", s, n);

+  OutputDebugStringA(temp);

+}

+*/

+

+HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)

+{

+  // OutputDebugStringW(L"a1");

+  // PrintNumber("formatIndex", formatIndex);

+    

+  RINOK(op.codecs->CreateInArchive(formatIndex, archive));

+  // OutputDebugStringW(L"a2");

+  if (!archive)

+    return S_OK;

+

+  #ifdef EXTERNAL_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];

+  if (ai.Flags_PreArc())

+  {

+    /* we notify parsers that extract executables, that they don't need

+       to open archive, if there is tail after executable (for SFX cases) */

+    CMyComPtr<IArchiveAllowTail> allowTail;

+    archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);

+    if (allowTail)

+      allowTail->AllowTail(BoolToInt(true));

+  }

+  if (op.props)

+  {

+    /*

+    FOR_VECTOR (y, op.props)

+    {

+      const COptionalOpenProperties &optProps = (*op.props)[y];

+      if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)

+      {

+        RINOK(SetProperties(archive, optProps.Props));

+        break;

+      }

+    }

+    */

+    RINOK(SetProperties(archive, *op.props));

+  }

+  #endif

+  return S_OK;

+}

+

+#ifndef _SFX

+

+static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)

+{

+  pi.Extension = ai.GetMainExt();

+  pi.FileTime_Defined = false;

+  pi.ArcType = ai.Name;

+  

+  RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType));

+

+  // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe));

+  pi.IsSelfExe = ai.Flags_PreArc();

+  

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidMTime, &prop));

+    if (prop.vt == VT_FILETIME)

+    {

+      pi.FileTime_Defined = true;

+      pi.FileTime = prop.filetime;

+    }

+  }

+  

+  if (!pi.FileTime_Defined)

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidCTime, &prop));

+    if (prop.vt == VT_FILETIME)

+    {

+      pi.FileTime_Defined = true;

+      pi.FileTime = prop.filetime;

+    }

+  }

+  

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidName, &prop));

+    if (prop.vt == VT_BSTR)

+    {

+      pi.Name = prop.bstrVal;

+      pi.Extension.Empty();

+    }

+    else

+    {

+      RINOK(archive->GetArchiveProperty(kpidExtension, &prop));

+      if (prop.vt == VT_BSTR)

+        pi.Extension = prop.bstrVal;

+    }

+  }

+  

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetArchiveProperty(kpidShortComment, &prop));

+    if (prop.vt == VT_BSTR)

+      pi.Comment = prop.bstrVal;

+  }

+

+

+  UInt32 numItems;

+  RINOK(archive->GetNumberOfItems(&numItems));

+  

+  // pi.NumSubFiles = numItems;

+  // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined));

+  // if (!pi.UnpackSize_Defined)

+  {

+    pi.NumSubFiles = 0;

+    pi.NumSubDirs = 0;

+    pi.UnpackSize = 0;

+    for (UInt32 i = 0; i < numItems; i++)

+    {

+      UInt64 size = 0;

+      bool defined = false;

+      Archive_GetItem_Size(archive, i, size, defined);

+      if (defined)

+      {

+        pi.UnpackSize_Defined = true;

+        pi.UnpackSize += size;

+      }

+

+      bool isDir = false;

+      Archive_IsItem_Folder(archive, i, isDir);

+      if (isDir)

+        pi.NumSubDirs++;

+      else

+        pi.NumSubFiles++;

+    }

+    if (pi.NumSubDirs != 0)

+      pi.NumSubDirs_Defined = true;

+    pi.NumSubFiles_Defined = true;

+  }

+

+  return S_OK;

+}

+

+#endif

+

+HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset)

+{

+  if (!op.stream)

+    return S_OK;

+  RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL));

+  const UInt32 kBufSize = 1 << 11;

+  Byte buf[kBufSize];

+  

+  for (;;)

+  {

+    UInt32 processed = 0;

+    RINOK(op.stream->Read(buf, kBufSize, &processed));

+    if (processed == 0)

+    {

+      // ErrorInfo.NonZerosTail = false;

+      ErrorInfo.IgnoreTail = true;

+      return S_OK;

+    }

+    for (size_t i = 0; i < processed; i++)

+    {

+      if (buf[i] != 0)

+      {

+        // ErrorInfo.IgnoreTail = false;

+        // ErrorInfo.NonZerosTail = true;

+        return S_OK;

+      }

+    }

+  }

+}

+

+#ifndef _SFX

+

+class CExtractCallback_To_OpenCallback:

+  public IArchiveExtractCallback,

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+public:

+  CMyComPtr<IArchiveOpenCallback> Callback;

+  UInt64 Files;

+  UInt64 Offset;

+

+  MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo)

+  INTERFACE_IArchiveExtractCallback(;)

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+  void Init(IArchiveOpenCallback *callback)

+  {

+    Callback = callback;

+    Files = 0;

+    Offset = 0;

+  }

+};

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)

+{

+  if (Callback)

+  {

+    UInt64 value = Offset;

+    if (inSize)

+      value += *inSize;

+    return Callback->SetCompleted(&Files, &value);

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */)

+{

+  *outStream = 0;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */)

+{

+  return S_OK;

+}

+

+static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,

+    IInStream *stream, const UInt64 *maxCheckStartPosition,

+    IArchiveOpenCallback *openCallback,

+    IArchiveExtractCallback *extractCallback)

+{

+  /*

+  if (needPhySize)

+  {

+    CMyComPtr<IArchiveOpen2> open2;

+    archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2);

+    if (open2)

+      return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);

+  }

+  */

+  RINOK(archive->Open(stream, maxCheckStartPosition, openCallback));

+  if (needPhySize)

+  {

+    bool phySize_Defined = false;

+    UInt64 phySize = 0;

+    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined));

+    if (phySize_Defined)

+      return S_OK;

+

+    bool phySizeCantBeDetected = false;;

+    RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));

+

+    if (!phySizeCantBeDetected)

+    {

+      RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback));

+    }

+  }

+  return S_OK;

+}

+

+static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)

+{

+  FOR_VECTOR (i, orderIndices)

+    if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name))

+      return i;

+  return -1;

+}

+

+#endif

+

+HRESULT CArc::OpenStream2(const COpenOptions &op)

+{

+  // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout);

+

+  Archive.Release();

+  GetRawProps.Release();

+  GetRootProps.Release();

+

+  ErrorInfo.ClearErrors();

+  ErrorInfo.ErrorFormatIndex = -1;

+

+  IsParseArc = false;

+  ArcStreamOffset = 0;

+  

+  // OutputDebugStringW(L"1");

+  // OutputDebugStringW(Path);

+

   const UString fileName = ExtractFileNameFromPath(Path);

   UString extension;

   {

     int dotPos = fileName.ReverseFind(L'.');

     if (dotPos >= 0)

-      extension = fileName.Mid(dotPos + 1);

+      extension = fileName.Ptr(dotPos + 1);

   }

-  CIntVector orderIndices;

-  if (formatIndex >= 0)

-    orderIndices.Add(formatIndex);

-  else

-  {

-

-  int i;

-  int numFinded = 0;

-  for (i = 0; i < codecs->Formats.Size(); i++)

-    if (codecs->Formats[i].FindExtension(extension) >= 0)

-      orderIndices.Insert(numFinded++, i);

-    else

-      orderIndices.Add(i);

   

-  if (!stream)

+  CIntVector orderIndices;

+  

+  bool searchMarkerInHandler = false;

+  #ifdef _SFX

+    searchMarkerInHandler = true;

+  #endif

+

+  CBoolArr isMainFormatArr(op.codecs->Formats.Size());

   {

-    if (numFinded != 1)

-      return E_NOTIMPL;

-    orderIndices.DeleteFrom(1);

+    FOR_VECTOR(i, op.codecs->Formats)

+      isMainFormatArr[i] = false;

   }

 

+  UInt64 maxStartOffset =

+      op.openType.MaxStartOffset_Defined ?

+      op.openType.MaxStartOffset :

+      kMaxCheckStartPosition;

+

   #ifndef _SFX

-  if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))

-  {

-    CIntVector orderIndices2;

-    CByteBuffer byteBuffer;

-    const size_t kBufferSize = (1 << 21);

-    byteBuffer.SetCapacity(kBufferSize);

-    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

-    size_t processedSize = kBufferSize;

-    RINOK(ReadStream(stream, byteBuffer, &processedSize));

-    if (processedSize == 0)

-      return S_FALSE;

+  bool isUnknownExt = false;

+  #endif

 

-    const Byte *buf = byteBuffer;

-    CByteBuffer hashBuffer;

-    const UInt32 kNumVals = 1 << (kNumHashBytes * 8);

-    hashBuffer.SetCapacity(kNumVals);

+  bool isForced = false;

+  unsigned numMainTypes = 0;

+  int formatIndex = op.openType.FormatIndex;

+

+  if (formatIndex >= 0)

+  {

+    isForced = true;

+    orderIndices.Add(formatIndex);

+    numMainTypes = 1;

+    isMainFormatArr[formatIndex] = true;

+

+    searchMarkerInHandler = true;

+  }

+  else

+  {

+    unsigned numFinded = 0;

+    #ifndef _SFX

+    bool isPrearcExt = false;

+    #endif

+    

+    {

+      FOR_VECTOR (i, op.codecs->Formats)

+      {

+        const CArcInfoEx &ai = op.codecs->Formats[i];

+

+        if (IgnoreSplit || !op.openType.CanReturnArc)

+          if (ai.IsSplit())

+            continue;

+        if (op.excludedFormats->FindInSorted(i) >= 0)

+          continue;

+

+        #ifndef _SFX

+        if (IsPreArcFormat(ai))

+          isPrearcExt = true;

+        #endif

+

+        if (ai.FindExtension(extension) >= 0)

+        {

+          // PrintNumber("orderIndices.Insert", i);

+          orderIndices.Insert(numFinded++, i);

+          isMainFormatArr[i] = true;

+        }

+        else

+          orderIndices.Add(i);

+      }

+    }

+  

+    if (!op.stream)

+    {

+      if (numFinded != 1)

+        return E_NOTIMPL;

+      orderIndices.DeleteFrom(1);

+    }

+    // PrintNumber("numFinded", numFinded );

+

+    /*

+    if (op.openOnlySpecifiedByExtension)

+    {

+      if (numFinded != 0 && !IsExeExt(extension))

+        orderIndices.DeleteFrom(numFinded);

+    }

+    */

+

+    #ifndef _SFX

+

+      if (op.stream && orderIndices.Size() >= 2)

+      {

+        RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+        CByteBuffer byteBuffer;

+        CIntVector orderIndices2;

+        if (numFinded == 0 || IsExeExt(extension))

+        {

+          // signature search was here

+        }

+        else if (extension == L"000" || extension == L"001")

+        {

+          int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");

+          if (i >= 0)

+          {

+            const size_t kBufSize = (1 << 10);

+            byteBuffer.Alloc(kBufSize);

+            size_t processedSize = kBufSize;

+            RINOK(ReadStream(op.stream, byteBuffer, &processedSize));

+            if (processedSize >= 16)

+            {

+              const Byte *buf = byteBuffer;

+              const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };

+              if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0)

+              {

+                orderIndices2.Add(orderIndices[i]);

+                orderIndices[i] = -1;

+                if (i >= (int)numFinded)

+                  numFinded++;

+              }

+            }

+          }

+        }

+        else

+        {

+          const size_t kBufSize = (1 << 10);

+          byteBuffer.Alloc(kBufSize);

+          size_t processedSize = kBufSize;

+          RINOK(ReadStream(op.stream, byteBuffer, &processedSize));

+          if (processedSize == 0)

+            return S_FALSE;

+          

+          /*

+          check type order:

+            1) matched extension, no signuature

+            2) matched extension, matched signuature

+            // 3) no signuature

+            // 4) matched signuature

+          */

+

+          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);

+          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);

+          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0);

+          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize);

+        }

+      

+        FOR_VECTOR (i, orderIndices)

+        {

+          int val = orderIndices[i];

+          if (val != -1)

+            orderIndices2.Add(val);

+        }

+        orderIndices = orderIndices2;

+      }

+      

+      if (orderIndices.Size() >= 2)

+      {

+        int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso");

+        int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf");

+        if (iUdf > iIso && iIso >= 0)

+        {

+          int isoIndex = orderIndices[iIso];

+          int udfIndex = orderIndices[iUdf];

+          orderIndices[iUdf] = isoIndex;

+          orderIndices[iIso] = udfIndex;

+        }

+      }

+

+      numMainTypes = numFinded;

+      isUnknownExt = (numMainTypes == 0) || isPrearcExt;

+

+    #else // _SFX

+

+      numMainTypes = orderIndices.Size();

+    

+    #endif

+  }

+

+  UInt64 fileSize = 0;

+  if (op.stream)

+  {

+    RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));

+    RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+  }

+  FileSize = fileSize;

+

+

+  #ifndef _SFX

+

+  CBoolArr skipFrontalFormat(op.codecs->Formats.Size());

+  {

+    FOR_VECTOR(i, op.codecs->Formats)

+      skipFrontalFormat[i] = false;

+  }

+  

+  #endif

+

+  const COpenType &mode = op.openType;

+

+  

+  

+

+  

+  if (mode.CanReturnArc)

+  {

+    // ---------- OPEN main type by extenssion ----------

+  

+    unsigned numCheckTypes = orderIndices.Size();

+    if (formatIndex >= 0)

+      numCheckTypes = numMainTypes;

+    

+    for (unsigned i = 0; i < numCheckTypes; i++)

+    {

+      FormatIndex = orderIndices[i];

+      const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

+      // OutputDebugStringW(ai.Name);

+      

+      bool exactOnly = false;

+      if (i >= numMainTypes)

+      {

+        if (!ai.Flags_BackwardOpen()

+            // && !ai.Flags_PureStartOpen()

+            )

+          continue;

+        exactOnly = true;

+      }

+      

+      // Some handlers do not set total bytes. So we set it here

+      RINOK(op.callback->SetTotal(NULL, &fileSize));

+      if (op.stream)

+      {

+        RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+      }

+      

+      CMyComPtr<IInArchive> archive;

+      

+      RINOK(PrepareToOpen(op, FormatIndex, archive));

+      if (!archive)

+        continue;

+      

+      HRESULT result;

+      if (op.stream)

+      {

+        UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;

+        result = archive->Open(op.stream, &searchLimit, op.callback);

+      }

+      else

+      {

+        CMyComPtr<IArchiveOpenSeq> openSeq;

+        archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);

+        if (!openSeq)

+          return E_NOTIMPL;

+        result = openSeq->OpenSeq(op.seqStream);

+      }

+      

+      RINOK(ReadBasicProps(archive, 0, result));

+      

+      if (result == S_FALSE)

+      {

+        bool isArc = ErrorInfo.IsArc_After_NonOpen();

+

+        #ifndef _SFX

+        // if it's archive, we allow another open attempt for parser

+        if (!mode.CanReturnParser || !isArc)

+          skipFrontalFormat[FormatIndex] = true;

+        #endif

+        

+        if (exactOnly)

+          continue;

+        

+        if (i == 0 && numMainTypes == 1)

+        {

+          // we set NonOpenErrorInfo, only if there is only one main format (defined by extension).

+          ErrorInfo.ErrorFormatIndex = FormatIndex;

+          NonOpen_ErrorInfo = ErrorInfo;

+       

+          if (!mode.CanReturnParser && isArc)

+          {

+            // if (formatIndex < 0 && !searchMarkerInHandler)

+            {

+              // if bad archive was detected, we don't need additional open attempts

+              #ifndef _SFX

+              if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */)

+              #endif

+                return S_FALSE;

+            }

+          }

+        }

+        

+        /*

+        #ifndef _SFX

+        if (IsExeExt(extension) || ai.Flags_PreArc())

+        {

+        // openOnlyFullArc = false;

+        // canReturnTailArc = true;

+        // limitSignatureSearch = true;

+        }

+        #endif

+        */

+        

+        continue;

+      }

+      

+      RINOK(result);

+      

+      #ifndef _SFX

+

+      bool isMainFormat = isMainFormatArr[FormatIndex];

+      const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);

+

+      bool thereIsTail = ErrorInfo.ThereIsTail;

+      if (thereIsTail && mode.ZerosTailIsAllowed)

+      {

+        RINOK(CheckZerosTail(op, Offset + PhySize));

+        if (ErrorInfo.IgnoreTail)

+          thereIsTail = false;

+      }

+

+      if (Offset > 0)

+      {

+        if (exactOnly

+            || !searchMarkerInHandler

+            || !specFlags.CanReturn_NonStart()

+            || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset))

+          continue;

+      }

+      if (thereIsTail)

+      {

+        if (Offset > 0)

+        {

+          if (!specFlags.CanReturnMid)

+            continue;

+        }

+        else if (!specFlags.CanReturnFrontal)

+          continue;

+      }

+

+      if (Offset > 0 || thereIsTail)

+      {

+        if (formatIndex < 0)

+        {

+          if (IsPreArcFormat(ai))

+          {

+            // openOnlyFullArc = false;

+            // canReturnTailArc = true;

+            /*

+            if (mode.SkipSfxStub)

+            limitSignatureSearch = true;

+            */

+            // if (mode.SkipSfxStub)

+            {

+              // skipFrontalFormat[FormatIndex] = true;

+              continue;

+            }

+          }

+        }

+      }

+     

+      #endif

+

+      Archive = archive;

+      return S_OK;

+    }

+  }

+

+  

+

+  #ifndef _SFX

+

+  if (!op.stream)

+    return S_FALSE;

+

+  if (formatIndex >= 0 && !mode.CanReturnParser)

+  {

+    if (mode.MaxStartOffset_Defined)

+    {

+      if (mode.MaxStartOffset == 0)

+        return S_FALSE;

+    }

+    else

+    {

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

+      }

+    }

+  }

+

+  NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler;

+  CMyComPtr<IInArchive> handler = handlerSpec;

+

+  CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;

+  CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;

+  extractCallback_To_OpenCallback_Spec->Init(op.callback);

+

+  {

+    // ---------- Check all possible START archives ----------

+    // this code is better for full file archives than Parser's code.

+

+    CByteBuffer byteBuffer;

+    bool endOfFile = false;

+    size_t processedSize;

+    {

+      size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF)

+      if (bufSize > fileSize)

+      {

+        bufSize = (size_t)fileSize;

+        endOfFile = true;

+      }

+      byteBuffer.Alloc(bufSize);

+      RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+      processedSize = bufSize;

+      RINOK(ReadStream(op.stream, byteBuffer, &processedSize));

+      if (processedSize == 0)

+        return S_FALSE;

+      if (processedSize < bufSize)

+        endOfFile = true;

+    }

+    CUIntVector sortedFormats;

+

+    unsigned i;

+

+    int splitIndex = -1;

+

+    for (i = 0; i < orderIndices.Size(); i++)

+    {

+      unsigned form = orderIndices[i];

+      if (skipFrontalFormat[form])

+        continue;

+      const CArcInfoEx &ai = op.codecs->Formats[form];

+      if (ai.IsSplit())

+      {

+        splitIndex = form;

+        continue;

+      }

+

+      if (ai.IsArcFunc)

+      {

+        UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize);

+        if (isArcRes == k_IsArc_Res_NO)

+          continue;

+        if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)

+          continue;

+        // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue;

+        sortedFormats.Insert(0, form);

+        continue;

+      }

+

+      bool isNewStyleSignature = IsNewStyleSignature(ai);

+      bool needCheck = !isNewStyleSignature

+          || ai.Signatures.IsEmpty()

+          || ai.Flags_PureStartOpen()

+          || ai.Flags_StartOpen()

+          || ai.Flags_BackwardOpen();

+    

+      if (isNewStyleSignature && !ai.Signatures.IsEmpty())

+      {

+        unsigned k;

+        for (k = 0; k < ai.Signatures.Size(); k++)

+        {

+          const CByteBuffer &sig = ai.Signatures[k];

+          UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();

+          if (processedSize < signatureEnd)

+          {

+            if (!endOfFile)

+              needCheck = true;

+          }

+          else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0)

+            break;

+        }

+        if (k != ai.Signatures.Size())

+        {

+          sortedFormats.Insert(0, form);

+          continue;

+        }

+      }

+      if (needCheck)

+        sortedFormats.Add(form);

+    }

+

+    if (splitIndex >= 0)

+      sortedFormats.Insert(0, splitIndex);

+

+    for (i = 0; i < sortedFormats.Size(); i++)

+    {

+      FormatIndex = sortedFormats[i];

+      const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

+

+      RINOK(op.callback->SetTotal(NULL, &fileSize));

+      RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+

+      CMyComPtr<IInArchive> archive;

+      RINOK(PrepareToOpen(op, FormatIndex, archive));

+      if (!archive)

+        continue;

+      

+      PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name));

+      HRESULT result;

+      {

+        UInt64 searchLimit = 0;

+        /*

+        if (mode.CanReturnArc)

+          result = archive->Open(op.stream, &searchLimit, op.callback);

+        else

+        */

+        result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback);

+      }

+      

+      if (result == S_FALSE)

+      {

+        skipFrontalFormat[FormatIndex] = true;

+        // FIXME: maybe we must use LenIsUnknown.

+        // printf("  OpenForSize Error");

+        continue;

+      }

+      RINOK(result);

+

+      RINOK(ReadBasicProps(archive, 0, result));

+

+      if (Offset > 0)

+      {

+        continue; // good handler doesn't return such Offset > 0

+        // but there are some cases like false prefixed PK00 archive, when

+        // we can support it?

+      }

+

+      NArchive::NParser::CParseItem pi;

+      pi.Offset = Offset;

+      pi.Size = AvailPhySize;

+      

+      // bool needScan = false;

+

+      if (!PhySizeDefined)

+      {

+        // it's for Z format

+        pi.LenIsUnknown = true;

+        // needScan = true;

+        // phySize = arcRem;

+        // nextNeedCheckStartOpen = false;

+      }

+

+      /*

+      if (OkPhySize_Defined)

+        pi.OkSize = pi.OkPhySize;

+      else

+        pi.OkSize = pi.Size;

+      */

+

+      pi.NormalizeOffset();

+      // printf("  phySize = %8d", (unsigned)phySize);

+

+

+      if (mode.CanReturnArc)

+      {

+        bool isMainFormat = isMainFormatArr[FormatIndex];

+        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);

+        bool openCur = false;

+

+        if (!ErrorInfo.ThereIsTail)

+          openCur = true;

+        else

+        {

+          if (mode.ZerosTailIsAllowed)

+          {

+            RINOK(CheckZerosTail(op, Offset + PhySize));

+            if (ErrorInfo.IgnoreTail)

+              openCur = true;

+          }

+          if (!openCur)

+          {

+            openCur = specFlags.CanReturnFrontal;

+            if (formatIndex < 0) // format is not forced

+            {

+              if (IsPreArcFormat(ai))

+              {

+                // if (mode.SkipSfxStub)

+                {

+                  openCur = false;

+                }

+              }

+            }

+          }

+        }

+        

+        if (openCur)

+        {

+          InStream = op.stream;

+          Archive = archive;

+          return S_OK;

+        }

+      }

+        

+      skipFrontalFormat[FormatIndex] = true;

+

+

+      // if (!mode.CanReturnArc)

+      /*

+      if (!ErrorInfo.ThereIsTail)

+          continue;

+      */

+      if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)

+        continue;

+

+      // printf("\nAdd offset = %d", (int)pi.Offset);

+      RINOK(ReadParseItemProps(archive, ai, pi));

+      handlerSpec->AddItem(pi);

+    }

+  }

+

+  

+

+  

+  

+  // ---------- PARSER ----------

+

+  CUIntVector arc2sig; // formatIndex to signatureIndex

+  CUIntVector sig2arc; // signatureIndex to formatIndex;

+  {

+    unsigned sum = 0;

+    FOR_VECTOR (i, op.codecs->Formats)

+    {

+      arc2sig.Add(sum);

+      const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;

+      sum += sigs.Size();

+      FOR_VECTOR (k, sigs)

+        sig2arc.Add(i);

+    }

+  }

+  

+  {

+    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

+

+    const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8);

+    CByteArr hashBuffer(kNumVals);

     Byte *hash = hashBuffer;

     memset(hash, 0xFF, kNumVals);

     Byte prevs[256];

-    if (orderIndices.Size() >= 256)

+    memset(prevs, 0xFF, sizeof(prevs));

+    if (sig2arc.Size() >= 0xFF)

       return S_FALSE;

-    int i;

-    for (i = 0; i < orderIndices.Size(); i++)

+

+    CUIntVector difficultFormats;

+    CBoolArr difficultBools(256);

     {

-      const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];

-      const CByteBuffer &sig = ai.StartSignature;

-      if (sig.GetCapacity() < kNumHashBytes)

-        continue;

-      UInt32 v = HASH_VAL(sig, 0);

-      prevs[i] = hash[v];

-      hash[v] = (Byte)i;

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

+        difficultBools[i] = false;

     }

 

-    processedSize -= (kNumHashBytes - 1);

-    for (UInt32 pos = 0; pos < processedSize; pos++)

+    bool thereAreHandlersForSearch = false;

+

+    // UInt32 maxSignatureEnd = 0;

+    

+    FOR_VECTOR (i, orderIndices)

     {

-      for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++);

-      if (pos == processedSize)

-        break;

-      UInt32 v = HASH_VAL(buf, pos);

-      Byte *ptr = &hash[v];

-      int i = *ptr;

-      do

+      int index = orderIndices[i];

+      if (index < 0)

+        continue;

+      const CArcInfoEx &ai = op.codecs->Formats[index];

+      bool isDifficult = false;

+      // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)

+      if (!ai.NewInterface)

+        isDifficult = true;

+      else

       {

-        int index = orderIndices[i];

-        const CArcInfoEx &ai = codecs->Formats[index];

-        const CByteBuffer &sig = ai.StartSignature;

-        if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&

-            TestSignature(buf + pos, sig, sig.GetCapacity()))

+        if (ai.Flags_StartOpen())

+          isDifficult = true;

+        FOR_VECTOR (k, ai.Signatures)

         {

-          orderIndices2.Add(index);

-          orderIndices[i] = 0xFF;

-          *ptr = prevs[i];

+          const CByteBuffer &sig = ai.Signatures[k];

+          /*

+          UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();

+          if (maxSignatureEnd < signatureEnd)

+            maxSignatureEnd = signatureEnd;

+          */

+          if (sig.Size() < kNumHashBytes)

+          {

+            isDifficult = true;

+            continue;

+          }

+          thereAreHandlersForSearch = true;

+          UInt32 v = HASH_VAL(sig, 0);

+          unsigned sigIndex = arc2sig[index] + k;

+          prevs[sigIndex] = hash[v];

+          hash[v] = (Byte)sigIndex;

         }

-        else

-          ptr = &prevs[i];

-        i = *ptr;

       }

-      while (i != 0xFF);

+      if (isDifficult)

+      {

+        difficultFormats.Add(index);

+        difficultBools[index] = true;

+      }

     }

     

-    for (i = 0; i < orderIndices.Size(); i++)

+    if (!thereAreHandlersForSearch)

     {

-      int val = orderIndices[i];

-      if (val != 0xFF)

-        orderIndices2.Add(val);

+      // openOnlyFullArc = true;

+      // canReturnTailArc = true;

     }

-    orderIndices = orderIndices2;

-  }

-  else if (extension == L"000" || extension == L"001")

-  {

-    CByteBuffer byteBuffer;

-    const size_t kBufferSize = (1 << 10);

-    byteBuffer.SetCapacity(kBufferSize);

-    Byte *buffer = byteBuffer;

-    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

-    size_t processedSize = kBufferSize;

-    RINOK(ReadStream(stream, buffer, &processedSize));

-    if (processedSize >= 16)

+    

+    RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+

+    CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;

+    CMyComPtr<IInStream> limitedStream = limitedStreamSpec;

+    limitedStreamSpec->SetStream(op.stream);

+

+    openCallback_Offset_Spec->Callback = op.callback;

+

+    #ifndef _NO_CRYPTO

+    if (op.callback)

     {

-      Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};

-      if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0)

+      openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);

+    }

+    #endif

+

+    RINOK(op.callback->SetTotal(NULL, &fileSize));

+    CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;

+    byteBuffer.Alloc(kBufSize);

+

+    UInt64 callbackPrev = 0;

+    bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos.

+

+    bool endOfFile = false;

+    UInt64 bufPhyPos = 0;

+    size_t bytesInBuf = 0;

+    // UInt64 prevPos = 0;

+    

+    // ---------- Main Scan Loop ----------

+

+    UInt64 pos = 0;

+

+    if (!mode.EachPos && handlerSpec->_items.Size() == 1)

+    {

+      NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];

+      if (!pi.LenIsUnknown && pi.Offset == 0)

+        pos = pi.Size;

+    }

+

+    for (;;)

+    {

+      // printf("\nPos = %d", (int)pos);

+      UInt64 posInBuf = pos - bufPhyPos;

+      

+      // if (pos > ((UInt64)1 << 35)) break;

+      

+      if (!endOfFile)

       {

-        for (int i = 0; i < orderIndices.Size(); i++)

+        if (bytesInBuf < kBufSize)

         {

-          int index = orderIndices[i];

-          const CArcInfoEx &ai = codecs->Formats[index];

-          if (ai.Name.CompareNoCase(L"rar") != 0)

+          size_t processedSize = kBufSize - bytesInBuf;

+          // printf("\nRead ask = %d", (unsigned)processedSize);

+          UInt64 seekPos = bufPhyPos + bytesInBuf;

+          RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL));

+          RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize));

+          // printf("   processed = %d", (unsigned)processedSize);

+          if (processedSize == 0)

+          {

+            fileSize = seekPos;

+            endOfFile = true;

+          }

+          else

+          {

+            bytesInBuf += processedSize;

+            limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos);

+          }

+          continue;

+        }

+        

+        if (bytesInBuf < posInBuf)

+        {

+          UInt64 skipSize = posInBuf - bytesInBuf;

+          if (skipSize <= kBeforeSize)

+          {

+            size_t keepSize = (size_t)(kBeforeSize - skipSize);

+            // printf("\nmemmove skip = %d", (int)keepSize);

+            memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize);

+            bytesInBuf = keepSize;

+            bufPhyPos = pos - keepSize;

             continue;

-          orderIndices.Delete(i--);

-          orderIndices.Insert(0, index);

-          break;

+          }

+          // printf("\nSkip %d", (int)(skipSize - kBeforeSize));

+          // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL));

+          bytesInBuf = 0;

+          bufPhyPos = pos - kBeforeSize;

+          continue;

+        }

+        

+        if (bytesInBuf - posInBuf < kAfterSize)

+        {

+          size_t beg = (size_t)posInBuf - kBeforeSize;

+          // printf("\nmemmove for after beg = %d", (int)beg);

+          memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg);

+          bufPhyPos += beg;

+          bytesInBuf -= beg;

+          continue;

         }

       }

+

+      if (pos >= callbackPrev + (1 << 23))

+      {

+        openCallback_Offset_Spec->Files = handlerSpec->_items.Size();

+        openCallback_Offset_Spec->Offset = pos;

+        RINOK(openCallback_Offset->SetCompleted(NULL, NULL));

+        callbackPrev = pos;

+      }

+

+      {

+        UInt64 endPos = bufPhyPos + bytesInBuf;

+        if (fileSize < endPos)

+        {

+          FileSize = fileSize; // why ????

+          fileSize = endPos;

+        }

+      }

+

+      size_t availSize = bytesInBuf - (size_t)posInBuf;

+      if (availSize < kNumHashBytes)

+        break;

+      size_t scanSize = availSize -

+          ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes);

+  

+      {

+        /*

+        UInt64 scanLimit = openOnlyFullArc ?

+            maxSignatureEnd :

+            op.openType.ScanSize + maxSignatureEnd;

+        */

+        if (!mode.CanReturnParser)

+        {

+          if (pos > maxStartOffset)

+            break;

+          UInt64 remScan = maxStartOffset - pos;

+          if (scanSize > remScan)

+            scanSize = (size_t)remScan;

+        }

+      }

+

+      scanSize++;

+

+      const Byte *buf = byteBuffer + (size_t)posInBuf;

+      size_t ppp = 0;

+      

+      if (!needCheckStartOpen)

+      {

+        for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++);

+        pos += ppp;

+        if (ppp == scanSize)

+          continue;

+      }

+      

+      UInt32 v = HASH_VAL(buf, ppp);

+      bool nextNeedCheckStartOpen = true;

+      unsigned i = hash[v];

+      unsigned indexOfDifficult = 0;

+

+      // ---------- Open Loop for Current Pos ----------

+      bool wasOpen = false;

+      

+      for (;;)

+      {

+        unsigned index;

+        bool isDifficult;

+        if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size())

+        {

+          index = difficultFormats[indexOfDifficult++];

+          isDifficult = true;

+        }

+        else

+        {

+          if (i == 0xFF)

+            break;

+          index = sig2arc[i];

+          unsigned sigIndex = i - arc2sig[index];

+          i = prevs[i];

+          if (needCheckStartOpen && difficultBools[index])

+            continue;

+          const CArcInfoEx &ai = op.codecs->Formats[index];

+

+          if (pos < ai.SignatureOffset)

+            continue;

+

+          /*

+          if (openOnlyFullArc)

+            if (pos != ai.SignatureOffset)

+              continue;

+          */

+  

+          const CByteBuffer &sig = ai.Signatures[sigIndex];

+

+          if (ppp + sig.Size() > availSize

+              || !TestSignature(buf + ppp, sig, sig.Size()))

+            continue;

+          // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));

+          // prevPos = pos;

+          isDifficult = false;

+        }

+

+        const CArcInfoEx &ai = op.codecs->Formats[index];

+

+

+        if ((isDifficult && pos == 0) || ai.SignatureOffset == pos)

+        {

+          // we don't check same archive second time */

+          if (skipFrontalFormat[index])

+            continue;

+        }

+

+        UInt64 startArcPos = pos;

+        if (!isDifficult)

+        {

+          if (pos < ai.SignatureOffset)

+            continue;

+          startArcPos = pos - ai.SignatureOffset;

+          /*

+          // we don't need the check for Z files

+          if (startArcPos < handlerSpec->GetLastEnd())

+            continue;

+          */

+        }

+        

+        if (ai.IsArcFunc && startArcPos >= bufPhyPos)

+        {

+          size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);

+          if (offsetInBuf < bytesInBuf)

+          {

+            UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf);

+            if (isArcRes == k_IsArc_Res_NO)

+              continue;

+            if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)

+              continue;

+            /*

+            if (isArcRes == k_IsArc_Res_YES_LOW_PROB)

+            {

+              // if (pos != ai.SignatureOffset)

+              continue;

+            }

+            */

+          }

+          // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name);

+        }

+        

+        /*

+        if (pos == 67109888)

+          pos = pos;

+        */

+        PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name));

+

+        bool isMainFormat = isMainFormatArr[index];

+        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);

+        

+        CMyComPtr<IInArchive> archive;

+        RINOK(PrepareToOpen(op, index, archive));

+        if (!archive)

+          return E_FAIL;

+        

+        // OutputDebugStringW(ai.Name);

+        

+        UInt64 rem = fileSize - startArcPos;

+        

+        UInt64 arcStreamOffset = 0;

+

+        if (ai.Flags_UseGlobalOffset())

+        {

+          limitedStreamSpec->InitAndSeek(0, fileSize);

+          limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL);

+        }

+        else

+        {

+          limitedStreamSpec->InitAndSeek(startArcPos, rem);

+          arcStreamOffset = startArcPos;

+        }

+        

+        UInt64 maxCheckStartPosition = 0;

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

+     

+        RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));

+

+        bool isOpen = false;

+        if (result == S_FALSE)

+        {

+          if (!mode.CanReturnParser)

+          {

+            if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen())

+            {

+              ErrorInfo.ErrorFormatIndex = index;

+              NonOpen_ErrorInfo = ErrorInfo;

+              // if archive was detected, we don't need additional open attempts

+              return S_FALSE;

+            }

+            continue;

+          }

+          if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0)

+            continue;

+        }

+        else

+        {

+          isOpen = true;

+          RINOK(result);

+          PRF(printf("  OK "));

+        }

+

+        // fprintf(stderr, "\n %8X  %S", startArcPos, Path);

+        // printf("\nOpen OK: %S", ai.Name);

+        

+        

+        NArchive::NParser::CParseItem pi;

+        pi.Offset = startArcPos;

+

+        if (ai.Flags_UseGlobalOffset())

+          pi.Offset = Offset;

+        else if (Offset != 0)

+          return E_FAIL;

+        UInt64 arcRem = FileSize - pi.Offset;

+        UInt64 phySize = arcRem;

+        bool phySizeDefined = PhySizeDefined;

+        if (phySizeDefined)

+        {

+          if (pi.Offset + PhySize > FileSize)

+          {

+            // ErrorInfo.ThereIsTail = true;

+            PhySize = FileSize - pi.Offset;

+          }

+          phySize = PhySize;

+        }

+        if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63))

+          return E_FAIL;

+

+        /*

+        if (!ai.UseGlobalOffset)

+        {

+          if (phySize > arcRem)

+          {

+            ThereIsTail = true;

+            phySize = arcRem;

+          }

+        }

+        */

+        

+        bool needScan = false;

+

+ 

+        if (isOpen && !phySizeDefined)

+        {

+          // it's for Z format

+          pi.LenIsUnknown = true;

+          needScan = true;

+          phySize = arcRem;

+          nextNeedCheckStartOpen = false;

+        }

+

+        pi.Size = phySize;

+        /*

+        if (OkPhySize_Defined)

+          pi.OkSize = OkPhySize;

+        */

+        pi.NormalizeOffset();

+        // printf("  phySize = %8d", (unsigned)phySize);

+

+        /*

+        if (needSkipFullArc)

+          if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize)

+            continue;

+        */

+        if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)

+        {

+          // it's possible for dmg archives

+          if (!mode.CanReturnArc)

+            continue;

+        }

+

+        if (mode.EachPos)

+          pos++;

+        else if (needScan)

+        {

+          pos++;

+          /*

+          if (!OkPhySize_Defined)

+            pos++;

+          else

+            pos = pi.Offset + pi.OkSize;

+          */

+        }

+        else

+          pos = pi.Offset + pi.Size;

+

+       

+        RINOK(ReadParseItemProps(archive, ai, pi));

+

+        if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */)

+        {

+          /* It's for DMG format.

+          This code deletes all previous items that are included to current item */

+            

+          while (!handlerSpec->_items.IsEmpty())

+          {

+            {

+              const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back();

+              if (back.Offset < pi.Offset)

+                break;

+              if (back.Offset + back.Size > pi.Offset + pi.Size)

+                break;

+            }

+            handlerSpec->_items.DeleteBack();

+          }

+        }

+        

+

+        if (isOpen && mode.CanReturnArc && phySizeDefined)

+        {

+          // if (pi.Offset + pi.Size >= fileSize)

+          bool openCur = false;

+

+          bool thereIsTail = ErrorInfo.ThereIsTail;

+          if (thereIsTail && mode.ZerosTailIsAllowed)

+          {

+            RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize));

+            if (ErrorInfo.IgnoreTail)

+              thereIsTail = false;

+          }

+

+          if (pi.Offset != 0)

+          {

+            if (!pi.IsNotArcType)

+              if (thereIsTail)

+                openCur = specFlags.CanReturnMid;

+              else

+                openCur = specFlags.CanReturnTail;

+          }

+          else

+          {

+            if (!thereIsTail)

+              openCur = true;

+            else

+              openCur = specFlags.CanReturnFrontal;

+              

+

+            if (formatIndex >= -2)

+              openCur = true;

+          }

+          if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)

+            openCur = false;

+

+          // We open file as SFX, if there is front archive or first archive is "Self Executable"

+          if (!openCur && !pi.IsSelfExe && !thereIsTail &&

+              (!pi.IsNotArcType || pi.Offset == 0))

+          {

+            if (handlerSpec->_items.IsEmpty())

+            {

+              if (specFlags.CanReturnTail)

+                openCur = true;

+            }

+            else if (handlerSpec->_items.Size() == 1)

+            {

+              if (handlerSpec->_items[0].IsSelfExe)

+              {

+                if (mode.SpecUnknownExt.CanReturnTail)

+                  openCur = true;

+              }

+            }

+          }

+

+          if (openCur)

+          {

+            InStream = op.stream;

+            Archive = archive;

+            FormatIndex = index;

+            ArcStreamOffset = arcStreamOffset;

+            return S_OK;

+          }

+        }

+

+        /*

+        if (openOnlyFullArc)

+        {

+          ErrorInfo.ClearErrors();

+          return S_FALSE;

+        }

+        */

+

+        pi.FormatIndex = index;

+

+        // printf("\nAdd offset = %d", (int)pi.Offset);

+        handlerSpec->AddItem(pi);

+        wasOpen = true;

+        break;

+      }

+      // ---------- End of Open Loop for Current Pos ----------

+     

+      if (!wasOpen)

+        pos++;

+      needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);

     }

-  }

-  if (orderIndices.Size() >= 2)

-  {

-    int isoIndex = codecs->FindFormatForArchiveType(L"iso");

-    int udfIndex = codecs->FindFormatForArchiveType(L"udf");

-    int iIso = -1;

-    int iUdf = -1;

-    for (int i = 0; i < orderIndices.Size(); i++)

+    // ---------- End of Main Scan Loop ----------

+

+    /*

+    if (handlerSpec->_items.Size() == 1)

     {

-      if (orderIndices[i] == isoIndex) iIso = i;

-      if (orderIndices[i] == udfIndex) iUdf = i;

+      const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];

+      if (pi.Size == fileSize && pi.Offset == 0)

+      {

+        Archive = archive;

+        FormatIndex2 = pi.FormatIndex;

+        return S_OK;

+      }

     }

-    if (iUdf > iIso && iIso >= 0)

+    */

+

+    if (mode.CanReturnParser)

     {

-      orderIndices[iUdf] = isoIndex;

-      orderIndices[iIso] = udfIndex;

+      bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing

+      handlerSpec->AddUnknownItem(fileSize);

+      if (handlerSpec->_items.Size() == 0)

+        return S_FALSE;

+      if (returnParser || handlerSpec->_items.Size() != 1)

+      {

+        // return S_FALSE;

+        handlerSpec->_stream = op.stream;

+        Archive = handler;

+        ErrorInfo.ClearErrors();

+        IsParseArc = true;

+        FormatIndex = -1; // It's parser

+        Offset = 0;

+        return S_OK;

+      }

     }

   }

 

   #endif

-  }

 

-  for (int i = 0; i < orderIndices.Size(); i++)

-  {

-    if (stream)

-    {

-      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

-    }

-    CMyComPtr<IInArchive> archive;

-

-    FormatIndex = orderIndices[i];

-    RINOK(codecs->CreateInArchive(FormatIndex, archive));

-    if (!archive)

-      continue;

-

-    #ifdef EXTERNAL_CODECS

-    {

-      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

-      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

-      if (setCompressCodecsInfo)

-      {

-        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));

-      }

-    }

-    #endif

-

-    // OutputDebugStringW(codecs->Formats[FormatIndex].Name);

-

-    HRESULT result;

-    if (stream)

-      result = archive->Open(stream, &kMaxCheckStartPosition, callback);

-    else

-    {

-      CMyComPtr<IArchiveOpenSeq> openSeq;

-      archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);

-      if (!openSeq)

-        return E_NOTIMPL;

-      result = openSeq->OpenSeq(seqStream);

-    }

-

-    if (result == S_FALSE)

-      continue;

-    RINOK(result);

-

-    {

-      NCOM::CPropVariant prop;

-      archive->GetArchiveProperty(kpidError, &prop);

-      if (prop.vt != VT_EMPTY)

-        ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";

-    }

-    

-    Archive = archive;

-    const CArcInfoEx &format = codecs->Formats[FormatIndex];

-    if (format.Exts.Size() == 0)

-      DefaultName = GetDefaultName2(fileName, L"", L"");

-    else

-    {

-      int subExtIndex = format.FindExtension(extension);

-      if (subExtIndex < 0)

-        subExtIndex = 0;

-      const CArcExtInfo &extInfo = format.Exts[subExtIndex];

-      DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);

-    }

-    return S_OK;

-  }

-  return S_FALSE;

+  if (!Archive)

+    return S_FALSE;

+  return S_OK;

 }

 

-HRESULT CArc::OpenStreamOrFile(

-    CCodecs *codecs,

-    int formatIndex,

-    bool stdInMode,

-    IInStream *stream,

-    IArchiveOpenCallback *callback)

+HRESULT CArc::OpenStream(const COpenOptions &op)

+{

+  RINOK(OpenStream2(op));

+  // PrintNumber("op.formatIndex 3", op.formatIndex);

+

+  if (Archive)

+  {

+    GetRawProps.Release();

+    GetRootProps.Release();

+    Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);

+    Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);

+

+    RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree));

+    RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted));

+    RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));

+    RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));

+    RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));

+

+    const UString fileName = ExtractFileNameFromPath(Path);

+    UString extension;

+    {

+      int dotPos = fileName.ReverseFind(L'.');

+      if (dotPos >= 0)

+        extension = fileName.Ptr(dotPos + 1);

+    }

+    

+    DefaultName.Empty();

+    if (FormatIndex >= 0)

+    {

+      const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];

+      if (ai.Exts.Size() == 0)

+        DefaultName = GetDefaultName2(fileName, L"", L"");

+      else

+      {

+        int subExtIndex = ai.FindExtension(extension);

+        if (subExtIndex < 0)

+          subExtIndex = 0;

+        const CArcExtInfo &extInfo = ai.Exts[subExtIndex];

+        DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);

+      }

+    }

+  }

+

+  return S_OK;

+}

+

+#ifdef _SFX

+

+#ifdef _WIN32

+  static const wchar_t *k_ExeExt = L".exe";

+  static const unsigned k_ExeExt_Len = 4;

+#else

+  static const wchar_t *k_ExeExt = L"";

+  static const unsigned k_ExeExt_Len = 0;

+#endif

+

+#endif

+

+HRESULT CArc::OpenStreamOrFile(COpenOptions &op)

 {

   CMyComPtr<IInStream> fileStream;

   CMyComPtr<ISequentialInStream> seqStream;

-  if (stdInMode)

-    seqStream = new CStdInFileStream;

-  else if (!stream)

+  CInFileStream *fileStreamSpec = NULL;

+  if (op.stdInMode)

   {

-    CInFileStream *fileStreamSpec = new CInFileStream;

+    seqStream = new CStdInFileStream;

+    op.seqStream = seqStream;

+  }

+  else if (!op.stream)

+  {

+    fileStreamSpec = new CInFileStream;

     fileStream = fileStreamSpec;

-    if (!fileStreamSpec->Open(Path))

+    Path = filePath;

+    if (!fileStreamSpec->Open(us2fs(Path)))

+    {

       return GetLastError();

-    stream = fileStream;

+    }

+    op.stream = fileStream;

+    #ifdef _SFX

+    IgnoreSplit = true;

+    #endif

   }

 

   /*

   if (callback)

   {

     UInt64 fileSize;

-    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));

-    RINOK(callback->SetTotal(NULL, &fileSize))

+    RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));

+    RINOK(op.callback->SetTotal(NULL, &fileSize))

   }

   */

 

-  return OpenStream(codecs, formatIndex, stream, seqStream, callback);

+  HRESULT res = OpenStream(op);

+  IgnoreSplit = false;

+  

+  #ifdef _SFX

+  

+  if (res != S_FALSE

+      || !fileStreamSpec

+      || !op.callbackSpec

+      || NonOpen_ErrorInfo.IsArc_After_NonOpen())

+    return res;

+  {

+    if (filePath.Len() > k_ExeExt_Len

+        && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0)

+    {

+      const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);

+      FOR_VECTOR (i, op.codecs->Formats)

+      {

+        const CArcInfoEx &ai = op.codecs->Formats[i];

+        if (ai.IsSplit())

+          continue;

+        UString path3 = path2;

+        path3 += L".";

+        path3 += ai.GetMainExt(); // "7z"  for SFX.

+        Path = path3 + L".001";

+        bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));

+        if (!isOk)

+        {

+          Path = path3;

+          isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));

+        }

+        if (isOk)

+        {

+          if (fileStreamSpec->Open(us2fs(Path)))

+          {

+            op.stream = fileStream;

+            NonOpen_ErrorInfo.ClearErrors_Full();

+            if (OpenStream(op) == S_OK)

+              return S_OK;

+          }

+        }

+      }

+    }

+  }

+  

+  #endif

+

+  return res;

+}

+

+void CArchiveLink::KeepModeForNextOpen()

+{

+  for (int i = Arcs.Size() - 1; i >= 0; i--)

+  {

+    CMyComPtr<IArchiveKeepModeForNextOpen> keep;

+    Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);

+    if (keep)

+      keep->KeepModeForNextOpen();

+  }

 }

 

 HRESULT CArchiveLink::Close()

 {

-  for (int i = Arcs.Size() - 1;  i >= 0; i--)

+  for (int i = Arcs.Size() - 1; i >= 0; i--)

   {

-    RINOK(Arcs[i].Archive->Close());

+    RINOK(Arcs[i].Close());

   }

   IsOpen = false;

+  // ErrorsText.Empty();

   return S_OK;

 }

 

 void CArchiveLink::Release()

 {

+  // NonOpenErrorFormatIndex = -1;

+  NonOpen_ErrorInfo.ClearErrors();

+  NonOpen_ArcPath.Empty();

   while (!Arcs.IsEmpty())

     Arcs.DeleteBack();

 }

 

-HRESULT CArchiveLink::Open(

-    CCodecs *codecs,

-    const CIntVector &formatIndices,

-    bool stdInMode,

-    IInStream *stream,

-    const UString &filePath,

-    IArchiveOpenCallback *callback)

+/*

+void CArchiveLink::Set_ErrorsText()

+{

+  FOR_VECTOR(i, Arcs)

+  {

+    const CArc &arc = Arcs[i];

+    if (!arc.ErrorFlagsText.IsEmpty())

+    {

+      if (!ErrorsText.IsEmpty())

+        ErrorsText += L'\n';

+      ErrorsText += GetUnicodeString(arc.ErrorFlagsText);

+    }

+    if (!arc.ErrorMessage.IsEmpty())

+    {

+      if (!ErrorsText.IsEmpty())

+        ErrorsText += L'\n';

+      ErrorsText += arc.ErrorMessage;

+    }

+

+    if (!arc.WarningMessage.IsEmpty())

+    {

+      if (!ErrorsText.IsEmpty())

+        ErrorsText += L'\n';

+      ErrorsText += arc.WarningMessage;

+    }

+  }

+}

+*/

+

+HRESULT CArchiveLink::Open(COpenOptions &op)

 {

   Release();

-  if (formatIndices.Size() >= 32)

+  if (op.types->Size() >= 32)

     return E_NOTIMPL;

   

   HRESULT resSpec;

@@ -389,29 +2802,79 @@
   for (;;)

   {

     resSpec = S_OK;

-    int formatIndex = -1;

-    if (formatIndices.Size() >= 1)

+

+    op.openType = COpenType();

+    if (op.types->Size() >= 1)

     {

-      if (Arcs.Size() >= formatIndices.Size())

-        break;

-      formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];

+      COpenType latest;

+      if (Arcs.Size() < op.types->Size())

+        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];

+      else

+      {

+        latest = (*op.types)[0];

+        if (!latest.Recursive)

+          break;

+      }

+      op.openType = latest;

     }

     else if (Arcs.Size() >= 32)

       break;

 

+    /*

+    op.formatIndex = -1;

+    if (op.types->Size() >= 1)

+    {

+      int latest;

+      if (Arcs.Size() < op.types->Size())

+        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];

+      else

+      {

+        latest = (*op.types)[0];

+        if (latest != -2 && latest != -3)

+          break;

+      }

+      if (latest >= 0)

+        op.formatIndex = latest;

+      else if (latest == -1 || latest == -2)

+      {

+        // default

+      }

+      else if (latest == -3)

+        op.formatIndex = -2;

+      else

+        op.formatIndex = latest + 2;

+    }

+    else if (Arcs.Size() >= 32)

+      break;

+    */

+

     if (Arcs.IsEmpty())

     {

       CArc arc;

-      arc.Path = filePath;

+      arc.filePath = op.filePath;

+      arc.Path = op.filePath;

       arc.SubfileIndex = (UInt32)(Int32)-1;

-      RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));

+      HRESULT result = arc.OpenStreamOrFile(op);

+      if (result != S_OK)

+      {

+        if (result == S_FALSE)

+        {

+          NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo;

+          // NonOpenErrorFormatIndex = arc.ErrorFormatIndex;

+          NonOpen_ArcPath = arc.Path;

+        }

+        return result;

+      }

       Arcs.Add(arc);

       continue;

     }

     

+    // PrintNumber("op.formatIndex 11", op.formatIndex);

+

     const CArc &arc = Arcs.Back();

     

-    resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);

+    if (op.types->Size() > Arcs.Size())

+      resSpec = E_NOTIMPL;

     

     UInt32 mainSubfile;

     {

@@ -442,26 +2905,53 @@
     

     CArc arc2;

     RINOK(arc.GetItemPath(mainSubfile, arc2.Path));

-    

+

+    bool zerosTailIsAllowed;

+    RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));

+

     CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;

-    callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);

+    op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);

     if (setSubArchiveName)

       setSubArchiveName->SetSubArchiveName(arc2.Path);

     

     arc2.SubfileIndex = mainSubfile;

-    HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);

-    resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);

+

+    // CIntVector incl;

+    CIntVector excl;

+

+    COpenOptions op2;

+    #ifndef _SFX

+    op2.props = op.props;

+    #endif

+    op2.codecs = op.codecs;

+    // op2.types = &incl;

+    op2.openType = op.openType;

+    op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed;

+    op2.excludedFormats = &excl;

+    op2.stdInMode = false;

+    op2.stream = subStream;

+    op2.filePath = arc2.Path;

+    op2.callback = op.callback;

+    op2.callbackSpec = op.callbackSpec;

+

+

+    HRESULT result = arc2.OpenStream(op2);

+    resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);

     if (result == S_FALSE)

+    {

+      NonOpen_ErrorInfo = arc2.ErrorInfo;

+      NonOpen_ArcPath = arc2.Path;

       break;

+    }

     RINOK(result);

     RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));

     Arcs.Add(arc2);

   }

   IsOpen = !Arcs.IsEmpty();

-  return S_OK;

+  return resSpec;

 }

 

-static void SetCallback(const UString &filePath,

+static void SetCallback(const FString &filePath,

     IOpenCallbackUI *callbackUI,

     IArchiveOpenCallback *reOpenCallback,

     CMyComPtr<IArchiveOpenCallback> &callback)

@@ -471,19 +2961,12 @@
   openCallbackSpec->Callback = callbackUI;

   openCallbackSpec->ReOpenCallback = reOpenCallback;

 

-  UString fullName;

-  int fileNamePartStartIndex;

-  NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex);

-  openCallbackSpec->Init(

-      fullName.Left(fileNamePartStartIndex),

-      fullName.Mid(fileNamePartStartIndex));

+  FString dirPrefix, fileName;

+  NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName);

+  openCallbackSpec->Init(dirPrefix, fileName);

 }

 

-HRESULT CArchiveLink::Open2(CCodecs *codecs,

-    const CIntVector &formatIndices,

-    bool stdInMode,

-    IInStream *stream,

-    const UString &filePath,

+HRESULT CArchiveLink::Open2(COpenOptions &op,

     IOpenCallbackUI *callbackUI)

 {

   VolumesSize = 0;

@@ -491,46 +2974,238 @@
   CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;

   openCallbackSpec->Callback = callbackUI;

 

-  UString fullName, prefix, name;

-  if (!stream && !stdInMode)

+  FString prefix, name;

+  if (!op.stream && !op.stdInMode)

   {

-    int fileNamePartStartIndex;

-    if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex))

-      return GetLastError();

-    prefix = fullName.Left(fileNamePartStartIndex);

-    name = fullName.Mid(fileNamePartStartIndex);

+    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);

     openCallbackSpec->Init(prefix, name);

   }

   else

   {

-    openCallbackSpec->SetSubArchiveName(filePath);

+    openCallbackSpec->SetSubArchiveName(op.filePath);

   }

 

-  RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback));

-  VolumePaths.Add(prefix + name);

-  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)

-    VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]);

-  VolumesSize = openCallbackSpec->TotalSize;

+  op.callback = callback;

+  op.callbackSpec = openCallbackSpec;

+  RINOK(Open(op));

+  // VolumePaths.Add(fs2us(prefix + name));

+

+  FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)

+  {

+    if (openCallbackSpec->FileNames_WasUsed[i])

+    {

+      VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]);

+      VolumesSize += openCallbackSpec->FileSizes[i];

+    }

+  }

+  // VolumesSize = openCallbackSpec->TotalSize;

   return S_OK;

 }

 

-HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath,

-    IArchiveOpenCallback *callback)

+HRESULT CArc::ReOpen(const COpenOptions &op)

+{

+  ErrorInfo.ClearErrors();

+  ErrorInfo.ErrorFormatIndex = -1;

+

+  UInt64 fileSize = 0;

+  if (op.stream)

+  {

+    RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));

+    RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));

+  }

+  FileSize = fileSize;

+

+  CMyComPtr<IInStream> stream2;

+  Int64 globalOffset = GetGlobalOffset();

+  if (globalOffset <= 0)

+    stream2 = op.stream;

+  else

+  {

+    CTailInStream *tailStreamSpec = new CTailInStream;

+    stream2 = tailStreamSpec;

+    tailStreamSpec->Stream = op.stream;

+    tailStreamSpec->Offset = globalOffset;

+    tailStreamSpec->Init();

+    RINOK(tailStreamSpec->SeekToStart());

+  }

+

+  // There are archives with embedded STUBs (like ZIP), so we must support signature scanning

+  // But for another archives we can use 0 here. So the code can be fixed !!!

+  UInt64 maxStartPosition = kMaxCheckStartPosition;

+  HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);

+  

+  if (res == S_OK)

+  {

+    RINOK(ReadBasicProps(Archive, globalOffset, res));

+    ArcStreamOffset = globalOffset;

+    if (ArcStreamOffset != 0)

+      InStream = op.stream;

+  }

+  return res;

+}

+

+

+HRESULT CArchiveLink::ReOpen(COpenOptions &op)

 {

   if (Arcs.Size() > 1)

     return E_NOTIMPL;

 

-  if (Arcs.Size() == 0)

-    return Open2(codecs, CIntVector(), false, NULL, filePath, 0);

+  CObjectVector<COpenType> inc;

+  CIntVector excl;

+

+  op.types = &inc;

+  op.excludedFormats = &excl;

+  op.stdInMode = false;

+  op.stream = NULL;

+  if (Arcs.Size() == 0) // ???

+    return Open2(op, NULL);

 

   CMyComPtr<IArchiveOpenCallback> openCallbackNew;

-  SetCallback(filePath, NULL, callback, openCallbackNew);

+  SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew);

 

   CInFileStream *fileStreamSpec = new CInFileStream;

   CMyComPtr<IInStream> stream(fileStreamSpec);

-  if (!fileStreamSpec->Open(filePath))

+  if (!fileStreamSpec->Open(us2fs(op.filePath)))

     return GetLastError();

-  HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback);

+  op.stream = stream;

+

+  CArc &arc = Arcs[0];

+  HRESULT res = arc.ReOpen(op);

   IsOpen = (res == S_OK);

   return res;

 }

+

+#ifndef _SFX

+

+bool ParseComplexSize(const wchar_t *s, UInt64 &result)

+{

+  result = 0;

+  const wchar_t *end;

+  UInt64 number = ConvertStringToUInt64(s, &end);

+  if (end == s)

+    return false;

+  if (*end == 0)

+  {

+    result = number;

+    return true;

+  }

+  if (end[1] != 0)

+    return false;

+  unsigned numBits;

+  switch (MyCharLower_Ascii(*end))

+  {

+    case 'b': result = number; return true;

+    case 'k': numBits = 10; break;

+    case 'm': numBits = 20; break;

+    case 'g': numBits = 30; break;

+    case 't': numBits = 40; break;

+    default: return false;

+  }

+  if (number >= ((UInt64)1 << (64 - numBits)))

+    return false;

+  result = number << numBits;

+  return true;

+}

+

+static bool ParseTypeParams(const UString &s, COpenType &type)

+{

+  if (s[0] == 0)

+    return true;

+  if (s[1] == 0)

+  {

+    switch ((unsigned)(Byte)s[0])

+    {

+      case 'e': type.EachPos = true; return true;

+      case 'a': type.CanReturnArc = true; return true;

+      case 'r': type.Recursive = true; return true;

+    }

+    return false;

+  }

+  if (s[0] == 's')

+  {

+    UInt64 result;

+    if (!ParseComplexSize(s.Ptr(1), result))

+      return false;

+    type.MaxStartOffset = result;

+    type.MaxStartOffset_Defined = true;

+    return true;

+  }

+

+  return false;

+}

+

+bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)

+{

+  int pos2 = s.Find(':');

+  UString name;

+  if (pos2 < 0)

+  {

+    name = s;

+    pos2 = s.Len();

+  }

+  else

+  {

+    name = s.Left(pos2);

+    pos2++;

+  }

+

+  int index = codecs.FindFormatForArchiveType(name);

+  type.Recursive = false;

+

+  if (index < 0)

+  {

+    if (name[0] == '*')

+    {

+      if (name[1] != 0)

+        return false;

+    }

+    else if (name[0] == '#')

+    {

+      if (name[1] != 0)

+        return false;

+      type.CanReturnArc = false;

+      type.CanReturnParser = true;

+    }

+    else

+      return false;

+  }

+  

+  type.FormatIndex = index;

+ 

+  for (unsigned i = pos2; i < s.Len();)

+  {

+    int next = s.Find(':', i);

+    if (next < 0)

+      next = s.Len();

+    UString name = s.Mid(i, next - i);

+    if (name.IsEmpty())

+      return false;

+    if (!ParseTypeParams(name, type))

+      return false;

+    i = next + 1;

+  }

+  

+  return true;

+}

+

+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)

+{

+  types.Clear();

+  for (unsigned pos = 0; pos < s.Len();)

+  {

+    int pos2 = s.Find('.', pos);

+    if (pos2 < 0)

+      pos2 = s.Len();

+    UString name = s.Mid(pos, pos2 - pos);

+    if (name.IsEmpty())

+      return false;

+    COpenType type;

+    if (!ParseType(codecs, name, type))

+      return false;

+    types.Add(type);

+    pos = pos2 + 1;

+  }

+  return true;

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
old mode 100755
new mode 100644
index 18ca0ea..6f07323
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -3,49 +3,309 @@
 #ifndef __OPEN_ARCHIVE_H

 #define __OPEN_ARCHIVE_H

 

-#include "Common/MyString.h"

-

-#include "Windows/FileFind.h"

-

-#include "../../Archive/IArchive.h"

+#include "../../../Windows/PropVariant.h"

 

 #include "ArchiveOpenCallback.h"

 #include "LoadCodecs.h"

+#include "Property.h"

 

-HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);

-HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);

+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_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();

 

-struct CArc

+/*

+struct COptionalOpenProperties

 {

-  CMyComPtr<IInArchive> Archive;

-  UString Path;

-  UString DefaultName;

+  UString FormatName;

+  CObjectVector<CProperty> Props;

+};

+*/

+

+#ifdef _SFX

+#define OPEN_PROPS_DECL

+#else

+#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;

+// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props

+#endif

+

+struct COpenSpecFlags

+{

+  // bool CanReturnFull;

+  bool CanReturnFrontal;

+  bool CanReturnTail;

+  bool CanReturnMid;

+

+  bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }

+

+  COpenSpecFlags():

+    // CanReturnFull(true),

+    CanReturnFrontal(false),

+    CanReturnTail(false),

+    CanReturnMid(false)

+    {}

+};

+

+struct COpenType

+{

   int FormatIndex;

+

+  COpenSpecFlags SpecForcedType;

+  COpenSpecFlags SpecMainType;

+  COpenSpecFlags SpecWrongExt;

+  COpenSpecFlags SpecUnknownExt;

+

+  bool Recursive;

+

+  bool CanReturnArc;

+  bool CanReturnParser;

+  bool EachPos;

+

+  // bool SkipSfxStub;

+  // bool ExeAsUnknown;

+

+  bool ZerosTailIsAllowed;

+

+  bool MaxStartOffset_Defined;

+  UInt64 MaxStartOffset;

+

+  const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const

+  {

+    return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));

+  }

+

+  COpenType():

+      FormatIndex(-1),

+      Recursive(true),

+      EachPos(false),

+      CanReturnArc(true),

+      CanReturnParser(false),

+      // SkipSfxStub(true),

+      // ExeAsUnknown(true),

+      ZerosTailIsAllowed(false),

+      MaxStartOffset_Defined(false),

+      MaxStartOffset(0)

+  {

+    SpecForcedType.CanReturnFrontal = true;

+    SpecForcedType.CanReturnTail = true;

+    SpecForcedType.CanReturnMid = true;

+

+    SpecMainType.CanReturnFrontal = true;

+

+    SpecUnknownExt.CanReturnTail = true; // for sfx

+    SpecUnknownExt.CanReturnMid = true;

+    SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad

+

+    // ZerosTailIsAllowed = true;

+  }

+};

+

+struct COpenOptions

+{

+  CCodecs *codecs;

+  COpenType openType;

+  const CObjectVector<COpenType> *types;

+  const CIntVector *excludedFormats;

+

+  IInStream *stream;

+  ISequentialInStream *seqStream;

+  IArchiveOpenCallback *callback;

+  COpenCallbackImp *callbackSpec;

+  OPEN_PROPS_DECL

+  // bool openOnlySpecifiedByExtension,

+

+  bool stdInMode;

+  UString filePath;

+

+  COpenOptions():

+      codecs(NULL),

+      types(NULL),

+      excludedFormats(NULL),

+      stream(NULL),

+      seqStream(NULL),

+      callback(NULL),

+      callbackSpec(NULL),

+      stdInMode(false)

+    {}

+

+};

+

+UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);

+

+struct CArcErrorInfo

+{

+  bool ThereIsTail;

+  bool UnexpecedEnd;

+  bool IgnoreTail; // all are zeros

+  // bool NonZerosTail;

+  bool ErrorFlags_Defined;

+  UInt32 ErrorFlags;

+  UInt32 WarningFlags;

+  int ErrorFormatIndex; // - 1 means no Error.

+                        // if FormatIndex == ErrorFormatIndex, the archive is open with offset

+  UInt64 TailSize;

+

+  /* if CArc is Open OK with some format:

+        - ErrorFormatIndex shows error format index, if extension is incorrect

+        - other variables show message and warnings of archive that is open */

+  

+  UString ErrorMessage;

+  UString WarningMessage;

+

+  // call IsArc_After_NonOpen only if Open returns S_FALSE

+  bool IsArc_After_NonOpen() const

+  {

+    return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);

+  }

+

+

+  CArcErrorInfo():

+      ThereIsTail(false),

+      UnexpecedEnd(false),

+      IgnoreTail(false),

+      // NonZerosTail(false),

+      ErrorFlags_Defined(false),

+      ErrorFlags(0),

+      WarningFlags(0),

+      ErrorFormatIndex(-1),

+      TailSize(0)

+    {}

+

+  void ClearErrors();

+

+  void ClearErrors_Full()

+  {

+    ErrorFormatIndex = -1;

+    ClearErrors();

+  }

+

+  bool IsThereErrorOrWarning() const

+  {

+    return ErrorFlags != 0

+        || WarningFlags != 0

+        || NeedTailWarning()

+        || UnexpecedEnd

+        || !ErrorMessage.IsEmpty()

+        || !WarningMessage.IsEmpty();

+  }

+

+  bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }

+  bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }

+

+  bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }

+

+  UInt32 GetWarningFlags() const

+  {

+    UInt32 a = WarningFlags;

+    if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)

+      a |= kpv_ErrorFlags_DataAfterEnd;

+    return a;

+  }

+

+  UInt32 GetErrorFlags() const

+  {

+    UInt32 a = ErrorFlags;

+    if (UnexpecedEnd)

+      a |= kpv_ErrorFlags_UnexpectedEnd;

+    return a;

+  }

+};

+

+class CArc

+{

+  HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);

+  HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);

+  HRESULT OpenStream2(const COpenOptions &options);

+

+public:

+  CMyComPtr<IInArchive> Archive;

+  CMyComPtr<IInStream> InStream;

+          // we use InStream in 2 cases (ArcStreamOffset != 0):

+          // 1) if we use additional cache stream

+          // 2) we reopen sfx archive with CTailInStream

+  

+  CMyComPtr<IArchiveGetRawProps> GetRawProps;

+  CMyComPtr<IArchiveGetRootProps> GetRootProps;

+

+  CArcErrorInfo ErrorInfo; // for OK archives

+  CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)

+

+  UString Path;

+  UString filePath;

+  UString DefaultName;

+  int FormatIndex; // - 1 means Parser.

   int SubfileIndex;

   FILETIME MTime;

   bool MTimeDefined;

-  UString ErrorMessage;

+  

+  Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler

+  UInt64 PhySize;

+  // UInt64 OkPhySize;

+  bool PhySizeDefined;

+  // bool OkPhySize_Defined;

+  UInt64 FileSize;

+  UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file

+  // bool offsetDefined;

 

-  CArc(): MTimeDefined(false) {}

+  UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler

+  Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive

+

+  // AString ErrorFlagsText;

+

+  bool IsParseArc;

+

+  bool IsTree;

+  

+  bool Ask_Deleted;

+  bool Ask_AltStream;

+  bool Ask_Aux;

+  bool Ask_INode;

+

+  bool IgnoreSplit; // don't try split handler

+

+  // void Set_ErrorFlagsText();

+

+  CArc():

+    MTimeDefined(false),

+    IsTree(false),

+    Ask_Deleted(false),

+    Ask_AltStream(false),

+    Ask_Aux(false),

+    Ask_INode(false),

+    IgnoreSplit(false)

+    {}

+

+  HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);

+

+  // ~CArc();

+

+  HRESULT Close()

+  {

+    InStream.Release();

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

+  

+  // GetItemPath2 adds [DELETED] dir prefix for deleted items.

+  HRESULT GetItemPath2(UInt32 index, UString &result) const;

+  

+  HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;

   HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;

   HRESULT IsItemAnti(UInt32 index, bool &result) const

-    { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); }

+    { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }

 

-  HRESULT OpenStream(

-    CCodecs *codecs,

-    int formatIndex,

-    IInStream *stream,

-    ISequentialInStream *seqStream,

-    IArchiveOpenCallback *callback);

 

-  HRESULT OpenStreamOrFile(

-    CCodecs *codecs,

-    int formatIndex,

-    bool stdInMode,

-    IInStream *stream,

-    IArchiveOpenCallback *callback);

+  HRESULT OpenStream(const COpenOptions &options);

+  HRESULT OpenStreamOrFile(COpenOptions &options);

+

+  HRESULT ReOpen(const COpenOptions &options);

+  

+  HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);

 };

 

 struct CArchiveLink

@@ -55,33 +315,32 @@
   UInt64 VolumesSize;

   bool IsOpen;

 

+  // int NonOpenErrorFormatIndex; // - 1 means no Error.

+  UString NonOpen_ArcPath;

+

+  CArcErrorInfo NonOpen_ErrorInfo;

+

+  // UString ErrorsText;

+  // void Set_ErrorsText();

+

   CArchiveLink(): VolumesSize(0), IsOpen(false) {}

+  void KeepModeForNextOpen();

   HRESULT Close();

   void Release();

   ~CArchiveLink() { Release(); }

 

+  const CArc *GetArc() const { return &Arcs.Back(); }

   IInArchive *GetArchive() const { return Arcs.Back().Archive; }

+  IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }

+  IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }

 

-  HRESULT Open(

-    CCodecs *codecs,

-    const CIntVector &formatIndices,

-    bool stdInMode,

-    IInStream *stream,

-    const UString &filePath,

-    IArchiveOpenCallback *callback);

+  HRESULT Open(COpenOptions &options);

 

-  HRESULT Open2(

-    CCodecs *codecs,

-    const CIntVector &formatIndices,

-    bool stdInMode,

-    IInStream *stream,

-    const UString &filePath,

-    IOpenCallbackUI *callbackUI);

+  HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);

 

-  HRESULT ReOpen(

-    CCodecs *codecs,

-    const UString &filePath,

-    IArchiveOpenCallback *callback);

+  HRESULT ReOpen(COpenOptions &options);

 };

 

+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);

+

 #endif

diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
old mode 100755
new mode 100644
index 4a9e294..a9278cd
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -2,33 +2,29 @@
 

 #include "StdAfx.h"

 

-#include "Common/IntToString.h"

+#include "../../../../C/CpuArch.h"

 

-#include "Windows/FileFind.h"

-#include "Windows/PropVariantConversions.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileIO.h"

+#include "../../../Windows/PropVariantConv.h"

 

 #include "../../PropID.h"

 

 #include "PropIDUtils.h"

 

+#define Get16(x) GetUi16(x)

+#define Get32(x) GetUi32(x)

+

 using namespace NWindows;

 

-void ConvertUInt32ToHex(UInt32 value, wchar_t *s)

-{

-  for (int i = 0; i < 8; i++)

-  {

-    int t = value & 0xF;

-    value >>= 4;

-    s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));

-  }

-  s[8] = L'\0';

-}

-

-static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";

+static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";

 /*

 0 READONLY

 1 HIDDEN

-3 SYSTEM

+2 SYSTEM

 

 4 DIRECTORY

 5 ARCHIVE

@@ -45,46 +41,45 @@
 16 VIRTUAL

 */

 

-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 : L'-';

-

-UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)

+void ConvertWinAttribToString(char *s, UInt32 wa)

 {

-  switch(propID)

+  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 : '-';

+

+void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()

+{

+  *dest = 0;

+  if (prop.vt == VT_FILETIME)

   {

-    case kpidCTime:

-    case kpidATime:

-    case kpidMTime:

-    {

-      if (prop.vt != VT_FILETIME)

-        break;

-      FILETIME localFileTime;

-      if ((prop.filetime.dwHighDateTime == 0 &&

-          prop.filetime.dwLowDateTime == 0) ||

-          !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))

-        return UString();

-      return ConvertFileTimeToString(localFileTime, true, full);

-    }

+    FILETIME localFileTime;

+    if ((prop.filetime.dwHighDateTime == 0 &&

+        prop.filetime.dwLowDateTime == 0) ||

+        !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))

+      return;

+    ConvertFileTimeToString(localFileTime, dest, true, full);

+    return;

+  }

+  switch (propID)

+  {

     case kpidCRC:

     {

       if (prop.vt != VT_UI4)

         break;

-      wchar_t temp[12];

-      ConvertUInt32ToHex(prop.ulVal, temp);

-      return temp;

+      ConvertUInt32ToHex8Digits(prop.ulVal, dest);

+      return;

     }

     case kpidAttrib:

     {

       if (prop.vt != VT_UI4)

         break;

-      UInt32 a = prop.ulVal;

-      wchar_t sz[32];

-      int pos = 0;

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

-        if (a & (1 << i) && i != 7)

-          sz[pos++] = g_WinAttrib[i];

-      sz[pos] = '\0';

-      return sz;

+      ConvertWinAttribToString(dest, prop.ulVal);

+      return;

     }

     case kpidPosixAttrib:

     {

@@ -92,29 +87,467 @@
         break;

       UString res;

       UInt32 a = prop.ulVal;

-      wchar_t temp[16];

 

-      temp[0] = kPosixTypes[(a >> 12) & 0xF];

+      dest[0] = kPosixTypes[(a >> 12) & 0xF];

       for (int i = 6; i >= 0; i -= 3)

       {

-        temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r');

-        temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w');

-        temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x');

+        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) temp[3] = ((a & (1 << 6)) ? 's' : 'S');

-      if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S');

-      if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T');

-      temp[10] = 0;

-      res = temp;

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

       {

-        ConvertUInt32ToHex(a, temp);

-        res = UString(temp) + L' ' + res;

+        dest[10] = ' ';

+        ConvertUInt32ToHex8Digits(a, dest + 11);

       }

-      return res;

+      return;

+    }

+    case kpidINode:

+    {

+      if (prop.vt != VT_UI8)

+        break;

+      ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);

+      dest += strlen(dest);

+      *dest++ = '-';

+      UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);

+      ConvertUInt64ToString(low, dest);

+      return;

+    }

+    case kpidVa:

+    {

+      UInt64 v = 0;

+      if (ConvertPropVariantToUInt64(prop, v))

+      {

+        dest[0] = '0';

+        dest[1] = 'x';

+        ConvertUInt64ToHex(prop.ulVal, dest + 2);

+        return;

+      }

+      break;

     }

   }

-  return ConvertPropVariantToString(prop);

+  ConvertPropVariantToShortString(prop, dest);

 }

+

+void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full)

+{

+  if (prop.vt == VT_BSTR)

+  {

+    dest = 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);

+}

+

+static inline char GetHex(Byte value)

+{

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+#ifndef _SFX

+

+static inline void AddHexToString(AString &res, Byte value)

+{

+  res += GetHex((Byte)(value >> 4));

+  res += GetHex((Byte)(value & 0xF));

+  res += ' ';

+}

+

+/*

+static AString Data_To_Hex(const Byte *data, size_t size)

+{

+  AString s;

+  for (size_t i = 0; i < size; i++)

+    AddHexToString(s, data[i]);

+  return s;

+}

+*/

+

+static const char *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"

+};

+

+struct CSecID2Name

+{

+  UInt32 n;

+  const char *sz;

+};

+

+const CSecID2Name sid_32_Names[] =

+{

+  { 544, "Administrators" },

+  { 545, "Users" },

+  { 546, "Guests" },

+  { 547, "PowerUsers" },

+  { 548, "AccountOperators" },

+  { 549, "ServerOperators" },

+  { 550, "PrintOperators" },

+  { 551, "BackupOperators" },

+  { 552, "Replicators" },

+  { 553, "Backup Operators" },

+  { 554, "PreWindows2000CompatibleAccess" },

+  { 555, "RemoteDesktopUsers" },

+  { 556, "NetworkConfigurationOperators" },

+  { 557, "IncomingForestTrustBuilders" },

+  { 558, "PerformanceMonitorUsers" },

+  { 559, "PerformanceLogUsers" },

+  { 560, "WindowsAuthorizationAccessGroup" },

+  { 561, "TerminalServerLicenseServers" },

+  { 562, "DistributedCOMUsers" },

+  { 569, "CryptographicOperators" },

+  { 573, "EventLogReaders" },

+  { 574, "CertificateServiceDCOMAccess" }

+};

+

+static const CSecID2Name sid_21_Names[] =

+{

+  { 500, "Administrator" },

+  { 501, "Guest" },

+  { 502, "KRBTGT" },

+  { 512, "DomainAdmins" },

+  { 513, "DomainUsers" },

+  { 515, "DomainComputers" },

+  { 516, "DomainControllers" },

+  { 517, "CertPublishers" },

+  { 518, "SchemaAdmins" },

+  { 519, "EnterpriseAdmins" },

+  { 520, "GroupPolicyCreatorOwners" },

+  { 553, "RASandIASServers" },

+  { 553, "RASandIASServers" },

+  { 571, "AllowedRODCPasswordReplicationGroup" },

+  { 572, "DeniedRODCPasswordReplicationGroup" }

+};

+

+struct CServicesToName

+{

+  UInt32 n[5];

+  const char *sz;

+};

+

+static const CServicesToName services_to_name[] =

+{

+  { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }

+};

+

+static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)

+{

+  sidSize = 0;

+  if (lim < 8)

+  {

+    s += "ERROR";

+    return;

+  }

+  UInt32 rev = p[0];

+  if (rev != 1)

+  {

+    s += "UNSUPPORTED";

+    return;

+  }

+  UInt32 num = p[1];

+  if (8 + num * 4 > lim)

+  {

+    s += "ERROR";

+    return;

+  }

+  sidSize = 8 + num * 4;

+  UInt32 authority = GetBe32(p + 4);

+

+  if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)

+  {

+    UInt32 v0 = Get32(p + 8);

+    if (v0 < ARRAY_SIZE(sidNames))

+    {

+      s += sidNames[v0];

+      return;

+    }

+    if (v0 == 32 && num == 2)

+    {

+      UInt32 v1 = Get32(p + 12);

+      for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++)

+        if (sid_32_Names[i].n == v1)

+        {

+          s += sid_32_Names[i].sz;

+          return;

+        }

+    }

+    if (v0 == 21 && num == 5)

+    {

+      UInt32 v4 = Get32(p + 8 + 4 * 4);

+      for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++)

+        if (sid_21_Names[i].n == v4)

+        {

+          s += sid_21_Names[i].sz;

+          return;

+        }

+    }

+    if (v0 == 80 && num == 6)

+    {

+      for (int i = 0; i < ARRAY_SIZE(services_to_name); i++)

+      {

+        const CServicesToName &sn = services_to_name[i];

+        int j;

+        for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);

+        if (j == 5)

+        {

+          s += sn.sz;

+          return;

+        }

+      }

+    }

+  }

+  

+  char sz[16];

+  s += "S-1-";

+  if (p[2] == 0 && p[3] == 0)

+  {

+    ConvertUInt32ToString(authority, sz);

+    s += sz;

+  }

+  else

+  {

+    s += "0x";

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

+      AddHexToString(s, p[i]);

+  }

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

+  {

+    s += '-';

+    ConvertUInt32ToString(Get32(p + 8 + i * 4), sz);

+    s += sz;

+  }

+}

+

+static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)

+{

+  if (pos > size)

+  {

+    s += "ERROR";

+    return;

+  }

+  UInt32 sidSize = 0;

+  ParseSid(s, p + pos, size - pos, sidSize);

+}

+

+static void AddUInt32ToString(AString &s, UInt32 val)

+{

+  char sz[16];

+  ConvertUInt32ToString(val, sz);

+  s += sz;

+}

+

+static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)

+{

+  UInt32 control = Get16(p + 2);

+  if ((flags & control) == 0)

+    return;

+  UInt32 pos = Get32(p + offset);

+  s += ' ';

+  s += strName;

+  if (pos >= size)

+    return;

+  p += pos;

+  size -= pos;

+  if (size < 8)

+    return;

+  if (Get16(p) != 2) // revision

+    return;

+  // UInt32 aclSize = Get16(p + 2);

+  UInt32 num = Get32(p + 4);

+  AddUInt32ToString(s, num);

+  /*

+  if (num >= (1 << 16))

+    return;

+  if (aclSize > size)

+    return;

+  size = aclSize;

+  size -= 8;

+  p += 8;

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

+  {

+    if (size <= 8)

+      return;

+    // Byte type = p[0];

+    // Byte flags = p[1];

+    // UInt32 aceSize = Get16(p + 2);

+    // UInt32 mask = Get32(p + 4);

+    p += 8;

+    size -= 8;

+

+    UInt32 sidSize = 0;

+    s += ' ';

+    s += ParseSid(p, size, sidSize);

+    if (sidSize == 0)

+      return;

+    p += sidSize;

+    size -= sidSize;

+  }

+  if (size != 0)

+    s += " ERROR";

+  */

+}

+

+#define MY_SE_OWNER_DEFAULTED       (0x0001)

+#define MY_SE_GROUP_DEFAULTED       (0x0002)

+#define MY_SE_DACL_PRESENT          (0x0004)

+#define MY_SE_DACL_DEFAULTED        (0x0008)

+#define MY_SE_SACL_PRESENT          (0x0010)

+#define MY_SE_SACL_DEFAULTED        (0x0020)

+#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)

+#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)

+#define MY_SE_DACL_AUTO_INHERITED   (0x0400)

+#define MY_SE_SACL_AUTO_INHERITED   (0x0800)

+#define MY_SE_DACL_PROTECTED        (0x1000)

+#define MY_SE_SACL_PROTECTED        (0x2000)

+#define MY_SE_RM_CONTROL_VALID      (0x4000)

+#define MY_SE_SELF_RELATIVE         (0x8000)

+

+void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)

+{

+  s.Empty();

+  if (size < 20 || size > (1 << 18))

+  {

+    s += "ERROR";

+    return;

+  }

+  if (Get16(data) != 1) // revision

+  {

+    s += "UNSUPPORTED";

+    return;

+  }

+  ParseOwner(s, data, size, Get32(data + 4));

+  s += ' ';

+  ParseOwner(s, data, size, Get32(data + 8));

+  ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);

+  ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);

+  s += ' ';

+  AddUInt32ToString(s, size);

+  // s += '\n';

+  // s += Data_To_Hex(data, size);

+}

+

+#ifdef _WIN32

+

+static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)

+{

+  if (pos >= size)

+    return false;

+  size -= pos;

+  if (size < 8)

+    return false;

+  UInt32 rev = data[pos];

+  if (rev != 1)

+    return false;

+  UInt32 num = data[pos + 1];

+  return (8 + num * 4 <= size);

+}

+

+static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)

+{

+  UInt32 control = Get16(p + 2);

+  if ((flags & control) == 0)

+    return true;

+  UInt32 pos = Get32(p + offset);

+  if (pos >= size)

+    return false;

+  p += pos;

+  size -= pos;

+  if (size < 8)

+    return false;

+  UInt32 aclSize = Get16(p + 2);

+  return (aclSize <= size);

+}

+

+bool CheckNtSecure(const Byte *data, UInt32 size)

+{

+  if (size < 20)

+    return false;

+  if (Get16(data) != 1) // revision

+    return true; // windows function can handle such error, so we allow it

+  if (size > (1 << 18))

+    return false;

+  if (!CheckSid(data, size, Get32(data + 4))) return false;

+  if (!CheckSid(data, size, Get32(data + 8))) return false;

+  if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;

+  if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;

+  return true;

+}

+

+#endif

+

+bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)

+{

+  s.Empty();

+  NFile::CReparseAttr attr;

+  if (attr.Parse(data, size))

+  {

+    if (!attr.IsSymLink())

+      s += L"Junction: ";

+    s += attr.GetPath();

+    if (!attr.IsOkNamePair())

+    {

+      s += L" : ";

+      s += attr.PrintName;

+    }

+    return true;

+  }

+

+  if (size < 8)

+    return false;

+  UInt32 tag = Get32(data);

+  UInt32 len = Get16(data + 4);

+  if (len + 8 > size)

+    return false;

+  if (Get16(data + 6) != 0) // padding

+    return false;

+

+  char hex[16];

+  ConvertUInt32ToHex8Digits(tag, hex);

+  s.AddAsciiStr(hex);

+  s += L' ';

+

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

+  }

+  return true;

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
old mode 100755
new mode 100644
index 05c09e7..fcfbc8c
--- a/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -3,10 +3,15 @@
 #ifndef __PROPID_UTILS_H

 #define __PROPID_UTILS_H

 

-#include "Common/MyString.h"

-#include "Common/Types.h"

+#include "../../../Common/MyString.h"

 

-void ConvertUInt32ToHex(UInt32 value, wchar_t *s);

-UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true);

+// provide at least 64 bytes for buffer including zero-end

+void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw();

+void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true);

+

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

 

 #endif

diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h
old mode 100755
new mode 100644
index 5253d52..31234ad
--- a/CPP/7zip/UI/Common/Property.h
+++ b/CPP/7zip/UI/Common/Property.h
@@ -1,9 +1,9 @@
 // Property.h

 

-#ifndef __PROPERTY_H

-#define __PROPERTY_H

+#ifndef __7Z_PROPERTY_H

+#define __7Z_PROPERTY_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

 

 struct CProperty

 {

diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
old mode 100755
new mode 100644
index b3347ce..3cd4d57
--- a/CPP/7zip/UI/Common/SetProperties.cpp
+++ b/CPP/7zip/UI/Common/SetProperties.cpp
@@ -2,25 +2,26 @@
 

 #include "StdAfx.h"

 

-#include "SetProperties.h"

+#include "../../../Common/MyCom.h"

+#include "../../../Common/MyString.h"

+#include "../../../Common/StringToInt.h"

 

-#include "Windows/PropVariant.h"

-#include "Common/MyString.h"

-#include "Common/StringToInt.h"

-#include "Common/MyCom.h"

+#include "../../../Windows/PropVariant.h"

 

 #include "../../Archive/IArchive.h"

 

+#include "SetProperties.h"

+

 using namespace NWindows;

 using namespace NCOM;

 

 static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)

 {

-  const wchar_t *endPtr;

-  UInt64 result = ConvertStringToUInt64(s, &endPtr);

-  if (endPtr - (const wchar_t *)s != s.Length())

+  const wchar_t *end;

+  UInt64 result = ConvertStringToUInt64(s, &end);

+  if (*end != 0 || s.IsEmpty())

     prop = s;

-  else if (result <= 0xFFFFFFFF)

+  else if (result <= (UInt32)0xFFFFFFFF)

     prop = (UInt32)result;

   else

     prop = result;

@@ -39,8 +40,8 @@
   CPropVariant *values = new CPropVariant[properties.Size()];

   try

   {

-    int i;

-    for(i = 0; i < properties.Size(); i++)

+    unsigned i;

+    for (i = 0; i < properties.Size(); i++)

     {

       const CProperty &property = properties[i];

       NCOM::CPropVariant propVariant;

@@ -49,13 +50,13 @@
       {

         if (!name.IsEmpty())

         {

-          wchar_t c = name[name.Length() - 1];

+          wchar_t c = name.Back();

           if (c == L'-')

             propVariant = false;

           else if (c == L'+')

             propVariant = true;

           if (propVariant.vt != VT_EMPTY)

-            name = name.Left(name.Length() - 1);

+            name.DeleteBack();

         }

       }

       else

@@ -64,7 +65,7 @@
       values[i] = propVariant;

     }

     CRecordVector<const wchar_t *> names;

-    for(i = 0; i < realNames.Size(); i++)

+    for (i = 0; i < realNames.Size(); i++)

       names.Add((const wchar_t *)realNames[i]);

     

     RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));

diff --git a/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
old mode 100755
new mode 100644
index 039adfa..4510ffd
--- a/CPP/7zip/UI/Common/SortUtils.cpp
+++ b/CPP/7zip/UI/Common/SortUtils.cpp
@@ -2,21 +2,22 @@
 

 #include "StdAfx.h"

 

-#include "SortUtils.h"

-#include "Common/Wildcard.h"

+#include "../../../Common/Wildcard.h"

 

-static int CompareStrings(const int *p1, const int *p2, void *param)

+#include "SortUtils.h"

+

+static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param)

 {

   const UStringVector &strings = *(const UStringVector *)param;

   return CompareFileNames(strings[*p1], strings[*p2]);

 }

 

-void SortFileNames(const UStringVector &strings, CIntVector &indices)

+void SortFileNames(const UStringVector &strings, CUIntVector &indices)

 {

-  indices.Clear();

-  int numItems = strings.Size();

-  indices.Reserve(numItems);

-  for(int i = 0; i < numItems; i++)

-    indices.Add(i);

+  unsigned numItems = strings.Size();

+  indices.ClearAndSetSize(numItems);

+  unsigned *vals = &indices[0];

+  for (unsigned i = 0; i < numItems; i++)

+    vals[i] = i;

   indices.Sort(CompareStrings, (void *)&strings);

 }

diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h
old mode 100755
new mode 100644
index 4835f11..82d5e4c
--- a/CPP/7zip/UI/Common/SortUtils.h
+++ b/CPP/7zip/UI/Common/SortUtils.h
@@ -1,10 +1,10 @@
 // SortUtils.h

 

-#ifndef __SORTUTLS_H

-#define __SORTUTLS_H

+#ifndef __SORT_UTLS_H

+#define __SORT_UTLS_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

 

-void SortFileNames(const UStringVector &strings, CIntVector &indices);

+void SortFileNames(const UStringVector &strings, CUIntVector &indices);

 

 #endif

diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h
old mode 100755
new mode 100644
index ab2617e..59d9ac1
--- a/CPP/7zip/UI/Common/StdAfx.h
+++ b/CPP/7zip/UI/Common/StdAfx.h
@@ -1,9 +1,8 @@
-// stdafx.h

+// StdAfx.h

 

 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp
old mode 100755
new mode 100644
index 48fb4e7..cfbee1a
--- a/CPP/7zip/UI/Common/TempFiles.cpp
+++ b/CPP/7zip/UI/Common/TempFiles.cpp
@@ -2,19 +2,18 @@
 

 #include "StdAfx.h"

 

-#include "TempFiles.h"

+#include "../../../Windows/FileDir.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/FileIO.h"

+#include "TempFiles.h"

 

 using namespace NWindows;

 using namespace NFile;

 

 void CTempFiles::Clear()

 {

-  while(!Paths.IsEmpty())

+  while (!Paths.IsEmpty())

   {

-    NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back());

+    NDir::DeleteFileAlways(Paths.Back());

     Paths.DeleteBack();

   }

 }

diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h
old mode 100755
new mode 100644
index 9e8e131..f62192d
--- a/CPP/7zip/UI/Common/TempFiles.h
+++ b/CPP/7zip/UI/Common/TempFiles.h
@@ -1,15 +1,15 @@
 // TempFiles.h

 

-#ifndef __TEMPFILES_H

-#define __TEMPFILES_H

+#ifndef __TEMP_FILES_H

+#define __TEMP_FILES_H

 

-#include "Common/MyString.h"

+#include "../../../Common/MyString.h"

 

 class CTempFiles

 {

   void Clear();

 public:

-  UStringVector Paths;

+  FStringVector Paths;

   ~CTempFiles() { Clear(); }

 };

 

diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
old mode 100755
new mode 100644
index 2e1cca0..ee13311
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -4,21 +4,19 @@
 

 #include "Update.h"

 

-#include "Common/IntToString.h"

-#include "Common/StringConvert.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

 

-#ifdef _WIN32

-#include "Windows/DLL.h"

-#endif

-

-#include "Windows/FileDir.h"

-#include "Windows/FileFind.h"

-#include "Windows/FileName.h"

-#include "Windows/PropVariant.h"

-#include "Windows/PropVariantConversions.h"

-#include "Windows/Time.h"

+#include "../../../Windows/DLL.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/PropVariant.h"

+#include "../../../Windows/PropVariantConv.h"

+#include "../../../Windows/TimeUtils.h"

 

 #include "../../Common/FileStreams.h"

+#include "../../Common/LimitedStreams.h"

 

 #include "../../Compress/CopyCoder.h"

 

@@ -38,9 +36,33 @@
 using namespace NWindows;

 using namespace NCOM;

 using namespace NFile;

+using namespace NDir;

 using namespace NName;

 

-static const wchar_t *kTempFolderPrefix = L"7zE";

+static CFSTR kTempFolderPrefix = FTEXT("7zE");

+

+

+static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)

+{

+  NFind::CFileInfo fileInfo;

+  FString pathPrefix = path + FCHAR_PATH_SEPARATOR;

+  {

+    NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);

+    while (enumerator.Next(fileInfo))

+    {

+      if (fileInfo.IsDir())

+        if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))

+          return false;

+    }

+  }

+  /*

+  // we don't need clear read-only for folders

+  if (!MySetFileAttributes(path, 0))

+    return false;

+  */

+  return RemoveDir(path);

+}

+

 

 using namespace NUpdateArchive;

 

@@ -48,24 +70,24 @@
   public IOutStream,

   public CMyUnknownImp

 {

-  int _streamIndex; // required stream

+  unsigned _streamIndex; // required stream

   UInt64 _offsetPos; // offset from start of _streamIndex index

   UInt64 _absPos;

   UInt64 _length;

 

-  struct CSubStreamInfo

+  struct CAltStreamInfo

   {

     COutFileStream *StreamSpec;

     CMyComPtr<IOutStream> Stream;

-    UString Name;

+    FString Name;

     UInt64 Pos;

     UInt64 RealSize;

   };

-  CObjectVector<CSubStreamInfo> Streams;

+  CObjectVector<CAltStreamInfo> Streams;

 public:

   // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;

   CRecordVector<UInt64> Sizes;

-  UString Prefix;

+  FString Prefix;

   CTempFiles *TempFiles;

 

   void Init()

@@ -76,6 +98,7 @@
     _length = 0;

   }

 

+  bool SetMTime(const FILETIME *mTime);

   HRESULT Close();

 

   MY_UNKNOWN_IMP1(IOutStream)

@@ -90,12 +113,12 @@
 HRESULT COutMultiVolStream::Close()

 {

   HRESULT res = S_OK;

-  for (int i = 0; i < Streams.Size(); i++)

+  FOR_VECTOR (i, Streams)

   {

-    CSubStreamInfo &s = Streams[i];

-    if (s.StreamSpec)

+    COutFileStream *s = Streams[i].StreamSpec;

+    if (s)

     {

-      HRESULT res2 = s.StreamSpec->Close();

+      HRESULT res2 = s->Close();

       if (res2 != S_OK)

         res = res2;

     }

@@ -103,40 +126,53 @@
   return res;

 }

 

+bool COutMultiVolStream::SetMTime(const FILETIME *mTime)

+{

+  bool res = true;

+  FOR_VECTOR (i, Streams)

+  {

+    COutFileStream *s = Streams[i].StreamSpec;

+    if (s)

+      if (!s->SetMTime(mTime))

+        res = false;

+  }

+  return res;

+}

+

 STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

 {

   if (processedSize != NULL)

     *processedSize = 0;

-  while(size > 0)

+  while (size > 0)

   {

     if (_streamIndex >= Streams.Size())

     {

-      CSubStreamInfo subStream;

+      CAltStreamInfo altStream;

 

-      wchar_t temp[16];

+      FChar temp[16];

       ConvertUInt32ToString(_streamIndex + 1, temp);

-      UString res = temp;

-      while (res.Length() < 3)

-        res = UString(L'0') + res;

-      UString name = Prefix + res;

-      subStream.StreamSpec = new COutFileStream;

-      subStream.Stream = subStream.StreamSpec;

-      if (!subStream.StreamSpec->Create(name, false))

+      FString res = temp;

+      while (res.Len() < 3)

+        res = FString(FTEXT('0')) + res;

+      FString name = Prefix + res;

+      altStream.StreamSpec = new COutFileStream;

+      altStream.Stream = altStream.StreamSpec;

+      if (!altStream.StreamSpec->Create(name, false))

         return ::GetLastError();

       {

         // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);

         TempFiles->Paths.Add(name);

       }

 

-      subStream.Pos = 0;

-      subStream.RealSize = 0;

-      subStream.Name = name;

-      Streams.Add(subStream);

+      altStream.Pos = 0;

+      altStream.RealSize = 0;

+      altStream.Name = name;

+      Streams.Add(altStream);

       continue;

     }

-    CSubStreamInfo &subStream = Streams[_streamIndex];

+    CAltStreamInfo &altStream = Streams[_streamIndex];

 

-    int index = _streamIndex;

+    unsigned index = _streamIndex;

     if (index >= Sizes.Size())

       index = Sizes.Size() - 1;

     UInt64 volSize = Sizes[index];

@@ -147,29 +183,29 @@
       _streamIndex++;

       continue;

     }

-    if (_offsetPos != subStream.Pos)

+    if (_offsetPos != altStream.Pos)

     {

       // CMyComPtr<IOutStream> outStream;

-      // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));

-      RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));

-      subStream.Pos = _offsetPos;

+      // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream));

+      RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));

+      altStream.Pos = _offsetPos;

     }

 

-    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);

+    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos);

     UInt32 realProcessed;

-    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));

+    RINOK(altStream.Stream->Write(data, curSize, &realProcessed));

     data = (void *)((Byte *)data + realProcessed);

     size -= realProcessed;

-    subStream.Pos += realProcessed;

+    altStream.Pos += realProcessed;

     _offsetPos += realProcessed;

     _absPos += realProcessed;

     if (_absPos > _length)

       _length = _absPos;

-    if (_offsetPos > subStream.RealSize)

-      subStream.RealSize = _offsetPos;

+    if (_offsetPos > altStream.RealSize)

+      altStream.RealSize = _offsetPos;

     if (processedSize != NULL)

       *processedSize += realProcessed;

-    if (subStream.Pos == volSize)

+    if (altStream.Pos == volSize)

     {

       _streamIndex++;

       _offsetPos = 0;

@@ -185,17 +221,11 @@
 {

   if (seekOrigin >= 3)

     return STG_E_INVALIDFUNCTION;

-  switch(seekOrigin)

+  switch (seekOrigin)

   {

-    case STREAM_SEEK_SET:

-      _absPos = offset;

-      break;

-    case STREAM_SEEK_CUR:

-      _absPos += offset;

-      break;

-    case STREAM_SEEK_END:

-      _absPos = _length + offset;

-      break;

+    case STREAM_SEEK_SET: _absPos = offset; break;

+    case STREAM_SEEK_CUR: _absPos += offset; break;

+    case STREAM_SEEK_END: _absPos = _length + offset; break;

   }

   _offsetPos = _absPos;

   if (newPosition != NULL)

@@ -208,24 +238,24 @@
 {

   if (newSize < 0)

     return E_INVALIDARG;

-  int i = 0;

+  unsigned i = 0;

   while (i < Streams.Size())

   {

-    CSubStreamInfo &subStream = Streams[i++];

-    if ((UInt64)newSize < subStream.RealSize)

+    CAltStreamInfo &altStream = Streams[i++];

+    if ((UInt64)newSize < altStream.RealSize)

     {

-      RINOK(subStream.Stream->SetSize(newSize));

-      subStream.RealSize = newSize;

+      RINOK(altStream.Stream->SetSize(newSize));

+      altStream.RealSize = newSize;

       break;

     }

-    newSize -= subStream.RealSize;

+    newSize -= altStream.RealSize;

   }

   while (i < Streams.Size())

   {

     {

-      CSubStreamInfo &subStream = Streams.Back();

-      subStream.Stream.Release();

-      NDirectory::DeleteFileAlways(subStream.Name);

+      CAltStreamInfo &altStream = Streams.Back();

+      altStream.Stream.Release();

+      DeleteFileAlways(altStream.Name);

     }

     Streams.DeleteBack();

   }

@@ -235,7 +265,67 @@
   return S_OK;

 }

 

-static const wchar_t *kDefaultArchiveType = L"7z";

+void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)

+{

+  OriginalPath = path;

+  

+  SplitPathToParts_2(path, Prefix, Name);

+  

+  if (mode == k_ArcNameMode_Add)

+    return;

+  if (mode == k_ArcNameMode_Exact)

+  {

+    BaseExtension.Empty();

+    return;

+  }

+  

+  int dotPos = Name.ReverseFind(L'.');

+  if (dotPos < 0)

+    return;

+  if ((unsigned)dotPos == Name.Len() - 1)

+  {

+    Name.DeleteBack();

+    BaseExtension.Empty();

+    return;

+  }

+  const UString ext = Name.Ptr(dotPos + 1);

+  if (BaseExtension.IsEqualToNoCase(ext))

+  {

+    BaseExtension = ext;

+    Name.DeleteFrom(dotPos);

+  }

+  else

+    BaseExtension.Empty();

+}

+

+UString CArchivePath::GetFinalPath() const

+{

+  UString path = GetPathWithoutExt();

+  if (!BaseExtension.IsEmpty())

+    path += UString(L'.') + BaseExtension;

+  return path;

+}

+

+UString CArchivePath::GetFinalVolPath() const

+{

+  UString path = GetPathWithoutExt();

+  if (!BaseExtension.IsEmpty())

+    path += UString(L'.') + VolExtension;

+  return path;

+}

+

+FString CArchivePath::GetTempPath() const

+{

+  FString path = TempPrefix + us2fs(Name);

+  if (!BaseExtension.IsEmpty())

+    path += FString(FTEXT('.')) + us2fs(BaseExtension);

+  path += FTEXT(".tmp");

+  path += TempPostfix;

+  return path;

+}

+

+static const wchar_t *kDefaultArcType = L"7z";

+static const wchar_t *kDefaultArcExt = L"7z";

 static const wchar_t *kSFXExtension =

   #ifdef _WIN32

     L"exe";

@@ -243,40 +333,58 @@
     L"";

   #endif

 

-bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath)

+bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,

+    const CObjectVector<COpenType> &types, const UString &arcPath)

 {

-  if (formatIndices.Size() > 1)

+  if (types.Size() > 1)

     return false;

-  int arcTypeIndex = -1;

-  if (formatIndices.Size() != 0)

-    arcTypeIndex = formatIndices[0];

-  if (arcTypeIndex >= 0)

-    MethodMode.FormatIndex = arcTypeIndex;

+  // int arcTypeIndex = -1;

+  if (types.Size() != 0)

+  {

+    MethodMode.Type = types[0];

+    MethodMode.Type_Defined = true;

+  }

+  if (MethodMode.Type.FormatIndex < 0)

+  {

+    // MethodMode.Type = -1;

+    MethodMode.Type = COpenType();

+    if (ArcNameMode != k_ArcNameMode_Add)

+    {

+      MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath);

+      if (MethodMode.Type.FormatIndex >= 0)

+        MethodMode.Type_Defined = true;

+    }

+  }

+  return true;

+}

+

+bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)

+{

+  UString typeExt;

+  int formatIndex = MethodMode.Type.FormatIndex;

+  if (formatIndex < 0)

+  {

+    typeExt = kDefaultArcExt;

+  }

   else

   {

-    MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);

-    // It works incorrectly for update command if archive has some non-default extension!

-    if (MethodMode.FormatIndex < 0)

-      MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);

+    const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];

+    if (!arcInfo.UpdateEnabled)

+      return false;

+    typeExt = arcInfo.GetMainExt();

   }

-  if (MethodMode.FormatIndex < 0)

-    return false;

-  const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];

-  if (!arcInfo.UpdateEnabled)

-    return false;

-  UString typeExt = arcInfo.GetMainExt();

   UString ext = typeExt;

   if (SfxMode)

     ext = kSFXExtension;

   ArchivePath.BaseExtension = ext;

   ArchivePath.VolExtension = typeExt;

-  ArchivePath.ParseFromPath(arcPath);

-  for (int i = 0; i < Commands.Size(); i++)

+  ArchivePath.ParseFromPath(arcPath, ArcNameMode);

+  FOR_VECTOR (i, Commands)

   {

     CUpdateArchiveCommand &uc = Commands[i];

     uc.ArchivePath.BaseExtension = ext;

     uc.ArchivePath.VolExtension = typeExt;

-    uc.ArchivePath.ParseFromPath(uc.UserArchivePath);

+    uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode);

   }

   return true;

 }

@@ -298,36 +406,98 @@
 }

 */

 

+bool CRenamePair::Prepare()

+{

+  if (RecursedType != NRecursedType::kNonRecursed)

+    return false;

+  if (!WildcardParsing)

+    return true;

+  return !DoesNameContainWildcard(OldName);

+}

+

+extern bool g_CaseSensitive;

+

+static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)

+{

+  for (int i = 0;; i++)

+  {

+    wchar_t c1 = s1[i];

+    wchar_t c2 = s2[i];

+    if (c1 == 0 || c2 == 0)

+      return i;

+    if (c1 == c2)

+      continue;

+    if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))

+      continue;

+    if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2))

+      continue;

+    return i;

+  }

+}

+

+bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const

+{

+  int num = CompareTwoNames(OldName, src);

+  if (OldName[num] == 0)

+  {

+    if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1]))

+      return false;

+  }

+  else

+  {

+    // OldName[num] != 0

+    // OldName = "1\1a.txt"

+    // src = "1"

+

+    if (!isFolder ||

+        src[num] != 0 ||

+        !IsCharDirLimiter(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;

+}

+

 static HRESULT Compress(

+    const CUpdateOptions &options,

     CCodecs *codecs,

     const CActionSet &actionSet,

-    IInArchive *archive,

-    const CCompressionMethodMode &compressionMethod,

+    const CArc *arc,

     CArchivePath &archivePath,

     const CObjectVector<CArcItem> &arcItems,

-    bool shareForWrite,

-    bool stdInMode,

-    /* const UString & stdInFileName, */

-    bool stdOutMode,

+    Byte *processedItemsStatuses,

     const CDirItems &dirItems,

-    bool sfxMode,

-    const UString &sfxModule,

-    const CRecordVector<UInt64> &volumesSizes,

+    const CDirItem *parentDirItem,

     CTempFiles &tempFiles,

     CUpdateErrorInfo &errorInfo,

     IUpdateCallbackUI *callback)

 {

   CMyComPtr<IOutArchive> outArchive;

-  if (archive != NULL)

+  int formatIndex = options.MethodMode.Type.FormatIndex;

+  if (arc)

   {

-    CMyComPtr<IInArchive> archive2 = archive;

+    formatIndex = arc->FormatIndex;

+    if (formatIndex < 0)

+      return E_NOTIMPL;

+    CMyComPtr<IInArchive> archive2 = arc->Archive;

     HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);

     if (result != S_OK)

       throw kUpdateIsNotSupoorted;

   }

   else

   {

-    RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));

+    RINOK(codecs->CreateOutArchive(formatIndex, outArchive));

 

     #ifdef EXTERNAL_CODECS

     {

@@ -347,7 +517,7 @@
   UInt32 value;

   RINOK(outArchive->GetFileTimeType(&value));

 

-  switch(value)

+  switch (value)

   {

     case NFileTimeType::kWindows:

     case NFileTimeType::kUnix:

@@ -358,8 +528,69 @@
       return E_FAIL;

   }

 

+  {

+    const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];

+    if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())

+      return E_NOTIMPL;

+    if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())

+      return E_NOTIMPL;

+  }

+

   CRecordVector<CUpdatePair2> updatePairs2;

 

+  UStringVector newNames;

+

+  if (options.RenamePairs.Size() != 0)

+  {

+    FOR_VECTOR (i, arcItems)

+    {

+      const CArcItem &ai = arcItems[i];

+      bool needRename = false;

+      UString dest;

+      if (ai.Censored)

+      {

+        FOR_VECTOR (j, options.RenamePairs)

+        {

+          const CRenamePair &rp = options.RenamePairs[j];

+          if (rp.GetNewPath(ai.IsDir, ai.Name, dest))

+          {

+            needRename = true;

+            break;

+          }

+          if (ai.IsAltStream)

+          {

+            int colonPos = ai.Name.ReverseFind(':');

+            int slashPosPos = GetReverseSlashPos(ai.Name);

+            if (colonPos > slashPosPos)

+            {

+              UString mainName = ai.Name.Left(colonPos);

+              /*

+              actually we must improve that code to support cases

+              with folder renaming like: rn arc dir1\ dir2\

+              */

+              if (rp.GetNewPath(false, mainName, dest))

+              {

+                needRename = true;

+                dest += ':';

+                dest += ai.Name.Ptr(colonPos + 1);

+                break;

+              }

+            }

+          }

+        }

+      }

+      CUpdatePair2 up2;

+      up2.SetAs_NoChangeArcItem(ai.IndexInServer);

+      if (needRename)

+      {

+        up2.NewProps = true;

+        RINOK(arc->IsItemAnti(i, up2.IsAnti));

+        up2.NewNameIndex = newNames.Add(dest);

+      }

+      updatePairs2.Add(up2);

+    }

+  }

+  else

   {

     CRecordVector<CUpdatePair> updatePairs;

     GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!

@@ -368,61 +599,81 @@
   }

 

   UInt32 numFiles = 0;

-  for (int i = 0; i < updatePairs2.Size(); i++)

+  FOR_VECTOR (i, updatePairs2)

     if (updatePairs2[i].NewData)

       numFiles++;

   

   RINOK(callback->SetNumFiles(numFiles));

-

   

   CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;

   CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);

   

-  updateCallbackSpec->ShareForWrite = shareForWrite;

-  updateCallbackSpec->StdInMode = stdInMode;

+  updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;

+  updateCallbackSpec->StdInMode = options.StdInMode;

   updateCallbackSpec->Callback = callback;

+

+  if (arc)

+  {

+    // 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;

+  updateCallbackSpec->ParentDirItem = parentDirItem;

+

+  updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;

+  updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;

+  updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;

+

   updateCallbackSpec->ArcItems = &arcItems;

   updateCallbackSpec->UpdatePairs = &updatePairs2;

 

+  updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;

+

+  if (options.RenamePairs.Size() != 0)

+    updateCallbackSpec->NewNames = &newNames;

+

+  CMyComPtr<IOutStream> outSeekStream;

   CMyComPtr<ISequentialOutStream> outStream;

 

-  if (!stdOutMode)

+  if (!options.StdOutMode)

   {

-    UString resultPath;

-    int pos;

-    if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))

+    FString dirPrefix;

+    if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix))

       throw 1417161;

-    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));

+    CreateComplexDir(dirPrefix);

   }

 

   COutFileStream *outStreamSpec = NULL;

   COutMultiVolStream *volStreamSpec = NULL;

 

-  if (volumesSizes.Size() == 0)

+  if (options.VolumesSizes.Size() == 0)

   {

-    if (stdOutMode)

+    if (options.StdOutMode)

       outStream = new CStdOutFileStream;

     else

     {

       outStreamSpec = new COutFileStream;

-      outStream = outStreamSpec;

+      outSeekStream = outStreamSpec;

+      outStream = outSeekStream;

       bool isOK = false;

-      UString realPath;

+      FString realPath;

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

       {

         if (archivePath.Temp)

         {

           if (i > 0)

           {

-            wchar_t s[16];

+            FChar s[16];

             ConvertUInt32ToString(i, s);

             archivePath.TempPostfix = s;

           }

           realPath = archivePath.GetTempPath();

         }

         else

-          realPath = archivePath.GetFinalPath();

+          realPath = us2fs(archivePath.GetFinalPath());

         if (outStreamSpec->Create(realPath, false))

         {

           tempFiles.Paths.Add(realPath);

@@ -445,12 +696,16 @@
   }

   else

   {

-    if (stdOutMode)

+    if (options.StdOutMode)

       return E_FAIL;

+    if (arc && arc->GetGlobalOffset() > 0)

+      return E_NOTIMPL;

+      

     volStreamSpec = new COutMultiVolStream;

-    outStream = volStreamSpec;

-    volStreamSpec->Sizes = volumesSizes;

-    volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");

+    outSeekStream = volStreamSpec;

+    outStream = outSeekStream;

+    volStreamSpec->Sizes = options.VolumesSizes;

+    volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L".");

     volStreamSpec->TempFiles = &tempFiles;

     volStreamSpec->Init();

 

@@ -462,29 +717,29 @@
     */

   }

 

-  RINOK(SetProperties(outArchive, compressionMethod.Properties));

+  RINOK(SetProperties(outArchive, options.MethodMode.Properties));

 

-  if (sfxMode)

+  if (options.SfxMode)

   {

     CInFileStream *sfxStreamSpec = new CInFileStream;

     CMyComPtr<IInStream> sfxStream(sfxStreamSpec);

-    if (!sfxStreamSpec->Open(sfxModule))

+    if (!sfxStreamSpec->Open(options.SfxModule))

     {

       errorInfo.SystemError = ::GetLastError();

       errorInfo.Message = L"7-Zip cannot open SFX module";

-      errorInfo.FileName = sfxModule;

+      errorInfo.FileName = options.SfxModule;

       return E_FAIL;

     }

 

     CMyComPtr<ISequentialOutStream> sfxOutStream;

     COutFileStream *outStreamSpec = NULL;

-    if (volumesSizes.Size() == 0)

+    if (options.VolumesSizes.Size() == 0)

       sfxOutStream = outStream;

     else

     {

       outStreamSpec = new COutFileStream;

       sfxOutStream = outStreamSpec;

-      UString realPath = archivePath.GetFinalPath();

+      FString realPath = us2fs(archivePath.GetFinalPath());

       if (!outStreamSpec->Create(realPath, false))

       {

         errorInfo.SystemError = ::GetLastError();

@@ -500,9 +755,61 @@
     }

   }

 

-  HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);

+  CMyComPtr<ISequentialOutStream> tailStream;

+

+  if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)

+    tailStream = outStream;

+  else

+  {

+    // Int64 globalOffset = arc->GetGlobalOffset();

+    RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL));

+    RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL));

+    if (options.StdOutMode)

+      tailStream = outStream;

+    else

+    {

+      CTailOutStream *tailStreamSpec = new CTailOutStream;

+      tailStream = tailStreamSpec;

+      tailStreamSpec->Stream = outSeekStream;

+      tailStreamSpec->Offset = arc->ArcStreamOffset;

+      tailStreamSpec->Init();

+    }

+  }

+

+

+  HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);

   callback->Finilize();

   RINOK(result);

+

+

+  if (options.SetArcMTime)

+  {

+    FILETIME ft;

+    ft.dwLowDateTime = 0;

+    ft.dwHighDateTime = 0;

+    FOR_VECTOR (i, updatePairs2)

+    {

+      CUpdatePair2 &pair2 = updatePairs2[i];

+      const FILETIME *ft2 = NULL;

+      if (pair2.NewProps && pair2.DirIndex >= 0)

+        ft2 = &dirItems.Items[pair2.DirIndex].MTime;

+      else if (pair2.UseArcProps && pair2.ArcIndex >= 0)

+        ft2 = &arcItems[pair2.ArcIndex].MTime;

+      if (ft2)

+      {

+        if (::CompareFileTime(&ft, ft2) < 0)

+          ft = *ft2;

+      }

+    }

+    if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)

+    {

+      if (outStreamSpec)

+        outStreamSpec->SetMTime(&ft);

+      else if (volStreamSpec)

+        volStreamSpec->SetMTime(&ft);;

+    }

+  }

+

   if (outStreamSpec)

     result = outStreamSpec->Close();

   else if (volStreamSpec)

@@ -510,7 +817,9 @@
   return result;

 }

 

-HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,

+static HRESULT EnumerateInArchiveItems(

+    // bool storeStreamsMode,

+    const NWildcard::CCensor &censor,

     const CArc &arc,

     CObjectVector<CArcItem> &arcItems)

 {

@@ -518,23 +827,21 @@
   UInt32 numItems;

   IInArchive *archive = arc.Archive;

   RINOK(archive->GetNumberOfItems(&numItems));

-  arcItems.Reserve(numItems);

+  arcItems.ClearAndReserve(numItems);

   for (UInt32 i = 0; i < numItems; i++)

   {

     CArcItem ai;

 

     RINOK(arc.GetItemPath(i, ai.Name));

-    RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));

-    ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);

+    RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir));

+    RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream));

+    /*

+    if (!storeStreamsMode && ai.IsAltStream)

+      continue;

+    */

+    ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir);

     RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));

-

-    {

-      CPropVariant prop;

-      RINOK(archive->GetProperty(i, kpidSize, &prop));

-      ai.SizeDefined = (prop.vt != VT_EMPTY);

-      if (ai.SizeDefined)

-        ai.Size = ConvertPropVariantToUInt64(prop);

-    }

+    RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));

 

     {

       CPropVariant prop;

@@ -542,7 +849,7 @@
       if (prop.vt == VT_UI4)

       {

         ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;

-        switch(ai.TimeType)

+        switch (ai.TimeType)

         {

           case NFileTimeType::kWindows:

           case NFileTimeType::kUnix:

@@ -555,99 +862,102 @@
     }

 

     ai.IndexInServer = i;

-    arcItems.Add(ai);

+    arcItems.AddInReserved(ai);

   }

   return S_OK;

 }

 

-

-static HRESULT UpdateWithItemLists(

-    CCodecs *codecs,

-    CUpdateOptions &options,

-    IInArchive *archive,

-    const CObjectVector<CArcItem> &arcItems,

-    CDirItems &dirItems,

-    CTempFiles &tempFiles,

-    CUpdateErrorInfo &errorInfo,

-    IUpdateCallbackUI2 *callback)

-{

-  for(int i = 0; i < options.Commands.Size(); i++)

-  {

-    CUpdateArchiveCommand &command = options.Commands[i];

-    if (options.StdOutMode)

-    {

-      RINOK(callback->StartArchive(L"stdout", archive != 0));

-    }

-    else

-    {

-      RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),

-          i == 0 && options.UpdateArchiveItself && archive != 0));

-    }

-

-    RINOK(Compress(

-        codecs,

-        command.ActionSet, archive,

-        options.MethodMode,

-        command.ArchivePath,

-        arcItems,

-        options.OpenShareForWrite,

-        options.StdInMode,

-        /* options.StdInFileName, */

-        options.StdOutMode,

-        dirItems,

-        options.SfxMode, options.SfxModule,

-        options.VolumesSizes,

-        tempFiles,

-        errorInfo, callback));

-

-    RINOK(callback->FinishArchive());

-  }

-  return S_OK;

-}

-

-#if defined(_WIN32) && !defined(UNDER_CE)

-class CCurrentDirRestorer

-{

-  UString _path;

-public:

-  CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); }

-  ~CCurrentDirRestorer() { RestoreDirectory();}

-  bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); }

-};

-#endif

-

 struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback

 {

   IUpdateCallbackUI2 *Callback;

-  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)

+  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)

   {

-    return Callback->ScanProgress(numFolders, numFiles, path);

+    return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);

   }

 };

 

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+#include <mapi.h>

+

+#endif

+

+struct CRefSortPair

+{

+  int Len;

+  int Index;

+};

+

+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

+

+static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)

+{

+  RINOZ(-MyCompare(a1->Len, a2->Len));

+  return MyCompare(a1->Index, a2->Index);

+}

+

+static int GetNumSlashes(const FChar *s)

+{

+  for (int numSlashes = 0;;)

+  {

+    FChar c = *s++;

+    if (c == 0)

+      return numSlashes;

+    if (

+        #ifdef _WIN32

+        c == FTEXT('\\') ||

+        #endif

+        c == FTEXT('/'))

+      numSlashes++;

+  }

+}

+

 #ifdef _WIN32

-typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(

-  ULONG_PTR ulUIParam,

-  LPSTR lpszDelimChar,

-  LPSTR lpszFilePaths,

-  LPSTR lpszFileNames,

-  ULONG ulReserved

-);

-typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;

+void ConvertToLongNames(NWildcard::CCensor &censor);

 #endif

 

 HRESULT UpdateArchive(

     CCodecs *codecs,

-    const NWildcard::CCensor &censor,

+    const CObjectVector<COpenType> &types,

+    const UString &cmdArcPath2,

+    NWildcard::CCensor &censor,

     CUpdateOptions &options,

     CUpdateErrorInfo &errorInfo,

     IOpenCallbackUI *openCallback,

-    IUpdateCallbackUI2 *callback)

+    IUpdateCallbackUI2 *callback,

+    bool needSetPath)

 {

   if (options.StdOutMode && options.EMailMode)

     return E_FAIL;

 

-  if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))

+  if (types.Size() > 1)

+    return E_NOTIMPL;

+

+  bool renameMode = !options.RenamePairs.IsEmpty();

+  if (renameMode)

+  {

+    if (options.Commands.Size() != 1)

+      return E_FAIL;

+  }

+

+  if (options.DeleteAfterCompressing)

+  {

+    if (options.Commands.Size() != 1)

+      return E_NOTIMPL;

+    const CActionSet &as = options.Commands[0].ActionSet;

+    for (int i = 2; i < NPairState::kNumValues; i++)

+      if (as.StateActions[i] != NPairAction::kCompress)

+        return E_NOTIMPL;

+  }

+

+  censor.AddPathsToCensor(options.PathMode);

+  #ifdef _WIN32

+  ConvertToLongNames(censor);

+  #endif

+  censor.ExtendExclude();

+

+  

+  if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */))

     return E_NOTIMPL;

 

   if (options.SfxMode)

@@ -661,40 +971,96 @@
       errorInfo.Message = L"SFX file is not specified";

       return E_FAIL;

     }

-    UString name = options.SfxModule;

-    #ifdef UNDER_CE

-    if (!NFind::DoesFileExist(name))

-    #else

-    if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))

-    #endif

+    bool found = false;

+    if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)

     {

-      errorInfo.SystemError = ::GetLastError();

-      errorInfo.Message = L"7-Zip cannot find specified SFX module";

-      errorInfo.FileName = name;

-      return E_FAIL;

+      const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule;

+      if (NFind::DoesFileExist(fullName))

+      {

+        options.SfxModule = fullName;

+        found = true;

+      }

+    }

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

+      }

     }

   }

 

-

   CArchiveLink arcLink;

-  const UString arcPath = options.ArchivePath.GetFinalPath();

 

-  if (!options.ArchivePath.OriginalPath.IsEmpty())

+  

+  if (needSetPath)

   {

-    NFind::CFileInfoW fi;

-    if (fi.Find(arcPath))

+    if (!options.InitFormatIndex(codecs, types, cmdArcPath2) ||

+        !options.SetArcPath(codecs, cmdArcPath2))

+      return E_NOTIMPL;

+  }

+  UString arcPath = options.ArchivePath.GetFinalPath();

+

+  if (cmdArcPath2.IsEmpty())

+  {

+    if (options.MethodMode.Type.FormatIndex < 0)

+      throw "type of archive is not specified";

+  }

+  else

+  {

+    NFind::CFileInfo fi;

+    if (!fi.Find(us2fs(arcPath)))

+    {

+      if (renameMode)

+        throw "can't find archive";;

+      if (options.MethodMode.Type.FormatIndex < 0)

+      {

+        if (!options.SetArcPath(codecs, cmdArcPath2))

+          return E_NOTIMPL;

+      }

+    }

+    else

     {

       if (fi.IsDir())

         throw "there is no such archive";

+      if (fi.IsDevice)

+        return E_NOTIMPL;

       if (options.VolumesSizes.Size() > 0)

         return E_NOTIMPL;

-      CIntVector formatIndices;

-      if (options.MethodMode.FormatIndex >= 0)

-        formatIndices.Add(options.MethodMode.FormatIndex);

-      HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);

+      CObjectVector<COpenType> types;

+      // change it.

+      if (options.MethodMode.Type_Defined)

+        types.Add(options.MethodMode.Type);

+      // We need to set Properties to open archive only in some cases (WIM archives).

+

+      CIntVector excl;

+      COpenOptions op;

+      #ifndef _SFX

+      op.props = &options.MethodMode.Properties;

+      #endif

+      op.codecs = codecs;

+      op.types = &types;

+      op.excludedFormats = &excl;

+      op.stdInMode = false;

+      op.stream = NULL;

+      op.filePath = arcPath;

+

+      HRESULT result = arcLink.Open2(op, openCallback);

+

       if (result == E_ABORT)

         return result;

-      RINOK(callback->OpenResult(arcPath, 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));

+      /*

+      if (result == S_FALSE)

+        return E_FAIL;

+      */

       RINOK(result);

       if (arcLink.VolumePaths.Size() > 1)

       {

@@ -706,17 +1072,44 @@
       CArc &arc = arcLink.Arcs.Back();

       arc.MTimeDefined = !fi.IsDevice;

       arc.MTime = fi.MTime;

+

+      if (arc.ErrorInfo.ThereIsTail)

+      {

+        errorInfo.SystemError = (DWORD)E_NOTIMPL;

+        errorInfo.Message = L"There is some data block after the end of the archive";

+        return E_NOTIMPL;

+      }

+      if (options.MethodMode.Type.FormatIndex < 0)

+      {

+        options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex;

+        if (!options.SetArcPath(codecs, cmdArcPath2))

+          return E_NOTIMPL;

+      }

     }

   }

-  else

+

+  if (options.MethodMode.Type.FormatIndex < 0)

   {

-    /*

-    if (archiveType.IsEmpty())

-      throw "type of archive is not specified";

-    */

+    options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType);

+    if (options.MethodMode.Type.FormatIndex < 0)

+      return E_NOTIMPL;

   }

 

+  bool thereIsInArchive = arcLink.IsOpen;

+  if (!thereIsInArchive && renameMode)

+    return E_FAIL;

+

   CDirItems dirItems;

+  CDirItem parentDirItem;

+  CDirItem *parentDirItem_Ptr = NULL;

+  

+  /*

+  FStringVector requestedPaths;

+  FStringVector *requestedPaths_Ptr = NULL;

+  if (options.DeleteAfterCompressing)

+    requestedPaths_Ptr = &requestedPaths;

+  */

+

   if (options.StdInMode)

   {

     CDirItem di;

@@ -730,7 +1123,8 @@
   else

   {

     bool needScanning = false;

-    for(int i = 0; i < options.Commands.Size(); i++)

+    if (!renameMode)

+    FOR_VECTOR (i, options.Commands)

       if (options.Commands[i].ActionSet.NeedScanning())

         needScanning = true;

     if (needScanning)

@@ -738,12 +1132,21 @@
       CEnumDirItemUpdateCallback enumCallback;

       enumCallback.Callback = callback;

       RINOK(callback->StartScanning());

-      UStringVector errorPaths;

-      CRecordVector<DWORD> errorCodes;

-      HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);

-      for (int i = 0; i < errorPaths.Size(); i++)

+

+      dirItems.SymLinks = options.SymLinks.Val;

+

+      #if defined(_WIN32) && !defined(UNDER_CE)

+      dirItems.ReadSecure = options.NtSecurity.Val;

+      #endif

+

+      dirItems.ScanAltStreams = options.AltStreams.Val;

+      HRESULT res = EnumerateItems(censor,

+          options.PathMode,

+          options.AddPathPrefix,

+          dirItems, &enumCallback);

+      FOR_VECTOR (i, dirItems.ErrorPaths)

       {

-        RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));

+        RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));

       }

       if (res != S_OK)

       {

@@ -752,14 +1155,46 @@
         return res;

       }

       RINOK(callback->FinishScanning());

+

+      if (censor.Pairs.Size() == 1)

+      {

+        NFind::CFileInfo fi;

+        FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT(".");

+        // UString prefix = censor.Pairs[0].Prefix;

+        /*

+        if (prefix.Back() == WCHAR_PATH_SEPARATOR)

+        {

+          prefix.DeleteBack();

+        }

+        */

+        if (fi.Find(prefix))

+          if (fi.IsDir())

+          {

+            parentDirItem.Size = fi.Size;

+            parentDirItem.CTime = fi.CTime;

+            parentDirItem.ATime = fi.ATime;

+            parentDirItem.MTime = fi.MTime;

+            parentDirItem.Attrib = fi.Attrib;

+            parentDirItem_Ptr = &parentDirItem;

+

+            int secureIndex = -1;

+            #if defined(_WIN32) && !defined(UNDER_CE)

+            if (options.NtSecurity.Val)

+              dirItems.AddSecurityItem(prefix, secureIndex);

+            #endif

+            parentDirItem.SecureIndex = secureIndex;

+

+            parentDirItem_Ptr = &parentDirItem;

+          }

+      }

     }

   }

 

-  UString tempDirPrefix;

+  FString tempDirPrefix;

   bool usesTempDir = false;

   

   #ifdef _WIN32

-  NDirectory::CTempDirectoryW tempDirectory;

+  CTempDir tempDirectory;

   if (options.EMailMode && options.EMailRemoveAfter)

   {

     tempDirectory.Create(kTempFolderPrefix);

@@ -773,8 +1208,6 @@
 

   bool createTempFile = false;

 

-  bool thereIsInArchive = arcLink.IsOpen;

-

   if (!options.StdOutMode && options.UpdateArchiveItself)

   {

     CArchivePath &ap = options.Commands[0].ArchivePath;

@@ -785,27 +1218,28 @@
       createTempFile = true;

       ap.Temp = true;

       if (!options.WorkingDir.IsEmpty())

-      {

         ap.TempPrefix = options.WorkingDir;

-        NormalizeDirPathPrefix(ap.TempPrefix);

-      }

+      else

+        ap.TempPrefix = us2fs(ap.Prefix);

+      NormalizeDirPathPrefix(ap.TempPrefix);

     }

   }

 

-  for(int i = 0; i < options.Commands.Size(); i++)

+  unsigned i;

+  for (i = 0; i < options.Commands.Size(); i++)

   {

     CArchivePath &ap = options.Commands[i].ArchivePath;

     if (usesTempDir)

     {

       // Check it

-      ap.Prefix = tempDirPrefix;

+      ap.Prefix = fs2us(tempDirPrefix);

       // ap.Temp = true;

       // ap.TempPrefix = tempDirPrefix;

     }

     if (!options.StdOutMode &&

         (i > 0 || !createTempFile))

     {

-      const UString &path = ap.GetFinalPath();

+      const FString path = us2fs(ap.GetFinalPath());

       if (NFind::DoesFileOrDirExist(path))

       {

         errorInfo.SystemError = 0;

@@ -819,13 +1253,64 @@
   CObjectVector<CArcItem> arcItems;

   if (thereIsInArchive)

   {

-    RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));

+    RINOK(EnumerateInArchiveItems(

+      // options.StoreAltStreams,

+      censor, arcLink.Arcs.Back(), arcItems));

   }

 

-  RINOK(UpdateWithItemLists(codecs, options,

-      thereIsInArchive ? arcLink.GetArchive() : 0,

-      arcItems, dirItems,

-      tempFiles, errorInfo, callback));

+  /*

+  FStringVector processedFilePaths;

+  FStringVector *processedFilePaths_Ptr = NULL;

+  if (options.DeleteAfterCompressing)

+    processedFilePaths_Ptr = &processedFilePaths;

+  */

+

+  CByteBuffer processedItems;

+  if (options.DeleteAfterCompressing)

+  {

+    unsigned num = dirItems.Items.Size();

+    processedItems.Alloc(num);

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

+      processedItems[i] = 0;

+  }

+

+  for (i = 0; i < options.Commands.Size(); i++)

+  {

+    const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0;

+    // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0;

+    // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0;

+    CUpdateArchiveCommand &command = options.Commands[i];

+    UString name;

+    bool isUpdating;

+    if (options.StdOutMode)

+    {

+      name = L"stdout";

+      isUpdating = arc != 0;

+    }

+    else

+    {

+      name = command.ArchivePath.GetFinalPath();

+      isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0);

+    }

+    RINOK(callback->StartArchive(name, isUpdating))

+

+    RINOK(Compress(options,

+        codecs,

+        command.ActionSet,

+        arc,

+        command.ArchivePath,

+        arcItems,

+        options.DeleteAfterCompressing ? (Byte *)processedItems : NULL,

+

+        dirItems,

+        parentDirItem_Ptr,

+

+        tempFiles,

+        errorInfo, callback));

+

+    RINOK(callback->FinishArchive());

+  }

+

 

   if (thereIsInArchive)

   {

@@ -839,21 +1324,21 @@
     try

     {

       CArchivePath &ap = options.Commands[0].ArchivePath;

-      const UString &tempPath = ap.GetTempPath();

+      const FString &tempPath = ap.GetTempPath();

       if (thereIsInArchive)

-        if (!NDirectory::DeleteFileAlways(arcPath))

+        if (!DeleteFileAlways(us2fs(arcPath)))

         {

           errorInfo.SystemError = ::GetLastError();

           errorInfo.Message = L"7-Zip cannot delete the file";

-          errorInfo.FileName = arcPath;

+          errorInfo.FileName = us2fs(arcPath);

           return E_FAIL;

         }

-      if (!NDirectory::MyMoveFile(tempPath, arcPath))

+      if (!MyMoveFile(tempPath, us2fs(arcPath)))

       {

         errorInfo.SystemError = ::GetLastError();

         errorInfo.Message = L"7-Zip cannot move the file";

         errorInfo.FileName = tempPath;

-        errorInfo.FileName2 = arcPath;

+        errorInfo.FileName2 = us2fs(arcPath);

         return E_FAIL;

       }

     }

@@ -863,30 +1348,42 @@
     }

   }

 

+

   #if defined(_WIN32) && !defined(UNDER_CE)

   if (options.EMailMode)

   {

     NDLL::CLibrary mapiLib;

-    if (!mapiLib.Load(TEXT("Mapi32.dll")))

+    if (!mapiLib.Load(FTEXT("Mapi32.dll")))

     {

       errorInfo.SystemError = ::GetLastError();

       errorInfo.Message = L"7-Zip cannot load Mapi32.dll";

       return E_FAIL;

     }

-    MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");

+

+    /*

+    LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");

     if (fnSend == 0)

     {

       errorInfo.SystemError = ::GetLastError();

       errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";

       return E_FAIL;

     }

-    UStringVector fullPaths;

-    int i;

-    for(i = 0; i < options.Commands.Size(); i++)

+    */

+    LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");

+    if (sendMail == 0)

+    {

+      errorInfo.SystemError = ::GetLastError();

+      errorInfo.Message = L"7-Zip cannot find MAPISendMail function";

+      return E_FAIL;

+    }

+

+    FStringVector fullPaths;

+    unsigned i;

+    for (i = 0; i < options.Commands.Size(); i++)

     {

       CArchivePath &ap = options.Commands[i].ArchivePath;

-      UString arcPath;

-      if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))

+      FString arcPath;

+      if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath))

       {

         errorInfo.SystemError = ::GetLastError();

         errorInfo.Message = L"GetFullPathName error";

@@ -895,16 +1392,86 @@
       fullPaths.Add(arcPath);

     }

     CCurrentDirRestorer curDirRestorer;

-    for(i = 0; i < fullPaths.Size(); i++)

+    for (i = 0; i < fullPaths.Size(); i++)

     {

-      UString arcPath = fullPaths[i];

+      UString arcPath = fs2us(fullPaths[i]);

       UString fileName = ExtractFileNameFromPath(arcPath);

       AString path = GetAnsiString(arcPath);

       AString name = GetAnsiString(fileName);

       // Warning!!! MAPISendDocuments function changes Current directory

-      fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);

+      // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);

+

+      MapiFileDesc f;

+      memset(&f, 0, sizeof(f));

+      f.nPosition = 0xFFFFFFFF;

+      f.lpszPathName = (char *)(const char *)path;

+      f.lpszFileName = (char *)(const char *)name;

+      

+      MapiMessage m;

+      memset(&m, 0, sizeof(m));

+      m.nFileCount = 1;

+      m.lpFiles = &f;

+      

+      const AString addr = GetAnsiString(options.EMailAddress);

+      MapiRecipDesc rec;

+      if (!addr.IsEmpty())

+      {

+        memset(&rec, 0, sizeof(rec));

+        rec.ulRecipClass = MAPI_TO;

+        rec.lpszAddress = (char *)(const char *)addr;

+        m.nRecipCount = 1;

+        m.lpRecips = &rec;

+      }

+      

+      sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);

     }

   }

   #endif

+

+  if (options.DeleteAfterCompressing)

+  {

+    CRecordVector<CRefSortPair> pairs;

+    FStringVector foldersNames;

+    for (i = 0; i < dirItems.Items.Size(); i++)

+    {

+      const CDirItem &dirItem = dirItems.Items[i];

+      FString phyPath = us2fs(dirItems.GetPhyPath(i));

+      if (dirItem.IsDir())

+      {

+        CRefSortPair pair;

+        pair.Index = i;

+        pair.Len = GetNumSlashes(phyPath);

+        pairs.Add(pair);

+      }

+      else

+      {

+        if (processedItems[i] != 0 || dirItem.Size == 0)

+        {

+          DeleteFileAlways(phyPath);

+        }

+        else

+        {

+          // file was skipped

+          /*

+          errorInfo.SystemError = 0;

+          errorInfo.Message = L"file was not processed";

+          errorInfo.FileName = phyPath;

+          return E_FAIL;

+          */

+        }

+      }

+    }

+

+    pairs.Sort(CompareRefSortPair, NULL);

+    for (i = 0; i < pairs.Size(); i++)

+    {

+      FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index));

+      if (NFind::DoesDirExist(phyPath))

+      {

+        // printf("delete %S\n", phyPath);

+        RemoveDir(phyPath);

+      }

+    }

+  }

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
old mode 100755
new mode 100644
index 6bc85b5..2d1d131
--- a/CPP/7zip/UI/Common/Update.h
+++ b/CPP/7zip/UI/Common/Update.h
@@ -3,14 +3,22 @@
 #ifndef __COMMON_UPDATE_H

 #define __COMMON_UPDATE_H

 

-#include "Common/Wildcard.h"

+#include "../../../Common/Wildcard.h"

 

 #include "ArchiveOpenCallback.h"

 #include "LoadCodecs.h"

+#include "OpenArchive.h"

 #include "Property.h"

 #include "UpdateAction.h"

 #include "UpdateCallback.h"

 

+enum EArcNameMode

+{

+  k_ArcNameMode_Smart,

+  k_ArcNameMode_Exact,

+  k_ArcNameMode_Add,

+};

+

 struct CArchivePath

 {

   UString OriginalPath;

@@ -21,57 +29,16 @@
   UString VolExtension;  // archive type extension for volumes

 

   bool Temp;

-  UString TempPrefix;  // path(folder) for temp location

-  UString TempPostfix;

+  FString TempPrefix;  // path(folder) for temp location

+  FString TempPostfix;

 

   CArchivePath(): Temp(false) {};

   

-  void ParseFromPath(const UString &path)

-  {

-    OriginalPath = path;

-

-    SplitPathToParts(path, Prefix, Name);

-    int dotPos = Name.ReverseFind(L'.');

-    if (dotPos < 0)

-      return;

-    if (dotPos == Name.Length() - 1)

-    {

-      Name = Name.Left(dotPos);

-      BaseExtension.Empty();

-      return;

-    }

-    if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)

-    {

-      BaseExtension = Name.Mid(dotPos + 1);

-      Name = Name.Left(dotPos);

-    }

-    else

-      BaseExtension.Empty();

-  }

-

-  UString GetPathWithoutExt() const

-  {

-    return Prefix + Name;

-  }

-

-  UString GetFinalPath() const

-  {

-    UString path = GetPathWithoutExt();

-    if (!BaseExtension.IsEmpty())

-      path += UString(L'.') + BaseExtension;

-    return path;

-  }

-

-  

-  UString GetTempPath() const

-  {

-    UString path = TempPrefix + Name;

-    if (!BaseExtension.IsEmpty())

-      path += UString(L'.') + BaseExtension;

-    path += L".tmp";

-    path += TempPostfix;

-    return path;

-  }

+  void ParseFromPath(const UString &path, EArcNameMode mode);

+  UString GetPathWithoutExt() const { return Prefix + Name; }

+  UString GetFinalPath() const;

+  UString GetFinalVolPath() const;

+  FString GetTempPath() const;

 };

 

 struct CUpdateArchiveCommand

@@ -83,9 +50,31 @@
 

 struct CCompressionMethodMode

 {

-  int FormatIndex;

+  bool Type_Defined;

+  COpenType Type;

   CObjectVector<CProperty> Properties;

-  CCompressionMethodMode(): FormatIndex(-1) {}

+  

+  CCompressionMethodMode(): Type_Defined(false) {}

+};

+

+namespace NRecursedType { enum EEnum

+{

+  kRecursed,

+  kWildcardOnlyRecursed,

+  kNonRecursed

+};}

+

+struct CRenamePair

+{

+  UString OldName;

+  UString NewName;

+  bool WildcardParsing;

+  NRecursedType::EEnum RecursedType;

+  

+  CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {}

+

+  bool Prepare();

+  bool GetNewPath(bool isFolder, const UString &src, UString &dest) const;

 };

 

 struct CUpdateOptions

@@ -95,9 +84,10 @@
   CObjectVector<CUpdateArchiveCommand> Commands;

   bool UpdateArchiveItself;

   CArchivePath ArchivePath;

-  

+  EArcNameMode ArcNameMode;

+

   bool SfxMode;

-  UString SfxModule;

+  FString SfxModule;

   

   bool OpenShareForWrite;

 

@@ -109,9 +99,23 @@
   bool EMailRemoveAfter;

   UString EMailAddress;

 

-  UString WorkingDir;

+  FString WorkingDir;

+  NWildcard::ECensorPathMode PathMode;

+  UString AddPathPrefix;

 

-  bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath);

+  CBoolPair NtSecurity;

+  CBoolPair AltStreams;

+  CBoolPair HardLinks;

+  CBoolPair SymLinks;

+

+  bool DeleteAfterCompressing;

+

+  bool SetArcMTime;

+

+  CObjectVector<CRenamePair> RenamePairs;

+

+  bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);

+  bool SetArcPath(const CCodecs *codecs, const UString &arcPath);

 

   CUpdateOptions():

     UpdateArchiveItself(true),

@@ -120,14 +124,20 @@
     StdOutMode(false),

     EMailMode(false),

     EMailRemoveAfter(false),

-    OpenShareForWrite(false)

+    OpenShareForWrite(false),

+    ArcNameMode(k_ArcNameMode_Smart),

+    PathMode(NWildcard::k_RelatPath),

+    

+    DeleteAfterCompressing(false),

+    SetArcMTime(false)

+

       {};

 

-  void SetAddActionCommand()

+  void SetActionCommand_Add()

   {

     Commands.Clear();

     CUpdateArchiveCommand c;

-    c.ActionSet = NUpdateArchive::kAddActionSet;

+    c.ActionSet = NUpdateArchive::k_ActionSet_Add;

     Commands.Add(c);

   }

 

@@ -137,8 +147,8 @@
 struct CErrorInfo

 {

   DWORD SystemError;

-  UString FileName;

-  UString FileName2;

+  FString FileName;

+  FString FileName2;

   UString Message;

   // UStringVector ErrorPaths;

   // CRecordVector<DWORD> ErrorCodes;

@@ -151,9 +161,9 @@
 

 #define INTERFACE_IUpdateCallbackUI2(x) \

   INTERFACE_IUpdateCallbackUI(x) \

-  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \

+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \

   virtual HRESULT StartScanning() x; \

-  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) 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 StartArchive(const wchar_t *name, bool updating) x; \

@@ -166,10 +176,13 @@
 

 HRESULT UpdateArchive(

     CCodecs *codecs,

-    const NWildcard::CCensor &censor,

+    const CObjectVector<COpenType> &types,

+    const UString &cmdArcPath2,

+    NWildcard::CCensor &censor,

     CUpdateOptions &options,

     CUpdateErrorInfo &errorInfo,

     IOpenCallbackUI *openCallback,

-    IUpdateCallbackUI2 *callback);

+    IUpdateCallbackUI2 *callback,

+    bool needSetPath);

 

 #endif

diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp
old mode 100755
new mode 100644
index 2e3dd62..ba138d2
--- a/CPP/7zip/UI/Common/UpdateAction.cpp
+++ b/CPP/7zip/UI/Common/UpdateAction.cpp
@@ -6,7 +6,7 @@
 

 namespace NUpdateArchive {

 

-const CActionSet kAddActionSet =

+const CActionSet k_ActionSet_Add =

 {{

   NPairAction::kCopy,

   NPairAction::kCopy,

@@ -17,7 +17,7 @@
   NPairAction::kCompress

 }};

 

-const CActionSet kUpdateActionSet =

+const CActionSet k_ActionSet_Update =

 {{

   NPairAction::kCopy,

   NPairAction::kCopy,

@@ -28,7 +28,7 @@
   NPairAction::kCompress

 }};

 

-const CActionSet kFreshActionSet =

+const CActionSet k_ActionSet_Fresh =

 {{

   NPairAction::kCopy,

   NPairAction::kCopy,

@@ -39,7 +39,7 @@
   NPairAction::kCompress

 }};

 

-const CActionSet kSynchronizeActionSet =

+const CActionSet k_ActionSet_Sync =

 {{

   NPairAction::kCopy,

   NPairAction::kIgnore,

@@ -50,7 +50,7 @@
   NPairAction::kCompress,

 }};

 

-const CActionSet kDeleteActionSet =

+const CActionSet k_ActionSet_Delete =

 {{

   NPairAction::kCopy,

   NPairAction::kIgnore,

diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
old mode 100755
new mode 100644
index 7ad57ce..6e10b7d
--- a/CPP/7zip/UI/Common/UpdateAction.h
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -7,7 +7,7 @@
 

   namespace NPairState

   {

-    const int kNumValues = 7;

+    const unsigned kNumValues = 7;

     enum EEnum

     {

       kNotMasked = 0,

@@ -34,9 +34,18 @@
   struct CActionSet

   {

     NPairAction::EEnum StateActions[NPairState::kNumValues];

+    

+    const bool IsEqualTo(const CActionSet &a) const

+    {

+      for (unsigned i = 0; i < NPairState::kNumValues; i++)

+        if (StateActions[i] != a.StateActions[i])

+          return false;

+      return true;

+    }

+

     bool NeedScanning() const

     {

-      int i;

+      unsigned i;

       for (i = 0; i < NPairState::kNumValues; i++)

         if (StateActions[i] == NPairAction::kCompress)

           return true;

@@ -47,11 +56,11 @@
     }

   };

   

-  extern const CActionSet kAddActionSet;

-  extern const CActionSet kUpdateActionSet;

-  extern const CActionSet kFreshActionSet;

-  extern const CActionSet kSynchronizeActionSet;

-  extern const CActionSet kDeleteActionSet;

+  extern const CActionSet k_ActionSet_Add;

+  extern const CActionSet k_ActionSet_Update;

+  extern const CActionSet k_ActionSet_Fresh;

+  extern const CActionSet k_ActionSet_Sync;

+  extern const CActionSet k_ActionSet_Delete;

 }

 

 #endif

diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
old mode 100755
new mode 100644
index 55c9374..8aaddfa
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -2,18 +2,32 @@
 

 #include "StdAfx.h"

 

-#include "Common/ComTry.h"

-#include "Common/Defs.h"

-#include "Common/IntToString.h"

-#include "Common/StringConvert.h"

+#include "../../../Common/ComTry.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/Wildcard.h"

 

-#include "Windows/PropVariant.h"

+#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"

 

+#if defined(_WIN32) && !defined(UNDER_CE)

+#define _USE_SECURITY_CODE

+#include "../../../Windows/SecurityUtils.h"

+#endif

+

 using namespace NWindows;

+using namespace NFile;

+

+#ifdef _USE_SECURITY_CODE

+bool InitLocalPrivileges();

+#endif

 

 CArchiveUpdateCallback::CArchiveUpdateCallback():

   Callback(0),

@@ -22,8 +36,19 @@
   DirItems(0),

   ArcItems(0),

   UpdatePairs(0),

-  NewNames(0)

-  {}

+  NewNames(0),

+  KeepOriginalItemNames(false),

+  ProcessedItemsStatuses(NULL),

+  ParentDirItem(NULL),

+  StoreNtSecurity(false),

+  StoreHardLinks(false),

+  StoreSymLinks(false),

+  _hardIndex_From((UInt32)(Int32)-1)

+{

+  #ifdef _USE_SECURITY_CODE

+  _saclEnabled = InitLocalPrivileges();

+  #endif

+}

 

 

 STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)

@@ -49,7 +74,7 @@
 

 

 /*

-STATPROPSTG kProperties[] =

+static const STATPROPSTG kProps[] =

 {

   { NULL, kpidPath, VT_BSTR},

   { NULL, kpidIsDir, VT_BOOL},

@@ -63,7 +88,7 @@
 

 STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)

 {

-  return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator);

+  return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);

 }

 */

 

@@ -73,11 +98,11 @@
   COM_TRY_BEGIN

   RINOK(Callback->CheckBreak());

   const CUpdatePair2 &up = (*UpdatePairs)[index];

-  if (newData != NULL) *newData = BoolToInt(up.NewData);

-  if (newProps != NULL) *newProps = BoolToInt(up.NewProps);

-  if (indexInArchive != NULL)

+  if (newData) *newData = BoolToInt(up.NewData);

+  if (newProps) *newProps = BoolToInt(up.NewProps);

+  if (indexInArchive)

   {

-    *indexInArchive = (UInt32)-1;

+    *indexInArchive = (UInt32)(Int32)-1;

     if (up.ExistInArchive())

       *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;

   }

@@ -85,40 +110,289 @@
   COM_TRY_END

 }

 

+STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)

+{

+  NCOM::CPropVariant prop;

+  switch (propID)

+  {

+    case kpidIsDir:  prop = true; break;

+    case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;

+    case kpidCTime:  if (ParentDirItem) prop = ParentDirItem->CTime; break;

+    case kpidATime:  if (ParentDirItem) prop = ParentDirItem->ATime; break;

+    case kpidMTime:  if (ParentDirItem) prop = ParentDirItem->MTime; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)

+{

+  *parentType = NParentType::kDir;

+  *parent = (UInt32)(Int32)-1;

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)

+{

+  *numProps = 0;

+  if (StoreNtSecurity)

+    *numProps = 1;

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)

+{

+  *name = NULL;

+  *propID = kpidNtSecure;

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID

+    #ifdef _USE_SECURITY_CODE

+    propID

+    #endif

+    , const void **data, UInt32 *dataSize, UInt32 *propType)

+{

+  *data = 0;

+  *dataSize = 0;

+  *propType = 0;

+  if (!StoreNtSecurity)

+    return S_OK;

+  #ifdef _USE_SECURITY_CODE

+  if (propID == kpidNtSecure)

+  {

+    if (StdInMode)

+      return S_OK;

+

+    if (ParentDirItem)

+    {

+      if (ParentDirItem->SecureIndex < 0)

+        return S_OK;

+      const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex];

+      *data = buf;

+      *dataSize = (UInt32)buf.Size();

+      *propType = NPropDataType::kRaw;

+      return S_OK;

+    }

+

+    if (GetRootProps)

+      return GetRootProps->GetRootRawProp(propID, data, dataSize, propType);

+  }

+  #endif

+  return S_OK;

+}

+

+//    #ifdef _USE_SECURITY_CODE

+//    #endif

+

+STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)

+{

+  *data = 0;

+  *dataSize = 0;

+  *propType = 0;

+

+  if (propID == kpidNtSecure ||

+      propID == kpidNtReparse)

+  {

+    if (StdInMode)

+      return S_OK;

+

+    const CUpdatePair2 &up = (*UpdatePairs)[index];

+    if (up.UseArcProps && up.ExistInArchive() && GetRawProps)

+      return GetRawProps->GetRawProp(

+          ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,

+          propID, data, dataSize, propType);

+

+    {

+      const CUpdatePair2 &up = (*UpdatePairs)[index];

+      /*

+      if (!up.NewData)

+        return E_FAIL;

+      */

+      if (up.IsAnti)

+        return S_OK;

+      

+      #ifndef UNDER_CE

+      const CDirItem &di = DirItems->Items[up.DirIndex];

+      #endif

+

+      #ifdef _USE_SECURITY_CODE

+      if (propID == kpidNtSecure)

+      {

+        if (!StoreNtSecurity)

+          return S_OK;

+        if (di.SecureIndex < 0)

+          return S_OK;

+        const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex];

+        *data = buf;

+        *dataSize = (UInt32)buf.Size();

+        *propType = NPropDataType::kRaw;

+      }

+      else

+      #endif

+      {

+        // propID == kpidNtReparse

+        if (!StoreSymLinks)

+          return S_OK;

+        #ifndef UNDER_CE

+        const CByteBuffer *buf = &di.ReparseData2;

+        if (buf->Size() == 0)

+          buf = &di.ReparseData;

+        if (buf->Size() != 0)

+        {

+          *data = *buf;

+          *dataSize = (UInt32)buf->Size();

+          *propType = NPropDataType::kRaw;

+        }

+        #endif

+      }

+ 

+      return S_OK;

+    }

+  }

+

+  return S_OK;

+}

+

+#ifndef UNDER_CE

+

+static UString GetRelativePath(const UString &to, const UString &from)

+{

+  UStringVector partsTo, partsFrom;

+  SplitPathToParts(to, partsTo);

+  SplitPathToParts(from, partsFrom);

+

+  unsigned i;

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

+  {

+    if (i + 1 >= partsFrom.Size() ||

+        i + 1 >= partsTo.Size())

+      break;

+    if (CompareFileNames(partsFrom[i], partsTo[i]) != 0)

+      break;

+  }

+

+  if (i == 0)

+  {

+    #ifdef _WIN32

+    if (NName::IsDrivePath(to) ||

+        NName::IsDrivePath(from))

+      return to;

+    #endif

+  }

+

+  UString s;

+  unsigned k;

+  

+  for (k = i + 1; k < partsFrom.Size(); k++)

+    s += L".." WSTRING_PATH_SEPARATOR;

+  

+  for (k = i; k < partsTo.Size(); k++)

+  {

+    if (k != i)

+      s += WCHAR_PATH_SEPARATOR;

+    s += partsTo[k];

+  }

+

+  return s;

+}

+

+#endif

+

 STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

 {

   COM_TRY_BEGIN

   const CUpdatePair2 &up = (*UpdatePairs)[index];

-  NWindows::NCOM::CPropVariant prop;

-  

-  if (propID == kpidIsAnti)

-  {

-    prop = up.IsAnti;

-    prop.Detach(value);

-    return S_OK;

-  }

+  NCOM::CPropVariant prop;

 

-  if (up.IsAnti)

+  if (up.NewData)

   {

-    switch(propID)

+    /*

+    if (propID == kpidIsHardLink)

     {

-      case kpidIsDir:

-      case kpidPath:

-        break;

-      case kpidSize:

-        prop = (UInt64)0;

+      prop = _isHardLink;

+      prop.Detach(value);

+      return S_OK;

+    }

+    */

+    if (propID == kpidSymLink)

+    {

+      if (index == _hardIndex_From)

+      {

         prop.Detach(value);

         return S_OK;

-      default:

+      }

+      if (up.DirIndex >= 0)

+      {

+        #ifndef UNDER_CE

+        const CDirItem &di = DirItems->Items[up.DirIndex];

+        // if (di.IsDir())

+        {

+          CReparseAttr attr;

+          if (attr.Parse(di.ReparseData, di.ReparseData.Size()))

+          {

+            UString simpleName = attr.GetPath();

+            if (attr.IsRelative())

+              prop = simpleName;

+            else

+            {

+              const UString phyPath = DirItems->GetPhyPath(up.DirIndex);

+              FString fullPath;

+              if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath))

+              {

+                prop = GetRelativePath(simpleName, fs2us(fullPath));

+              }

+            }

+            prop.Detach(value);

+            return S_OK;

+          }

+        }

+        #endif

+      }

+    }

+    else if (propID == kpidHardLink)

+    {

+      if (index == _hardIndex_From)

+      {

+        const CKeyKeyValPair &pair = _map[_hardIndex_To];

+        const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];

+        prop = DirItems->GetLogPath(up2.DirIndex);

         prop.Detach(value);

         return S_OK;

+      }

+      if (up.DirIndex >= 0)

+      {

+        prop.Detach(value);

+        return S_OK;

+      }

     }

   }

   

-  if (up.ExistOnDisk())

+  if (up.IsAnti

+      && propID != kpidIsDir

+      && propID != kpidPath

+      && propID != kpidIsAltStream)

+  {

+    switch (propID)

+    {

+      case kpidSize:  prop = (UInt64)0; break;

+      case kpidIsAnti:  prop = true; break;

+    }

+  }

+  else if (propID == kpidPath && up.NewNameIndex >= 0)

+    prop = (*NewNames)[up.NewNameIndex];

+  else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)

+  {

+    // we can generate new ShortName here;

+  }

+  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())

   {

     const CDirItem &di = DirItems->Items[up.DirIndex];

-    switch(propID)

+    switch (propID)

     {

       case kpidPath:  prop = DirItems->GetLogPath(up.DirIndex); break;

       case kpidIsDir:  prop = di.IsDir(); break;

@@ -127,27 +401,10 @@
       case kpidCTime:  prop = di.CTime; break;

       case kpidATime:  prop = di.ATime; break;

       case kpidMTime:  prop = di.MTime; break;

-    }

-  }

-  else

-  {

-    if (propID == kpidPath)

-    {

-      if (up.NewNameIndex >= 0)

-      {

-        prop = (*NewNames)[up.NewNameIndex];

-        prop.Detach(value);

-        return S_OK;

-      }

-    }

-    if (up.ExistInArchive() && Archive)

-    {

-      UInt32 indexInArchive;

-      if (ArcItems == 0)

-        indexInArchive = up.ArcIndex;

-      else

-        indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer;

-      return Archive->GetProperty(indexInArchive, propID, value);

+      case kpidIsAltStream:  prop = di.IsAltStream; break;

+      #if defined(_WIN32) && !defined(UNDER_CE)

+      // case kpidShortName:  prop = di.ShortName; break;

+      #endif

     }

   }

   prop.Detach(value);

@@ -155,9 +412,12 @@
   COM_TRY_END

 }

 

+static NSynchronization::CCriticalSection CS;

+

 STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)

 {

   COM_TRY_BEGIN

+  *inStream = NULL;

   const CUpdatePair2 &up = (*UpdatePairs)[index];

   if (!up.NewData)

     return E_FAIL;

@@ -165,14 +425,33 @@
   RINOK(Callback->CheckBreak());

   RINOK(Callback->Finilize());

 

+  bool isDir = IsDir(up);

+

   if (up.IsAnti)

   {

-    return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true);

+    UString name;

+    if (up.ArcIndex >= 0)

+      name = (*ArcItems)[up.ArcIndex].Name;

+    else if (up.DirIndex >= 0)

+      name = DirItems->GetLogPath(up.DirIndex);

+    RINOK(Callback->GetStream(name, true));

+    

+    /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.

+       so we return empty stream */

+

+    if (!isDir)

+    {

+      CBufInStream *inStreamSpec = new CBufInStream();

+      CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;

+      inStreamSpec->Init(NULL, 0);

+      *inStream = inStreamLoc.Detach();

+    }

+    return S_OK;

   }

-  const CDirItem &di = DirItems->Items[up.DirIndex];

+  

   RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));

  

-  if (di.IsDir())

+  if (isDir)

     return S_OK;

 

   if (StdInMode)

@@ -185,13 +464,59 @@
   {

     CInFileStream *inStreamSpec = new CInFileStream;

     CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

+

+    inStreamSpec->SupportHardLinks = StoreHardLinks;

+

     const UString path = DirItems->GetPhyPath(up.DirIndex);

-    if (!inStreamSpec->OpenShared(path, ShareForWrite))

+

+    #if defined(_WIN32) && !defined(UNDER_CE)

+    if (DirItems->Items[up.DirIndex].AreReparseData())

+    {

+      if (!inStreamSpec->File.OpenReparse(us2fs(path)))

+      {

+        return Callback->OpenFileError(path, ::GetLastError());

+      }

+    }

+    else

+    #endif

+    if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite))

     {

       return Callback->OpenFileError(path, ::GetLastError());

     }

+

+    if (StoreHardLinks)

+    {

+      CStreamFileProps props;

+      if (inStreamSpec->GetProps2(&props) == S_OK)

+      {

+        if (props.NumLinks > 1)

+        {

+          CKeyKeyValPair pair;

+          pair.Key1 = props.VolID;

+          pair.Key2 = props.FileID_Low;

+          pair.Value = index;

+          unsigned numItems = _map.Size();

+          unsigned pairIndex = _map.AddToUniqueSorted2(pair);

+          if (numItems == _map.Size())

+          {

+            // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex];

+            _hardIndex_From = index;

+            _hardIndex_To = pairIndex;

+            // we could return NULL as stream, but it's better to return real stream

+            // return S_OK;

+          }

+        }

+      }

+    }

+

+    if (ProcessedItemsStatuses)

+    {

+      NSynchronization::CCriticalSectionLock lock(CS);

+      ProcessedItemsStatuses[up.DirIndex] = 1;

+    }

     *inStream = inStreamLoc.Detach();

   }

+  

   return S_OK;

   COM_TRY_END

 }

@@ -216,12 +541,12 @@
 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)

 {

   COM_TRY_BEGIN

-  wchar_t temp[16];

+  FChar temp[16];

   ConvertUInt32ToString(index + 1, temp);

-  UString res = temp;

-  while (res.Length() < 2)

-    res = UString(L'0') + res;

-  UString fileName = VolName;

+  FString res = temp;

+  while (res.Len() < 2)

+    res.InsertAtFront(FTEXT('0'));

+  FString fileName = VolName;

   fileName += L'.';

   fileName += res;

   fileName += VolExt;

diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
old mode 100755
new mode 100644
index 2785ee9..41544db
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -1,10 +1,9 @@
 // UpdateCallback.h

 

-#ifndef __UPDATECALLBACK_H

-#define __UPDATECALLBACK_H

+#ifndef __UPDATE_CALLBACK_H

+#define __UPDATE_CALLBACK_H

 

-#include "Common/MyCom.h"

-#include "Common/MyString.h"

+#include "../../../Common/MyCom.h"

 

 #include "../../IPassword.h"

 #include "../../ICoder.h"

@@ -32,16 +31,43 @@
   INTERFACE_IUpdateCallbackUI(=0)

 };

 

+struct CKeyKeyValPair

+{

+  UInt64 Key1;

+  UInt64 Key2;

+  unsigned Value;

+

+  int Compare(const CKeyKeyValPair &a) const

+  {

+    if (Key1 < a.Key1) return -1;

+    if (Key1 > a.Key1) return 1;

+    return MyCompare(Key2, a.Key2);

+  }

+};

+

+

 class CArchiveUpdateCallback:

   public IArchiveUpdateCallback2,

+  public IArchiveGetRawProps,

+  public IArchiveGetRootProps,

   public ICryptoGetTextPassword2,

   public ICryptoGetTextPassword,

   public ICompressProgressInfo,

   public CMyUnknownImp

 {

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  bool _saclEnabled;

+  #endif

+  CRecordVector<CKeyKeyValPair> _map;

+

+  UInt32 _hardIndex_From;

+  UInt32 _hardIndex_To;

+

 public:

-  MY_UNKNOWN_IMP4(

+  MY_UNKNOWN_IMP6(

       IArchiveUpdateCallback2,

+      IArchiveGetRawProps,

+      IArchiveGetRootProps,

       ICryptoGetTextPassword2,

       ICryptoGetTextPassword,

       ICompressProgressInfo)

@@ -49,26 +75,48 @@
   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

 

   INTERFACE_IArchiveUpdateCallback2(;)

+  INTERFACE_IArchiveGetRawProps(;)

+  INTERFACE_IArchiveGetRootProps(;)

 

   STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);

   STDMETHOD(CryptoGetTextPassword)(BSTR *password);

 

-public:

   CRecordVector<UInt64> VolumesSizes;

-  UString VolName;

-  UString VolExt;

+  FString VolName;

+  FString VolExt;

 

   IUpdateCallbackUI *Callback;

 

   bool ShareForWrite;

   bool StdInMode;

+  

   const CDirItems *DirItems;

+  const CDirItem *ParentDirItem;

+  

   const CObjectVector<CArcItem> *ArcItems;

   const CRecordVector<CUpdatePair2> *UpdatePairs;

   const UStringVector *NewNames;

   CMyComPtr<IInArchive> Archive;

+  CMyComPtr<IArchiveGetRawProps> GetRawProps;

+  CMyComPtr<IArchiveGetRootProps> GetRootProps;

+

+  bool KeepOriginalItemNames;

+  bool StoreNtSecurity;

+  bool StoreHardLinks;

+  bool StoreSymLinks;

+

+  Byte *ProcessedItemsStatuses;

 

   CArchiveUpdateCallback();

+

+  bool IsDir(const CUpdatePair2 &up) const

+  {

+    if (up.DirIndex >= 0)

+      return DirItems->Items[up.DirIndex].IsDir();

+    else if (up.ArcIndex >= 0)

+      return (*ArcItems)[up.ArcIndex].IsDir;

+    return false;

+  }

 };

 

 #endif

diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
old mode 100755
new mode 100644
index 812bff8..e9c9c51
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -4,10 +4,9 @@
 

 #include <time.h>

 

-#include "Common/Defs.h"

-#include "Common/Wildcard.h"

+#include "../../../Common/Wildcard.h"

 

-#include "Windows/Time.h"

+#include "../../../Windows/TimeUtils.h"

 

 #include "SortUtils.h"

 #include "UpdatePair.h"

@@ -17,7 +16,7 @@
 

 static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)

 {

-  switch(fileTimeType)

+  switch (fileTimeType)

   {

     case NFileTimeType::kWindows:

       return ::CompareFileTime(&time1, &time2);

@@ -39,24 +38,38 @@
   throw 4191618;

 }

 

-static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";

-static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):";

+static const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:";

+static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:";

+static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";

 

-static void ThrowError(const UString &message, const UString &s1, const UString &s2)

+static void ThrowError(const char *message, const UString &s1, const UString &s2)

 {

-  UString m = message;

-  m += L'\n';

-  m += s1;

-  m += L'\n';

-  m += s2;

+  UString m;

+  m.SetFromAscii(message);

+  m += L'\n'; m += s1;

+  m += L'\n'; m += s2;

   throw m;

 }

 

-static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)

+static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)

 {

-  for(int i = 0; i + 1 < indices.Size(); i++)

-    if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)

-      ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]);

+  int res = CompareFileNames(ai1.Name, ai2.Name);

+  if (res != 0)

+    return res;

+  if (ai1.IsDir != ai2.IsDir)

+    return ai1.IsDir ? -1 : 1;

+  return 0;

+}

+

+static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)

+{

+  unsigned i1 = *p1;

+  unsigned i2 = *p2;

+  const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;

+  int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);

+  if (res != 0)

+    return res;

+  return MyCompare(i1, i2);

 }

 

 void GetUpdatePairInfoList(

@@ -65,48 +78,103 @@
     NFileTimeType::EEnum fileTimeType,

     CRecordVector<CUpdatePair> &updatePairs)

 {

-  CIntVector dirIndices, arcIndices;

+  CUIntVector dirIndices, arcIndices;

   

-  int numDirItems = dirItems.Items.Size();

-  int numArcItems = arcItems.Size();

+  unsigned numDirItems = dirItems.Items.Size();

+  unsigned numArcItems = arcItems.Size();

   

-  

+  CIntArr duplicatedArcItem(numArcItems);

   {

-    UStringVector arcNames;

-    arcNames.Reserve(numArcItems);

-    for (int i = 0; i < numArcItems; i++)

-      arcNames.Add(arcItems[i].Name);

-    SortFileNames(arcNames, arcIndices);

-    TestDuplicateString(arcNames, arcIndices);

+    int *vals = &duplicatedArcItem[0];

+    for (unsigned i = 0; i < numArcItems; i++)

+      vals[i] = 0;

+  }

+

+  {

+    arcIndices.ClearAndSetSize(numArcItems);

+    {

+      unsigned *vals = &arcIndices[0];

+      for (unsigned i = 0; i < numArcItems; i++)

+        vals[i] = i;

+    }

+    arcIndices.Sort(CompareArcItems, (void *)&arcItems);

+    for (unsigned i = 0; i + 1 < numArcItems; i++)

+      if (CompareArcItemsBase(

+          arcItems[arcIndices[i]],

+          arcItems[arcIndices[i + 1]]) == 0)

+      {

+        duplicatedArcItem[i] = 1;

+        duplicatedArcItem[i + 1] = -1;

+      }

   }

 

   UStringVector dirNames;

   {

-    dirNames.Reserve(numDirItems);

-    for (int i = 0; i < numDirItems; i++)

-      dirNames.Add(dirItems.GetLogPath(i));

+    dirNames.ClearAndReserve(numDirItems);

+    unsigned i;

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

+      dirNames.AddInReserved(dirItems.GetLogPath(i));

     SortFileNames(dirNames, dirIndices);

-    TestDuplicateString(dirNames, dirIndices);

+    for (i = 0; i + 1 < numDirItems; i++)

+    {

+      const UString &s1 = dirNames[dirIndices[i]];

+      const UString &s2 = dirNames[dirIndices[i + 1]];

+      if (CompareFileNames(s1, s2) == 0)

+        ThrowError(k_Duplicate_inDir_Message, s1, s2);

+    }

   }

   

-  int dirIndex = 0, arcIndex = 0;

-  while (dirIndex < numDirItems && arcIndex < numArcItems)

+  unsigned dirIndex = 0;

+  unsigned arcIndex = 0;

+

+  int prevHostFile = -1;

+  const UString *prevHostName = NULL;

+  

+  while (dirIndex < numDirItems || arcIndex < numArcItems)

   {

     CUpdatePair pair;

-    int dirIndex2 = dirIndices[dirIndex];

-    int arcIndex2 = arcIndices[arcIndex];

-    const CDirItem &di = dirItems.Items[dirIndex2];

-    const CArcItem &ai = arcItems[arcIndex2];

-    int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name);

+    

+    int dirIndex2 = -1;

+    int arcIndex2 = -1;

+    const CDirItem *di = NULL;

+    const CArcItem *ai = NULL;

+    

+    int compareResult = -1;

+    const UString *name = NULL;

+    

+    if (dirIndex < numDirItems)

+    {

+      dirIndex2 = dirIndices[dirIndex];

+      di = &dirItems.Items[dirIndex2];

+    }

+

+    if (arcIndex < numArcItems)

+    {

+      arcIndex2 = arcIndices[arcIndex];

+      ai = &arcItems[arcIndex2];

+      compareResult = 1;

+      if (dirIndex < numDirItems)

+      {

+        compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name);

+        if (compareResult == 0)

+        {

+          if (di->IsDir() != ai->IsDir)

+            compareResult = (ai->IsDir ? 1 : -1);

+        }

+      }

+    }

+    

     if (compareResult < 0)

     {

+      name = &dirNames[dirIndex2];

       pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;

       pair.DirIndex = dirIndex2;

       dirIndex++;

     }

     else if (compareResult > 0)

     {

-      pair.State = ai.Censored ?

+      name = &ai->Name;

+      pair.State = ai->Censored ?

           NUpdateArchive::NPairState::kOnlyInArchive:

           NUpdateArchive::NPairState::kNotMasked;

       pair.ArcIndex = arcIndex2;

@@ -114,43 +182,50 @@
     }

     else

     {

-      if (!ai.Censored)

-        ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name);

+      int dupl = duplicatedArcItem[arcIndex];

+      if (dupl != 0)

+        ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name);

+

+      name = &dirNames[dirIndex2];

+      if (!ai->Censored)

+        ThrowError(k_NotCensoredCollision_Message, *name, ai->Name);

+      

       pair.DirIndex = dirIndex2;

       pair.ArcIndex = arcIndex2;

-      switch (ai.MTimeDefined ? MyCompareTime(

-          ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType,

-          di.MTime, ai.MTime): 0)

+

+      switch (ai->MTimeDefined ? MyCompareTime(

+          ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,

+          di->MTime, ai->MTime): 0)

       {

         case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;

-        case 1:  pair.State = NUpdateArchive::NPairState::kOldInArchive; break;

+        case  1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;

         default:

-          pair.State = (ai.SizeDefined && di.Size == ai.Size) ?

+          pair.State = (ai->SizeDefined && di->Size == ai->Size) ?

               NUpdateArchive::NPairState::kSameFiles :

               NUpdateArchive::NPairState::kUnknowNewerFiles;

       }

+      

       dirIndex++;

       arcIndex++;

     }

-    updatePairs.Add(pair);

-  }

-

-  for (; dirIndex < numDirItems; dirIndex++)

-  {

-    CUpdatePair pair;

-    pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;

-    pair.DirIndex = dirIndices[dirIndex];

-    updatePairs.Add(pair);

-  }

-  

-  for (; arcIndex < numArcItems; arcIndex++)

-  {

-    CUpdatePair pair;

-    int arcIndex2 = arcIndices[arcIndex];

-    pair.State = arcItems[arcIndex2].Censored ?

-        NUpdateArchive::NPairState::kOnlyInArchive:

-        NUpdateArchive::NPairState::kNotMasked;

-    pair.ArcIndex = arcIndex2;

+    

+    if ((di && di->IsAltStream) ||

+        (ai && ai->IsAltStream))

+    {

+      if (prevHostName)

+      {

+        unsigned hostLen = prevHostName->Len();

+        if (name->Len() > hostLen)

+          if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0)

+            pair.HostIndex = prevHostFile;

+      }

+    }

+    else

+    {

+      prevHostFile = updatePairs.Size();

+      prevHostName = name;

+    }

+    

     updatePairs.Add(pair);

   }

 

diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h
old mode 100755
new mode 100644
index 5ee2665..36da243
--- a/CPP/7zip/UI/Common/UpdatePair.h
+++ b/CPP/7zip/UI/Common/UpdatePair.h
@@ -13,7 +13,9 @@
   NUpdateArchive::NPairState::EEnum State;

   int ArcIndex;

   int DirIndex;

-  CUpdatePair(): ArcIndex(-1), DirIndex(-1) {}

+  int HostIndex; // >= 0 for alt streams only, contains index of host pair

+

+  CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}

 };

 

 void GetUpdatePairInfoList(

diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
old mode 100755
new mode 100644
index 3ba677d..6726af3
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -14,17 +14,17 @@
     CRecordVector<CUpdatePair2> &operationChain,

     IUpdateProduceCallback *callback)

 {

-  for (int i = 0; i < updatePairs.Size(); i++)

+  FOR_VECTOR (i, updatePairs)

   {

     const CUpdatePair &pair = updatePairs[i];

 

     CUpdatePair2 up2;

-    up2.IsAnti = false;

     up2.DirIndex = pair.DirIndex;

     up2.ArcIndex = pair.ArcIndex;

     up2.NewData = up2.NewProps = true;

+    up2.UseArcProps = false;

     

-    switch(actionSet.StateActions[pair.State])

+    switch (actionSet.StateActions[pair.State])

     {

       case NPairAction::kIgnore:

         /*

@@ -39,7 +39,21 @@
       case NPairAction::kCopy:

         if (pair.State == NPairState::kOnlyOnDisk)

           throw kUpdateActionSetCollision;

+        if (pair.State == NPairState::kOnlyInArchive)

+        {

+          if (pair.HostIndex >= 0)

+          {

+            /*

+              ignore alt stream if

+                1) no such alt stream in Disk

+                2) there is Host file in disk

+            */

+            if (updatePairs[pair.HostIndex].DirIndex >= 0)

+              continue;

+          }

+        }

         up2.NewData = up2.NewProps = false;

+        up2.UseArcProps = true;

         break;

       

       case NPairAction::kCompress:

@@ -50,6 +64,7 @@
       

       case NPairAction::kCompressAsAnti:

         up2.IsAnti = true;

+        up2.UseArcProps = (pair.ArcIndex >= 0);

         break;

     }

     operationChain.Add(up2);

diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
old mode 100755
new mode 100644
index c511caf..f53055e
--- a/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -9,16 +9,36 @@
 {

   bool NewData;

   bool NewProps;

-  bool IsAnti;

+  bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties.

+  bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status

   

   int DirIndex;

   int ArcIndex;

   int NewNameIndex;

 

+  bool IsMainRenameItem;

+

+  void SetAs_NoChangeArcItem(int arcIndex)

+  {

+    NewData = NewProps = false;

+    UseArcProps = true;

+    IsAnti = false;

+    ArcIndex = arcIndex;

+  }

+

   bool ExistOnDisk() const { return DirIndex != -1; }

   bool ExistInArchive() const { return ArcIndex != -1; }

 

-  CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {}

+  CUpdatePair2():

+      NewData(false),

+      NewProps(false),

+      UseArcProps(false),

+      IsAnti(false),

+      DirIndex(-1),

+      ArcIndex(-1),

+      NewNameIndex(-1),

+      IsMainRenameItem(false)

+      {}

 };

 

 struct IUpdateProduceCallback

diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
old mode 100755
new mode 100644
index 2989632..6ff225b
--- a/CPP/7zip/UI/Common/WorkDir.cpp
+++ b/CPP/7zip/UI/Common/WorkDir.cpp
@@ -2,26 +2,26 @@
 

 #include "StdAfx.h"

 

-#include "Common/StringConvert.h"

-#include "Common/Wildcard.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/Wildcard.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/FileName.h"

+#include "../../../Windows/FileName.h"

 

 #include "WorkDir.h"

 

 using namespace NWindows;

 using namespace NFile;

+using namespace NDir;

 

-UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)

+FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)

 {

   NWorkDir::NMode::EEnum mode = workDirInfo.Mode;

   #ifndef UNDER_CE

   if (workDirInfo.ForRemovableOnly)

   {

     mode = NWorkDir::NMode::kCurrent;

-    UString prefix = path.Left(3);

-    if (prefix[1] == L':' && prefix[2] == L'\\')

+    FString prefix = path.Left(3);

+    if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\'))

     {

       UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));

       if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)

@@ -36,24 +36,56 @@
     */

   }

   #endif

-  switch(mode)

+  int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1;

+  fileName = path.Ptr(pos);

+  switch (mode)

   {

     case NWorkDir::NMode::kCurrent:

     {

-      return ExtractDirPrefixFromPath(path);

+      return path.Left(pos);;

     }

     case NWorkDir::NMode::kSpecified:

     {

-      UString tempDir = workDirInfo.Path;

+      FString tempDir = workDirInfo.Path;

       NName::NormalizeDirPathPrefix(tempDir);

       return tempDir;

     }

     default:

     {

-      UString tempDir;

-      if (!NDirectory::MyGetTempPath(tempDir))

+      FString tempDir;

+      if (!MyGetTempPath(tempDir))

         throw 141717;

       return tempDir;

     }

   }

 }

+

+HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)

+{

+  NWorkDir::CInfo workDirInfo;

+  workDirInfo.Load();

+  FString namePart;

+  FString workDir = GetWorkDir(workDirInfo, originalPath, namePart);

+  CreateComplexDir(workDir);

+  CTempFile tempFile;

+  _outStreamSpec = new COutFileStream;

+  OutStream = _outStreamSpec;

+  if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File))

+  {

+    DWORD error = GetLastError();

+    return error ? error : E_FAIL;

+  }

+  _originalPath = originalPath;

+  return S_OK;

+}

+

+HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal)

+{

+  OutStream.Release();

+  if (!_tempFile.MoveTo(_originalPath, deleteOriginal))

+  {

+    DWORD error = GetLastError();

+    return error ? error : E_FAIL;

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h
old mode 100755
new mode 100644
index 8208f3a..13d4ed9
--- a/CPP/7zip/UI/Common/WorkDir.h
+++ b/CPP/7zip/UI/Common/WorkDir.h
@@ -1,10 +1,26 @@
 // WorkDir.h

 

-#ifndef __WORKDIR_H

-#define __WORKDIR_H

+#ifndef __WORK_DIR_H

+#define __WORK_DIR_H

+

+#include "../../../Windows/FileDir.h"

+

+#include "../../Common/FileStreams.h"

 

 #include "ZipRegistry.h"

 

-UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);

+FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName);

+

+class CWorkDirTempFile

+{

+  FString _originalPath;

+  NWindows::NFile::NDir::CTempFile _tempFile;

+  COutFileStream *_outStreamSpec;

+public:

+  CMyComPtr<IOutStream> OutStream;

+

+  HRESULT CreateTempFile(const FString &originalPath);

+  HRESULT MoveToOriginal(bool deleteOriginal);

+};

 

 #endif

diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
old mode 100755
new mode 100644
index 1760d9b..df00aac
--- a/CPP/7zip/UI/Common/ZipRegistry.h
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -3,8 +3,8 @@
 #ifndef __ZIP_REGISTRY_H

 #define __ZIP_REGISTRY_H

 

-#include "Common/MyString.h"

-#include "Common/Types.h"

+#include "../../../Common/MyTypes.h"

+#include "../../../Common/MyString.h"

 

 #include "ExtractMode.h"

 

@@ -14,12 +14,23 @@
   {

     NPathMode::EEnum PathMode;

     NOverwriteMode::EEnum OverwriteMode;

-    bool ShowPassword;

+    bool PathMode_Force;

+    bool OverwriteMode_Force;

+    

+    CBoolPair SplitDest;

+    CBoolPair ElimDup;

+    // CBoolPair AltStreams;

+    CBoolPair NtSecurity;

+    CBoolPair ShowPassword;

+

     UStringVector Paths;

 

     void Save() const;

     void Load();

   };

+  

+  void Save_ShowPassword(bool showPassword);

+  bool Read_ShowPassword();

 }

 

 namespace NCompression

@@ -57,6 +68,11 @@
 

     CObjectVector<CFormatOptions> Formats;

 

+    CBoolPair NtSecurity;

+    CBoolPair AltStreams;

+    CBoolPair HardLinks;

+    CBoolPair SymLinks;

+

     void Save() const;

     void Load();

   };

@@ -76,7 +92,7 @@
   struct CInfo

   {

     NMode::EEnum Mode;

-    UString Path;

+    FString Path;

     bool ForRemovableOnly;

 

     void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }

@@ -96,6 +112,7 @@
 struct CContextMenuInfo

 {

   bool Cascaded;

+  bool MenuIcons;

   UInt32 Flags;

 

   void Save() const;

diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp
old mode 100755
new mode 100644
index a31d8e0..16cd24c
--- a/CPP/7zip/UI/Console/BenchCon.cpp
+++ b/CPP/7zip/UI/Console/BenchCon.cpp
@@ -2,296 +2,41 @@
 

 #include "StdAfx.h"

 

-#include "../../../Common/IntToString.h"

-#include "../../../Common/MyCom.h"

-

-#if !defined(_7ZIP_ST) || defined(_WIN32)

-#include "../../../Windows/System.h"

-#endif

-

 #include "../Common/Bench.h"

 

 #include "BenchCon.h"

 #include "ConsoleClose.h"

 

-struct CTotalBenchRes

+struct CPrintBenchCallback: public IBenchPrintCallback

 {

-  UInt64 NumIterations;

-  UInt64 Rating;

-  UInt64 Usage;

-  UInt64 RPU;

-  void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }

-  void Normalize()

-  {

-    if (NumIterations == 0)

-      return;

-    Rating /= NumIterations;

-    Usage /= NumIterations;

-    RPU /= NumIterations;

-    NumIterations = 1;

-  }

-  void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)

-  {

-    Rating = (r1.Rating + r2.Rating) / 2;

-    Usage = (r1.Usage + r2.Usage) / 2;

-    RPU = (r1.RPU + r2.RPU) / 2;

-    NumIterations = (r1.NumIterations + r2.NumIterations) / 2;

-  }

+  FILE *_file;

+

+  void Print(const char *s);

+  void NewLine();

+  HRESULT CheckBreak();

 };

 

-struct CBenchCallback: public IBenchCallback

+void CPrintBenchCallback::Print(const char *s)

 {

-  CTotalBenchRes EncodeRes;

-  CTotalBenchRes DecodeRes;

-  FILE *f;

-  void Init() { EncodeRes.Init(); DecodeRes.Init(); }

-  void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }

-  UInt32 dictionarySize;

-  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);

-  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);

-};

-

-static void NormalizeVals(UInt64 &v1, UInt64 &v2)

-{

-  while (v1 > 1000000)

-  {

-    v1 >>= 1;

-    v2 >>= 1;

-  }

+  fputs(s, _file);

 }

 

-static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)

+void CPrintBenchCallback::NewLine()

 {

-  UInt64 elTime = elapsedTime;

-  NormalizeVals(freq, elTime);

-  if (elTime == 0)

-    elTime = 1;

-  return value * freq / elTime;

+  Print("\n");

 }

 

-static void PrintNumber(FILE *f, UInt64 value, int size)

+HRESULT CPrintBenchCallback::CheckBreak()

 {

-  char s[32];

-  ConvertUInt64ToString(value, s);

-  fprintf(f, " ");

-  for (int len = (int)strlen(s); len < size; len++)

-    fprintf(f, " ");

-  fputs(s, f);

+  return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK;

 }

 

-static void PrintRating(FILE *f, UInt64 rating)

+HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS

+    const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f)

 {

-  PrintNumber(f, rating / 1000000, 6);

-}

-

-static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)

-{

-  PrintNumber(f, (usage + 5000) / 10000, 5);

-  PrintRating(f, rpu);

-  PrintRating(f, rating);

-}

-

-

-static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)

-{

-  UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);

-  PrintNumber(f, speed / 1024, 7);

-  UInt64 usage = GetUsage(info);

-  UInt64 rpu = GetRatingPerUsage(info, rating);

-  PrintResults(f, usage, rpu, rating);

-  res.NumIterations++;

-  res.RPU += rpu;

-  res.Rating += rating;

-  res.Usage += usage;

-}

-

-static void PrintTotals(FILE *f, const CTotalBenchRes &res)

-{

-  fprintf(f, "       ");

-  PrintResults(f, res.Usage, res.RPU, res.Rating);

-}

-

-

-HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)

-{

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  if (final)

-  {

-    UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);

-    PrintResults(f, info, rating, EncodeRes);

-  }

-  return S_OK;

-}

-

-static const char *kSep = "  | ";

-

-

-HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)

-{

-  if (NConsoleClose::TestBreakSignal())

-    return E_ABORT;

-  if (final)

-  {

-    UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);

-    fputs(kSep, f);

-    CBenchInfo info2 = info;

-    info2.UnpackSize *= info2.NumIterations;

-    info2.PackSize *= info2.NumIterations;

-    info2.NumIterations = 1;

-    PrintResults(f, info2, rating, DecodeRes);

-  }

-  return S_OK;

-}

-

-static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)

-{

-  fprintf(f, "\nRAM %s ", sizeString);

-  PrintNumber(f, (size >> 20), 5);

-  fprintf(f, " MB,  # %s %3d", threadsString, (unsigned int)numThreads);

-}

-

-HRESULT LzmaBenchCon(

-  DECL_EXTERNAL_CODECS_LOC_VARS

-  FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)

-{

-  if (!CrcInternalTest())

-    return S_FALSE;

-  #ifndef _7ZIP_ST

-  UInt64 ramSize = NWindows::NSystem::GetRamSize();  //

-  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

-  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);

-  if (numThreads == (UInt32)-1)

-    numThreads = numCPUs;

-  if (numThreads > 1)

-    numThreads &= ~1;

-  if (dictionary == (UInt32)-1)

-  {

-    int dicSizeLog;

-    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)

-      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)

-        break;

-    dictionary = (1 << dicSizeLog);

-  }

-  #else

-  if (dictionary == (UInt32)-1)

-    dictionary = (1 << 22);

-  numThreads = 1;

-  #endif

-

-  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads:   ", numThreads);

-

-  CBenchCallback callback;

-  callback.Init();

-  callback.f = f;

-  

-  fprintf(f, "\n\nDict        Compressing          |        Decompressing\n   ");

-  int j;

-  for (j = 0; j < 2; j++)

-  {

-    fprintf(f, "   Speed Usage    R/U Rating");

-    if (j == 0)

-      fputs(kSep, f);

-  }

-  fprintf(f, "\n   ");

-  for (j = 0; j < 2; j++)

-  {

-    fprintf(f, "    KB/s     %%   MIPS   MIPS");

-    if (j == 0)

-      fputs(kSep, f);

-  }

-  fprintf(f, "\n\n");

-  for (UInt32 i = 0; i < numIterations; i++)

-  {

-    const int kStartDicLog = 22;

-    int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;

-    while (((UInt32)1 << pow) > dictionary)

-      pow--;

-    for (; ((UInt32)1 << pow) <= dictionary; pow++)

-    {

-      fprintf(f, "%2d:", pow);

-      callback.dictionarySize = (UInt32)1 << pow;

-      HRESULT res = LzmaBench(

-        EXTERNAL_CODECS_LOC_VARS

-        numThreads, callback.dictionarySize, &callback);

-      fprintf(f, "\n");

-      RINOK(res);

-    }

-  }

-  callback.Normalize();

-  fprintf(f, "----------------------------------------------------------------\nAvr:");

-  PrintTotals(f, callback.EncodeRes);

-  fprintf(f, "     ");

-  PrintTotals(f, callback.DecodeRes);

-  fprintf(f, "\nTot:");

-  CTotalBenchRes midRes;

-  midRes.SetMid(callback.EncodeRes, callback.DecodeRes);

-  PrintTotals(f, midRes);

-  fprintf(f, "\n");

-  return S_OK;

-}

-

-struct CTempValues

-{

-  UInt64 *Values;

-  CTempValues(UInt32 num) { Values = new UInt64[num]; }

-  ~CTempValues() { delete []Values; }

-};

-

-HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)

-{

-  if (!CrcInternalTest())

-    return S_FALSE;

-

-  #ifndef _7ZIP_ST

-  UInt64 ramSize = NWindows::NSystem::GetRamSize();

-  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

-  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);

-  if (numThreads == (UInt32)-1)

-    numThreads = numCPUs;

-  #else

-  numThreads = 1;

-  #endif

-  if (dictionary == (UInt32)-1)

-    dictionary = (1 << 24);

-

-  CTempValues speedTotals(numThreads);

-  fprintf(f, "\n\nSize");

-  for (UInt32 ti = 0; ti < numThreads; ti++)

-  {

-    fprintf(f, " %5d", ti + 1);

-    speedTotals.Values[ti] = 0;

-  }

-  fprintf(f, "\n\n");

-

-  UInt64 numSteps = 0;

-  for (UInt32 i = 0; i < numIterations; i++)

-  {

-    for (int pow = 10; pow < 32; pow++)

-    {

-      UInt32 bufSize = (UInt32)1 << pow;

-      if (bufSize > dictionary)

-        break;

-      fprintf(f, "%2d: ", pow);

-      UInt64 speed;

-      for (UInt32 ti = 0; ti < numThreads; ti++)

-      {

-        if (NConsoleClose::TestBreakSignal())

-          return E_ABORT;

-        RINOK(CrcBench(ti + 1, bufSize, speed));

-        PrintNumber(f, (speed >> 20), 5);

-        speedTotals.Values[ti] += speed;

-      }

-      fprintf(f, "\n");

-      numSteps++;

-    }

-  }

-  if (numSteps != 0)

-  {

-    fprintf(f, "\nAvg:");

-    for (UInt32 ti = 0; ti < numThreads; ti++)

-      PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);

-    fprintf(f, "\n");

-  }

-  return S_OK;

+  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/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h
old mode 100755
new mode 100644
index c5eafbf..ef235ee
--- a/CPP/7zip/UI/Console/BenchCon.h
+++ b/CPP/7zip/UI/Console/BenchCon.h
@@ -6,11 +6,9 @@
 #include <stdio.h>

 

 #include "../../Common/CreateCoder.h"

+#include "../../UI/Common/Property.h"

 

-HRESULT LzmaBenchCon(

-    DECL_EXTERNAL_CODECS_LOC_VARS

-    FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);

-

-HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);

+HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS

+    const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f);

 

 #endif

diff --git a/CPP/7zip/UI/Console/Console.mak b/CPP/7zip/UI/Console/Console.mak
new file mode 100644
index 0000000..b0f8301
--- /dev/null
+++ b/CPP/7zip/UI/Console/Console.mak
@@ -0,0 +1,35 @@
+CONSOLE_OBJS = \

+  $O\BenchCon.obj \

+  $O\ConsoleClose.obj \

+  $O\ExtractCallbackConsole.obj \

+  $O\HashCon.obj \

+  $O\List.obj \

+  $O\Main.obj \

+  $O\MainAr.obj \

+  $O\OpenCallbackConsole.obj \

+  $O\PercentPrinter.obj \

+  $O\UpdateCallbackConsole.obj \

+  $O\UserInputUtils.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveCommandLine.obj \

+  $O\ArchiveExtractCallback.obj \

+  $O\ArchiveOpenCallback.obj \

+  $O\Bench.obj \

+  $O\DefaultName.obj \

+  $O\EnumDirItems.obj \

+  $O\Extract.obj \

+  $O\ExtractingFilePath.obj \

+  $O\HashCalc.obj \

+  $O\LoadCodecs.obj \

+  $O\OpenArchive.obj \

+  $O\PropIDUtils.obj \

+  $O\SetProperties.obj \

+  $O\SortUtils.obj \

+  $O\TempFiles.obj \

+  $O\Update.obj \

+  $O\UpdateAction.obj \

+  $O\UpdateCallback.obj \

+  $O\UpdatePair.obj \

+  $O\UpdateProduce.obj \

+

diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
old mode 100755
new mode 100644
index 278b069..0c6f806
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -1,20 +1,21 @@
-// ExtractCallbackConsole.h

+// ExtractCallbackConsole.cpp

 

 #include "StdAfx.h"

 

+// #undef sprintf

+

+#include "ConsoleClose.h"

 #include "ExtractCallbackConsole.h"

 #include "UserInputUtils.h"

-#include "ConsoleClose.h"

 

-#include "Common/Wildcard.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/Wildcard.h"

 

-#include "Windows/FileDir.h"

-#include "Windows/FileFind.h"

-#include "Windows/Time.h"

-#include "Windows/Defs.h"

-#include "Windows/PropVariant.h"

-#include "Windows/Error.h"

-#include "Windows/PropVariantConversions.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/TimeUtils.h"

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/PropVariantConv.h"

 

 #include "../../Common/FilePathAutoRename.h"

 

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

 using namespace NWindows;

 using namespace NFile;

-using namespace NDirectory;

+using namespace NDir;

 

 static const char *kTestString    =  "Testing     ";

 static const char *kExtractString =  "Extracting  ";

-static const char *kSkipString   =  "Skipping    ";

+static const char *kSkipString    =  "Skipping    ";

 

 // static const char *kCantAutoRename = "can not create file with auto name\n";

 // static const char *kCantRenameFile = "can not rename existing file\n";

@@ -43,7 +44,27 @@
 static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";

 static const char *kDataError = "Data Error";

 static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";

-static const char *kUnknownError = "Unknown Error";

+static const char *kUnavailableData = "Unavailable data";

+static const char *kUnexpectedEnd = "Unexpected end of data";

+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 *k_ErrorFlagsMessages[] =

+{

+    "Is not archive"

+  , "Headers Error"

+  , "Headers Error in encrypted archive. Wrong password?"

+  , "Unavailable start of archive"

+  , "Unconfirmed start of archive"

+  , "Unexpected end of archive"

+  , "There are data after the end of archive"

+  , "Unsupported method"

+  , "Unsupported feature"

+  , "Data Error"

+  , "CRC Error"

+};

+

 

 STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)

 {

@@ -64,13 +85,13 @@
     const wchar_t *newName, const FILETIME *, const UInt64 *,

     Int32 *answer)

 {

-  (*OutStream) << "file " << existName <<

-    "\nalready exists. Overwrite with " << endl;

-  (*OutStream) << newName;

+  (*OutStream) << "file " << existName << endl <<

+        "already exists. Overwrite with" << endl <<

+        newName;

   

   NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);

   

-  switch(overwriteAnswer)

+  switch (overwriteAnswer)

   {

     case NUserAnswerMode::kQuit:  return E_ABORT;

     case NUserAnswerMode::kNo:     *answer = NOverwriteAnswer::kNo; break;

@@ -85,13 +106,15 @@
 

 STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)

 {

+  const char *s;

   switch (askExtractMode)

   {

-    case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break;

-    case NArchive::NExtract::NAskMode::kTest:    (*OutStream) << kTestString; break;

-    case NArchive::NExtract::NAskMode::kSkip:    (*OutStream) << kSkipString; break;

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

   };

-  (*OutStream) << name;

+  (*OutStream) << s << name;

   if (position != 0)

     (*OutStream) << " <" << *position << ">";

   return S_OK;

@@ -100,35 +123,57 @@
 STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)

 {

   (*OutStream) << message << endl;

-  NumFileErrorsInCurrentArchive++;

+  NumFileErrorsInCurrent++;

   NumFileErrors++;

   return S_OK;

 }

 

 STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)

 {

-  switch(operationResult)

+  switch (operationResult)

   {

     case NArchive::NExtract::NOperationResult::kOK:

       break;

     default:

     {

-      NumFileErrorsInCurrentArchive++;

+      NumFileErrorsInCurrent++;

       NumFileErrors++;

-      (*OutStream) << "     ";

-      switch(operationResult)

+      (*OutStream) << "  :  ";

+      const char *s = NULL;

+      switch (operationResult)

       {

-        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

-          (*OutStream) << kUnsupportedMethod;

+        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:

+          s = kUnsupportedMethod;

           break;

         case NArchive::NExtract::NOperationResult::kCRCError:

-          (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);

+          s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);

           break;

         case NArchive::NExtract::NOperationResult::kDataError:

-          (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);

+          s = (encrypted ? kDataErrorEncrypted : kDataError);

           break;

-        default:

-          (*OutStream) << kUnknownError;

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

       }

     }

   }

@@ -159,8 +204,10 @@
 

 HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)

 {

-  NumArchives++;

-  NumFileErrorsInCurrentArchive = 0;

+  NumTryArcs++;

+  ThereIsErrorInCurrent = false;

+  ThereIsWarningInCurrent = false;

+  NumFileErrorsInCurrent = 0;

   (*OutStream) << endl << kProcessing << name << endl;

   return S_OK;

 }

@@ -185,10 +232,92 @@
         (*OutStream) << NError::MyFormatMessage(result);

     }

     (*OutStream) << endl;

-    NumArchiveErrors++;

+    NumCantOpenArcs++;

+    ThereIsErrorInCurrent = true;

   }

   return S_OK;

 }

+

+AString GetOpenArcErrorMessage(UInt32 errorFlags)

+{

+  AString s;

+  for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)

+  {

+    UInt32 f = (1 << i);

+    if ((errorFlags & f) == 0)

+      continue;

+    const char *m = k_ErrorFlagsMessages[i];

+    if (!s.IsEmpty())

+      s += '\n';

+    s += m;

+    errorFlags &= ~f;

+  }

+  if (errorFlags != 0)

+  {

+    char sz[16];

+    sz[0] = '0';

+    sz[1] = 'x';

+    ConvertUInt32ToHex(errorFlags, sz + 2);

+    if (!s.IsEmpty())

+      s += '\n';

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

+{

+  if (level != 0)

+  {

+    (*OutStream) << name << endl;

+  }

+

+  if (errorFlags != 0)

+  {

+    (*OutStream) << "Errors: ";

+    (*OutStream) << endl;

+    (*OutStream) << GetOpenArcErrorMessage(errorFlags);

+    (*OutStream) << endl;

+    NumOpenArcErrors++;

+    ThereIsErrorInCurrent = true;

+  }

+

+  if (errors && wcslen(errors) != 0)

+  {

+    (*OutStream) << "Errors: ";

+    (*OutStream) << endl;

+    (*OutStream) << errors;

+    (*OutStream) << endl;

+    NumOpenArcErrors++;

+    ThereIsErrorInCurrent = true;

+  }

+

+  if (warningFlags != 0)

+  {

+    (*OutStream) << "Warnings: ";

+    (*OutStream) << endl;

+    (*OutStream) << GetOpenArcErrorMessage(warningFlags);

+    (*OutStream) << endl;

+    NumOpenArcWarnings++;

+    ThereIsWarningInCurrent = true;

+  }

+

+  if (warnings && wcslen(warnings) != 0)

+  {

+    (*OutStream) << "Warnings: ";

+    (*OutStream) << endl;

+    (*OutStream) << warnings;

+    (*OutStream) << endl;

+    NumOpenArcWarnings++;

+    ThereIsWarningInCurrent = true;

+  }

+

+  (*OutStream) << endl;

+  return S_OK;

+}

   

 HRESULT CExtractCallbackConsole::ThereAreNoFiles()

 {

@@ -201,28 +330,54 @@
   if (result == S_OK)

   {

     (*OutStream) << endl;

-    if (NumFileErrorsInCurrentArchive == 0)

+

+    if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent)

+    {

+      if (ThereIsWarningInCurrent)

+        NumArcsWithWarnings++;

+      else

+        NumOkArcs++;

       (*OutStream) << kEverythingIsOk << endl;

+    }

     else

     {

-      NumArchiveErrors++;

-      (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;

+      NumArcsWithError++;

+      if (NumFileErrorsInCurrent != 0)

+        (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl;

     }

+    return S_OK;

   }

-  if (result == S_OK)

-    return result;

-  NumArchiveErrors++;

+  

+  NumArcsWithError++;

   if (result == E_ABORT || result == ERROR_DISK_FULL)

     return result;

   (*OutStream) << endl << kError;

   if (result == E_OUTOFMEMORY)

     (*OutStream) << kMemoryExceptionMessage;

   else

-  {

-    UString message;

-    NError::MyFormatMessage(result, message);

-    (*OutStream) << message;

-  }

+    (*OutStream) << NError::MyFormatMessage(result);

   (*OutStream) << endl;

   return S_OK;

 }

+

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

+}

diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
old mode 100755
new mode 100644
index 7086527..cefa2c2
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -3,11 +3,15 @@
 #ifndef __EXTRACTCALLBACKCONSOLE_H

 #define __EXTRACTCALLBACKCONSOLE_H

 

-#include "Common/MyString.h"

-#include "Common/StdOutStream.h"

+#include "../../../Common/MyString.h"

+#include "../../../Common/StdOutStream.h"

+

 #include "../../Common/FileStreams.h"

+

 #include "../../IPassword.h"

+

 #include "../../Archive/IArchive.h"

+

 #include "../Common/ArchiveExtractCallback.h"

 

 class CExtractCallbackConsole:

@@ -40,8 +44,13 @@
 

   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

@@ -53,19 +62,36 @@
 

   #endif

   

-  UInt64 NumArchives;

-  UInt64 NumArchiveErrors;

+  UInt64 NumTryArcs;

+  bool ThereIsErrorInCurrent;

+  bool ThereIsWarningInCurrent;

+

+  UInt64 NumCantOpenArcs;

+  UInt64 NumOkArcs;

+  UInt64 NumArcsWithError;

+  UInt64 NumArcsWithWarnings;

+

+  UInt64 NumProblemArcsLevs;

+  UInt64 NumOpenArcErrors;

+  UInt64 NumOpenArcWarnings;

+  

   UInt64 NumFileErrors;

-  UInt64 NumFileErrorsInCurrentArchive;

+  UInt64 NumFileErrorsInCurrent;

 

   CStdOutStream *OutStream;

 

   void Init()

   {

-    NumArchives = 0;

-    NumArchiveErrors = 0;

+    NumTryArcs = 0;

+    NumOkArcs = 0;

+    NumCantOpenArcs = 0;

+    NumArcsWithError = 0;

+    NumArcsWithWarnings = 0;

+

+    NumOpenArcErrors = 0;

+    NumOpenArcWarnings = 0;

     NumFileErrors = 0;

-    NumFileErrorsInCurrentArchive = 0;

+    NumFileErrorsInCurrent = 0;

   }

 

 };

diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
new file mode 100644
index 0000000..a9e62c2
--- /dev/null
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -0,0 +1,274 @@
+// HashCon.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/ErrorMsg.h"

+

+#include "ConsoleClose.h"

+#include "HashCon.h"

+

+static const wchar_t *kEmptyFileAlias = L"[Content]";

+

+static const char *kScanningMessage = "Scanning";

+

+HRESULT CHashCallbackConsole::CheckBreak()

+{

+  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;

+}

+

+HRESULT CHashCallbackConsole::StartScanning()

+{

+  (*OutStream) << kScanningMessage;

+  return CheckBreak();

+}

+

+HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)

+{

+  return CheckBreak();

+}

+

+HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)

+{

+  return CanNotFindError_Base(name, systemError);

+}

+

+HRESULT CHashCallbackConsole::FinishScanning()

+{

+  (*OutStream) << endl << endl;

+  return CheckBreak();

+}

+

+HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */)

+{

+  return CheckBreak();

+}

+

+HRESULT CHashCallbackConsole::SetTotal(UInt64 size)

+{

+  if (EnablePercents)

+    m_PercentPrinter.SetTotal(size);

+  return CheckBreak();

+}

+

+HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)

+{

+  if (completeValue && EnablePercents)

+  {

+    m_PercentPrinter.SetRatio(*completeValue);

+    m_PercentPrinter.PrintRatio();

+  }

+  return CheckBreak();

+}

+

+static void AddMinuses(AString &s, unsigned num)

+{

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

+    s += '-';

+}

+

+static void SetSpaces(char *s, int num)

+{

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

+    s[i] = ' ';

+}

+

+static void SetSpacesAndNul(char *s, int num)

+{

+  SetSpaces(s, num);

+  s[num] = 0;

+}

+

+static void AddSpaces(UString &s, int num)

+{

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

+    s += ' ';

+}

+

+static const int kSizeField_Len = 13;

+static const int kNameField_Len = 12;

+

+static unsigned GetColumnWidth(unsigned digestSize)

+{

+  unsigned width = digestSize * 2;

+  const unsigned kMinColumnWidth = 8;

+  return width < kMinColumnWidth ? kMinColumnWidth: width;

+}

+

+void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)

+{

+  AString s;

+  for (unsigned i = 0; i < hashers.Size(); i++)

+  {

+    const CHasherState &h = hashers[i];

+    AddMinuses(s, GetColumnWidth(h.DigestSize));

+    s += ' ';

+  }

+  AddMinuses(s, kSizeField_Len);

+  s += "  ";

+  AddMinuses(s, kNameField_Len);

+  m_PercentPrinter.PrintString(s);

+  m_PercentPrinter.PrintNewLine();

+}

+

+HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)

+{

+  UString s;

+  FOR_VECTOR (i, hb.Hashers)

+  {

+    const CHasherState &h = hb.Hashers[i];

+    s += h.Name;

+    AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1);

+  }

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

+}

+

+HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, 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;

+}

+

+HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)

+{

+  m_FileName = name;

+  return CheckBreak();

+}

+

+void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,

+    const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)

+{

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

+  }

+  char s[64];

+  s[0] = 0;

+  char *p = s;

+  if (showHash && fileSize != 0)

+  {

+    p = s + 32;

+    ConvertUInt64ToString(fileSize, p);

+    int numSpaces = kSizeField_Len - (int)strlen(p);

+    if (numSpaces > 0)

+    {

+      p -= numSpaces;

+      SetSpaces(p, numSpaces);

+    }

+  }

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

+}

+

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

+}

+

+static const char *k_DigestTitles[] =

+{

+    " :"

+  , " for data:              "

+  , " for data and names:    "

+  , " for streams and names: "

+};

+

+static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned 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";

+}

+

+

+void PrintHashStat(CStdOutStream &p, const CHashBundle &hb)

+{

+  FOR_VECTOR (i, hb.Hashers)

+  {

+    const CHasherState &h = hb.Hashers[i];

+    p << "\n";

+    PrintSum(p, h, k_HashCalc_Index_DataSum);

+    if (hb.NumFiles != 1 || hb.NumDirs != 0)

+      PrintSum(p, h, k_HashCalc_Index_NamesSum);

+    if (hb.NumAltStreams != 0)

+      PrintSum(p, h, k_HashCalc_Index_StreamsSum);

+  }

+}

+

+void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value)

+{

+  char s[32];

+  s[0] = ':';

+  s[1] = ' ';

+  ConvertUInt64ToString(value, s + 2);

+  m_PercentPrinter.PrintString(name);

+  m_PercentPrinter.PrintString(s);

+  m_PercentPrinter.PrintNewLine();

+}

+

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

+  

+  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("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
new file mode 100644
index 0000000..0e7469d
--- /dev/null
+++ b/CPP/7zip/UI/Console/HashCon.h
@@ -0,0 +1,26 @@
+// HashCon.h

+

+#ifndef __HASH_CON_H

+#define __HASH_CON_H

+

+#include "../Common/HashCalc.h"

+

+#include "UpdateCallbackConsole.h"

+

+class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase

+{

+  UString m_FileName;

+

+  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:

+  ~CHashCallbackConsole() { }

+

+  INTERFACE_IHashCallbackUI(;)

+};

+

+void PrintHashStat(CStdOutStream &stdStream, const CHashBundle &hb);

+

+#endif

diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
old mode 100755
new mode 100644
index 298adbd..dbbdeae
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -2,17 +2,16 @@
 

 #include "StdAfx.h"

 

-#include "Common/IntToString.h"

-#include "Common/MyCom.h"

-#include "Common/StdOutStream.h"

-#include "Common/StringConvert.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/MyCom.h"

+#include "../../../Common/StdOutStream.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/UTFConvert.h"

 

-#include "Windows/Error.h"

-#include "Windows/FileDir.h"

-#include "Windows/PropVariant.h"

-#include "Windows/PropVariantConversions.h"

-

-#include "../../Archive/IArchive.h"

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/PropVariant.h"

+#include "../../../Windows/PropVariantConv.h"

 

 #include "../Common/OpenArchive.h"

 #include "../Common/PropIDUtils.h"

@@ -22,88 +21,131 @@
 #include "OpenCallbackConsole.h"

 

 using namespace NWindows;

+using namespace NCOM;

 

-struct CPropIdToName

+

+

+static const char *kPropIdToName[] =

 {

-  PROPID PropID;

-  const wchar_t *Name;

-};

-

-static const CPropIdToName kPropIdToName[] =

-{

-  { kpidPath, L"Path" },

-  { kpidName, L"Name" },

-  { kpidIsDir, L"Folder" },

-  { kpidSize, L"Size" },

-  { kpidPackSize, L"Packed Size" },

-  { kpidAttrib, L"Attributes" },

-  { kpidCTime, L"Created" },

-  { kpidATime, L"Accessed" },

-  { kpidMTime, L"Modified" },

-  { kpidSolid, L"Solid" },

-  { kpidCommented, L"Commented" },

-  { kpidEncrypted, L"Encrypted" },

-  { kpidSplitBefore, L"Split Before" },

-  { kpidSplitAfter, L"Split After" },

-  { kpidDictionarySize, L"Dictionary Size" },

-  { kpidCRC, L"CRC" },

-  { kpidType, L"Type" },

-  { kpidIsAnti, L"Anti" },

-  { kpidMethod, L"Method" },

-  { kpidHostOS, L"Host OS" },

-  { kpidFileSystem, L"File System" },

-  { kpidUser, L"User" },

-  { kpidGroup, L"Group" },

-  { kpidBlock, L"Block" },

-  { kpidComment, L"Comment" },

-  { kpidPosition, L"Position" },

-  { kpidPrefix, L"Prefix" },

-  { kpidNumSubDirs, L"Folders" },

-  { kpidNumSubFiles, L"Files" },

-  { kpidUnpackVer, L"Version" },

-  { kpidVolume, L"Volume" },

-  { kpidIsVolume, L"Multivolume" },

-  { kpidOffset, L"Offset" },

-  { kpidLinks, L"Links" },

-  { kpidNumBlocks, L"Blocks" },

-  { kpidNumVolumes, L"Volumes" },

-

-  { kpidBit64, L"64-bit" },

-  { kpidBigEndian, L"Big-endian" },

-  { kpidCpu, L"CPU" },

-  { kpidPhySize, L"Physical Size" },

-  { kpidHeadersSize, L"Headers Size" },

-  { kpidChecksum, L"Checksum" },

-  { kpidCharacts, L"Characteristics" },

-  { kpidVa, L"Virtual Address" },

-  { kpidId, L"ID" },

-  { kpidShortName, L"Short Name" },

-  { kpidCreatorApp, L"Creator Application"},

-  { kpidSectorSize, L"Sector Size" },

-  { kpidPosixAttrib, L"Mode" },

-  { kpidLink, L"Link" },

-  { kpidError, L"Error" },

-

-  { kpidTotalSize, L"Total Size" },

-  { kpidFreeSpace, L"Free Space" },

-  { kpidClusterSize, L"Cluster Size" },

-  { kpidVolumeName, L"Label" }

+    "0"

+  , "1"

+  , "2"

+  , "Path"

+  , "Name"

+  , "Extension"

+  , "Folder"

+  , "Size"

+  , "Packed Size"

+  , "Attributes"

+  , "Created"

+  , "Accessed"

+  , "Modified"

+  , "Solid"

+  , "Commented"

+  , "Encrypted"

+  , "Split Before"

+  , "Split After"

+  , "Dictionary Size"

+  , "CRC"

+  , "Type"

+  , "Anti"

+  , "Method"

+  , "Host OS"

+  , "File System"

+  , "User"

+  , "Group"

+  , "Block"

+  , "Comment"

+  , "Position"

+  , "Path Prefix"

+  , "Folders"

+  , "Files"

+  , "Version"

+  , "Volume"

+  , "Multivolume"

+  , "Offset"

+  , "Links"

+  , "Blocks"

+  , "Volumes"

+  , "Time Type"

+  , "64-bit"

+  , "Big-endian"

+  , "CPU"

+  , "Physical Size"

+  , "Headers Size"

+  , "Checksum"

+  , "Characteristics"

+  , "Virtual Address"

+  , "ID"

+  , "Short Name"

+  , "Creator Application"

+  , "Sector Size"

+  , "Mode"

+  , "Symbolic Link"

+  , "Error"

+  , "Total Size"

+  , "Free Space"

+  , "Cluster Size"

+  , "Label"

+  , "Local Name"

+  , "Provider"

+  , "NT Security"

+  , "Alternate Stream"

+  , "Aux"

+  , "Deleted"

+  , "Tree"

+  , "SHA-1"

+  , "SHA-256"

+  , "Error Type"

+  , "Errors"

+  , "Errors"

+  , "Warnings"

+  , "Warning"

+  , "Streams"

+  , "Alternate Streams"

+  , "Alternate Streams Size"

+  , "Virtual Size"

+  , "Unpack Size"

+  , "Total Physical Size"

+  , "Volume Index"

+  , "SubType"

+  , "Short Comment"

+  , "Code Page"

+  , "Is not archive type"

+  , "Physical Size can't be detected"

+  , "Zeros Tail Is Allowed"

+  , "Tail Size"

+  , "Embedded Stub Size"

+  , "Link"

+  , "Hard Link"

+  , "iNode"

+  , "Stream ID"

 };

 

 static const char kEmptyAttribChar = '.';

 

 static const char *kListing = "Listing archive: ";

-static const wchar_t *kFilesMessage = L"files";

-static const wchar_t *kDirsMessage = L"folders";

 

-static void GetAttribString(DWORD wa, bool isDir, char *s)

+static const char *kString_Files = "files";

+static const char *kString_Dirs = "folders";

+static const char *kString_AltStreams = "alternate streams";

+static const char *kString_Streams = "streams";

+

+static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)

 {

-  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar;

-  s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;

-  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;

-  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;

-  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;

-  s[5] = '\0';

+  if (isDir)

+    wa |= FILE_ATTRIBUTE_DIRECTORY;

+  if (allAttribs)

+  {

+    ConvertWinAttribToString(s, wa);

+    return;

+  }

+  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar;

+  s[1] = ((wa & FILE_ATTRIBUTE_READONLY)  != 0) ? 'R': kEmptyAttribChar;

+  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN)    != 0) ? 'H': kEmptyAttribChar;

+  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM)    != 0) ? 'S': kEmptyAttribChar;

+  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE)   != 0) ? 'A': kEmptyAttribChar;

+  s[5] = 0;

 }

 

 enum EAdjustment

@@ -116,7 +158,9 @@
 struct CFieldInfo

 {

   PROPID PropID;

-  UString Name;

+  bool IsRawProp;

+  UString NameU;

+  AString NameA;

   EAdjustment TitleAdjustment;

   EAdjustment TextAdjustment;

   int PrefixSpacesWidth;

@@ -126,61 +170,177 @@
 struct CFieldInfoInit

 {

   PROPID PropID;

-  const wchar_t *Name;

+  const char *Name;

   EAdjustment TitleAdjustment;

   EAdjustment TextAdjustment;

   int PrefixSpacesWidth;

   int Width;

 };

 

-static CFieldInfoInit kStandardFieldTable[] =

+static const CFieldInfoInit kStandardFieldTable[] =

 {

-  { kpidMTime, L"   Date      Time", kLeft, kLeft, 0, 19 },

-  { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 },

-  { kpidSize, L"Size", kRight, kRight, 1, 12 },

-  { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 },

-  { kpidPath, L"Name", kLeft, kLeft, 2, 24 }

+  { kpidMTime, "   Date      Time", kLeft, kLeft, 0, 19 },

+  { kpidAttrib, "Attr", kRight, kCenter, 1, 5 },

+  { kpidSize, "Size", kRight, kRight, 1, 12 },

+  { kpidPackSize, "Compressed", kRight, kRight, 1, 12 },

+  { kpidPath, "Name", kLeft, kLeft, 2, 24 }

 };

 

+const int kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width

+static const char *g_Spaces =

+"                                " ;

+

 static void PrintSpaces(int numSpaces)

 {

-  for (int i = 0; i < numSpaces; i++)

-    g_StdOut << ' ';

+  if (numSpaces > 0 && numSpaces <= kNumSpacesMax)

+    g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);

 }

 

-static void PrintString(EAdjustment adjustment, int width, const UString &textString)

+static void PrintSpacesToString(char *dest, int numSpaces)

 {

-  const int numSpaces = width - textString.Length();

+  int i;

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

+    dest[i] = ' ';

+  dest[i] = 0;

+}

+

+static void PrintString(EAdjustment adj, int width, const UString &textString)

+{

+  const int numSpaces = width - textString.Len();

   int numLeftSpaces = 0;

-  switch (adjustment)

+  switch (adj)

   {

-    case kLeft:

-      numLeftSpaces = 0;

-      break;

-    case kCenter:

-      numLeftSpaces = numSpaces / 2;

-      break;

-    case kRight:

-      numLeftSpaces = numSpaces;

-      break;

+    case kLeft:   numLeftSpaces = 0; break;

+    case kCenter: numLeftSpaces = numSpaces / 2; break;

+    case kRight:  numLeftSpaces = numSpaces; break;

   }

   PrintSpaces(numLeftSpaces);

   g_StdOut << textString;

   PrintSpaces(numSpaces - numLeftSpaces);

 }

 

+static void PrintString(EAdjustment adj, int width, const char *textString)

+{

+  const int numSpaces = width - (int)strlen(textString);

+  int numLeftSpaces = 0;

+  switch (adj)

+  {

+    case kLeft:   numLeftSpaces = 0; break;

+    case kCenter: numLeftSpaces = numSpaces / 2; break;

+    case kRight:  numLeftSpaces = numSpaces; break;

+  }

+  PrintSpaces(numLeftSpaces);

+  g_StdOut << textString;

+  PrintSpaces(numSpaces - numLeftSpaces);

+}

+

+static void PrintStringToString(char *dest, EAdjustment adj, int width, const char *textString)

+{

+  int len = (int)strlen(textString);

+  const int numSpaces = width - len;

+  int numLeftSpaces = 0;

+  switch (adj)

+  {

+    case kLeft:   numLeftSpaces = 0; break;

+    case kCenter: numLeftSpaces = numSpaces / 2; break;

+    case kRight:  numLeftSpaces = numSpaces; break;

+  }

+  PrintSpacesToString(dest, numLeftSpaces);

+  if (numLeftSpaces > 0)

+    dest += numLeftSpaces;

+  memcpy(dest, textString, len);

+  dest += len;

+  PrintSpacesToString(dest, numSpaces - numLeftSpaces);

+}

+

+struct CListUInt64Def

+{

+  UInt64 Val;

+  bool Def;

+

+  CListUInt64Def(): Val(0), Def(false) {}

+  void Add(UInt64 v) { Val += v; Def = true; }

+  void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); }

+};

+

+struct CListFileTimeDef

+{

+  FILETIME Val;

+  bool Def;

+

+  CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; }

+  void Update(const CListFileTimeDef &t)

+  {

+    if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0))

+    {

+      Val = t.Val;

+      Def = true;

+    }

+  }

+};

+

+struct CListStat

+{

+  CListUInt64Def Size;

+  CListUInt64Def PackSize;

+  CListFileTimeDef MTime;

+  UInt64 NumFiles;

+

+  CListStat(): NumFiles(0) {}

+  void Update(const CListStat &stat)

+  {

+    Size.Add(stat.Size);

+    PackSize.Add(stat.PackSize);

+    MTime.Update(stat.MTime);

+    NumFiles += stat.NumFiles;

+  }

+  void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }

+};

+

+struct CListStat2

+{

+  CListStat MainFiles;

+  CListStat AltStreams;

+  UInt64 NumDirs;

+

+  CListStat2(): NumDirs(0) {}

+

+  void Update(const CListStat2 &stat)

+  {

+    MainFiles.Update(stat.MainFiles);

+    AltStreams.Update(stat.AltStreams);

+    NumDirs += stat.NumDirs;

+  }

+  const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; }

+  CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; }

+};

+

 class CFieldPrinter

 {

   CObjectVector<CFieldInfo> _fields;

+

+  void AddProp(BSTR name, PROPID propID, bool isRawProp);

 public:

-  void Clear() { _fields.Clear(); }

+  const CArc *Arc;

+  bool TechMode;

+  UString FilePath;

+  AString TempAString;

+  UString TempWString;

+  bool IsFolder;

+

+  AString LinesString;

+

+  void Clear() { _fields.Clear(); LinesString.Empty(); }

   void Init(const CFieldInfoInit *standardFieldTable, int numItems);

-  HRESULT Init(IInArchive *archive);

+

+  HRESULT AddMainProps(IInArchive *archive);

+  HRESULT AddRawProps(IArchiveGetRawProps *getRawProps);

+  

   void PrintTitle();

   void PrintTitleLines();

-  HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode);

-  HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,

-      const UInt64 *size, const UInt64 *compressedSize);

+  HRESULT PrintItemInfo(UInt32 index, const CListStat &stat);

+  void PrintSum(const CListStat &stat, UInt64 numDirs, const char *str);

+  void PrintSum(const CListStat2 &stat);

 };

 

 void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)

@@ -188,36 +348,70 @@
   Clear();

   for (int i = 0; i < numItems; i++)

   {

-    CFieldInfo fieldInfo;

-    const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];

-    fieldInfo.PropID = fieldInfoInit.PropID;

-    fieldInfo.Name = fieldInfoInit.Name;

-    fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;

-    fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;

-    fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;

-    fieldInfo.Width = fieldInfoInit.Width;

-    _fields.Add(fieldInfo);

+    CFieldInfo &f = _fields.AddNew();

+    const CFieldInfoInit &fii = standardFieldTable[i];

+    f.PropID = fii.PropID;

+    f.IsRawProp = false;

+    f.NameA = fii.Name;

+    f.TitleAdjustment = fii.TitleAdjustment;

+    f.TextAdjustment = fii.TextAdjustment;

+    f.PrefixSpacesWidth = fii.PrefixSpacesWidth;

+    f.Width = fii.Width;

+

+    int k;

+    for (k = 0; k < fii.PrefixSpacesWidth; k++)

+      LinesString += ' ';

+    for (k = 0; k < fii.Width; k++)

+      LinesString += '-';

   }

 }

 

-static UString GetPropName(PROPID propID, BSTR name)

+static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU)

 {

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

+  if (propID < ARRAY_SIZE(kPropIdToName))

   {

-    const CPropIdToName &propIdToName = kPropIdToName[i];

-    if (propIdToName.PropID == propID)

-      return propIdToName.Name;

+    nameA = kPropIdToName[propID];

+    return;

   }

   if (name)

-    return name;

-  wchar_t s[16];

-  ConvertUInt32ToString(propID, s);

-  return s;

+    nameU = name;

+  else

+  {

+    char s[16];

+    ConvertUInt32ToString(propID, s);

+    nameA = s;

+  }

 }

 

-HRESULT CFieldPrinter::Init(IInArchive *archive)

+void CFieldPrinter::AddProp(BSTR name, PROPID propID, bool isRawProp)

 {

-  Clear();

+  CFieldInfo f;

+  f.PropID = propID;

+  f.IsRawProp = isRawProp;

+  GetPropName(propID, name, f.NameA, f.NameU);

+  f.NameU += L" = ";

+  if (!f.NameA.IsEmpty())

+    f.NameA += " = ";

+  else

+  {

+    const UString &s = f.NameU;

+    AString sA;

+    unsigned i;

+    for (i = 0; i < s.Len(); i++)

+    {

+      wchar_t c = s[i];

+      if (c >= 0x80)

+        break;

+      sA += (char)c;

+    }

+    if (i == s.Len())

+      f.NameA = sA;

+  }

+  _fields.Add(f);

+}

+

+HRESULT CFieldPrinter::AddMainProps(IInArchive *archive)

+{

   UInt32 numProps;

   RINOK(archive->GetNumberOfProperties(&numProps));

   for (UInt32 i = 0; i < numProps; i++)

@@ -226,64 +420,80 @@
     PROPID propID;

     VARTYPE vt;

     RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));

-    CFieldInfo fieldInfo;

-    fieldInfo.PropID = propID;

-    fieldInfo.Name = GetPropName(propID, name);

-    _fields.Add(fieldInfo);

+    AddProp(name, propID, false);

+  }

+  return S_OK;

+}

+

+HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps)

+{

+  UInt32 numProps;

+  RINOK(getRawProps->GetNumRawProps(&numProps));

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    CMyComBSTR name;

+    PROPID propID;

+    RINOK(getRawProps->GetRawPropInfo(i, &name, &propID));

+    AddProp(name, propID, true);

   }

   return S_OK;

 }

 

 void CFieldPrinter::PrintTitle()

 {

-  for (int i = 0; i < _fields.Size(); i++)

+  FOR_VECTOR (i, _fields)

   {

-    const CFieldInfo &fieldInfo = _fields[i];

-    PrintSpaces(fieldInfo.PrefixSpacesWidth);

-    PrintString(fieldInfo.TitleAdjustment,

-      ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);

+    const CFieldInfo &f = _fields[i];

+    PrintSpaces(f.PrefixSpacesWidth);

+    PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA);

   }

 }

 

 void CFieldPrinter::PrintTitleLines()

 {

-  for (int i = 0; i < _fields.Size(); i++)

+  g_StdOut << LinesString;

+}

+

+static void PrintTime(char *dest, const FILETIME *ft)

+{

+  *dest = 0;

+  if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0)

+    return;

+  FILETIME locTime;

+  if (!FileTimeToLocalFileTime(ft, &locTime))

+    throw 20121211;

+  ConvertFileTimeToString(locTime, dest, true, true);

+}

+

+#ifndef _SFX

+

+static inline char GetHex(Byte value)

+{

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+static void HexToString(char *dest, const Byte *data, UInt32 size)

+{

+  for (UInt32 i = 0; i < size; i++)

   {

-    const CFieldInfo &fieldInfo = _fields[i];

-    PrintSpaces(fieldInfo.PrefixSpacesWidth);

-    for (int i = 0; i < fieldInfo.Width; i++)

-      g_StdOut << '-';

+    Byte b = data[i];

+    dest[0] = GetHex((Byte)((b >> 4) & 0xF));

+    dest[1] = GetHex((Byte)(b & 0xF));

+    dest += 2;

   }

+  *dest = 0;

 }

 

+#endif

 

-static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)

-{

-  return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);

-}

+#define MY_ENDL '\n'

 

-static const char *kEmptyTimeString = "                   ";

-static void PrintTime(const NCOM::CPropVariant &prop)

+HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)

 {

-  if (prop.vt != VT_FILETIME)

-    throw "incorrect item";

-  if (IsFileTimeZero(&prop.filetime))

-    g_StdOut << kEmptyTimeString;

-  else

-  {

-    FILETIME localFileTime;

-    if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime))

-      throw "FileTimeToLocalFileTime error";

-    char s[32];

-    if (ConvertFileTimeToString(localFileTime, s, true, true))

-      g_StdOut << s;

-    else

-      g_StdOut << kEmptyTimeString;

-  }

-}

+  char temp[128];

+  size_t tempPos = 0;

 

-HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)

-{

+  bool techMode = this->TechMode;

   /*

   if (techMode)

   {

@@ -292,162 +502,408 @@
     g_StdOut << endl;

   }

   */

-  for (int i = 0; i < _fields.Size(); i++)

+  FOR_VECTOR (i, _fields)

   {

-    const CFieldInfo &fieldInfo = _fields[i];

-    if (!techMode)

-      PrintSpaces(fieldInfo.PrefixSpacesWidth);

+    const CFieldInfo &f = _fields[i];

 

-    NCOM::CPropVariant prop;

-    if (fieldInfo.PropID == kpidPath)

+    if (!techMode)

     {

-      UString s;

-      RINOK(arc.GetItemPath(index, s));

-      prop = s;

+      PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth);

+      tempPos += f.PrefixSpacesWidth;

     }

-    else

-    {

-      RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));

-    }

+

     if (techMode)

     {

-      g_StdOut << fieldInfo.Name << " = ";

+      if (!f.NameA.IsEmpty())

+        g_StdOut << f.NameA;

+      else

+        g_StdOut << f.NameU;

     }

-    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;

-    if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))

-    {

-      UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;

-      bool isFolder;

-      RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));

-      char s[8];

-      GetAttribString(attrib, isFolder, s);

-      g_StdOut << s;

-    }

-    else if (prop.vt == VT_EMPTY)

+    

+    if (f.PropID == kpidPath)

     {

       if (!techMode)

-        PrintSpaces(width);

-    }

-    else if (fieldInfo.PropID == kpidMTime)

-    {

-      PrintTime(prop);

-    }

-    else if (prop.vt == VT_BSTR)

-    {

+        g_StdOut << temp;

+      g_StdOut.PrintUString(FilePath, TempAString);

       if (techMode)

-        g_StdOut << prop.bstrVal;

-      else

-        PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);

+        g_StdOut << MY_ENDL;

+      continue;

+    }

+

+    int width = f.Width;

+    

+    if (f.IsRawProp)

+    {

+      #ifndef _SFX

+      

+      const void *data;

+      UInt32 dataSize;

+      UInt32 propType;

+      RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType));

+      

+      if (dataSize != 0)

+      {

+        bool needPrint = true;

+        

+        if (f.PropID == kpidNtSecure)

+        {

+          if (propType != NPropDataType::kRaw)

+            return E_FAIL;

+          #ifndef _SFX

+          ConvertNtSecureToString((const Byte *)data, dataSize, TempAString);

+          g_StdOut << TempAString;

+          needPrint = false;

+          #endif

+        }

+        else if (f.PropID == kpidNtReparse)

+        {

+          UString s;

+          if (ConvertNtReparseToString((const Byte *)data, dataSize, s))

+          {

+            needPrint = false;

+            g_StdOut << s;

+          }

+        }

+      

+        if (needPrint)

+        {

+          if (propType != NPropDataType::kRaw)

+            return E_FAIL;

+          

+          const UInt32 kMaxDataSize = 64;

+          

+          if (dataSize > kMaxDataSize)

+          {

+            g_StdOut << "data:";

+            g_StdOut << dataSize;

+          }

+          else

+          {

+            char hexStr[kMaxDataSize * 2 + 4];

+            HexToString(hexStr, (const Byte *)data, dataSize);

+            g_StdOut << hexStr;

+          }

+        }

+      }

+      

+      #endif

     }

     else

     {

-      UString s = ConvertPropertyToString(prop, fieldInfo.PropID);

-      s.Replace(wchar_t(0xA), L' ');

-      s.Replace(wchar_t(0xD), L' ');

-

-      if (techMode)

-        g_StdOut << s;

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

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

+        if (techMode)

+          g_StdOut << temp + tempPos;

+        else

+          tempPos += strlen(temp + tempPos);

+      }

+      else if (prop.vt == VT_EMPTY)

+      {

+        if (!techMode)

+        {

+          PrintSpacesToString(temp + tempPos, width);

+          tempPos += width;

+        }

+      }

+      else if (prop.vt == VT_FILETIME)

+      {

+        PrintTime(temp + tempPos, &prop.filetime);

+        if (techMode)

+          g_StdOut << temp + tempPos;

+        else

+        {

+          size_t len = strlen(temp + tempPos);

+          tempPos += len;

+          if (len < (unsigned)f.Width)

+          {

+            len = (size_t)f.Width - len;

+            PrintSpacesToString(temp + tempPos, (int)len);

+            tempPos += len;

+          }

+        }

+      }

+      else if (prop.vt == VT_BSTR)

+      {

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

+      }

       else

-        PrintString(fieldInfo.TextAdjustment, width, s);

+      {

+        char s[64];

+        ConvertPropertyToShortString(s, prop, f.PropID);

+        if (techMode)

+          g_StdOut << s;

+        else

+        {

+          PrintStringToString(temp + tempPos, f.TextAdjustment, width, s);

+          tempPos += strlen(temp + tempPos);

+        }

+      }

     }

     if (techMode)

-      g_StdOut << endl;

+      g_StdOut << MY_ENDL;

   }

+  g_StdOut << MY_ENDL;

   return S_OK;

 }

 

-static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)

+static void PrintNumber(EAdjustment adj, int width, const CListUInt64Def &value)

 {

-  wchar_t textString[32] = { 0 };

-  if (value != NULL)

-    ConvertUInt64ToString(*value, textString);

-  PrintString(adjustment, width, textString);

+  wchar_t s[32];

+  s[0] = 0;

+  if (value.Def)

+    ConvertUInt64ToString(value.Val, s);

+  PrintString(adj, width, s);

 }

 

-

-HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,

-    const UInt64 *size, const UInt64 *compressedSize)

+static void PrintNumberAndString(AString &s, UInt64 value, const char *text)

 {

-  for (int i = 0; i < _fields.Size(); i++)

+  char t[32];

+  ConvertUInt64ToString(value, t);

+  s += t;

+  s += ' ';

+  s += text;

+}

+

+void CFieldPrinter::PrintSum(const CListStat &stat, UInt64 numDirs, const char *str)

+{

+  FOR_VECTOR (i, _fields)

   {

-    const CFieldInfo &fieldInfo = _fields[i];

-    PrintSpaces(fieldInfo.PrefixSpacesWidth);

-    NCOM::CPropVariant prop;

-    if (fieldInfo.PropID == kpidSize)

-      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);

-    else if (fieldInfo.PropID == kpidPackSize)

-      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);

-    else if (fieldInfo.PropID == kpidPath)

+    const CFieldInfo &f = _fields[i];

+    PrintSpaces(f.PrefixSpacesWidth);

+    if (f.PropID == kpidSize)

+      PrintNumber(f.TextAdjustment, f.Width, stat.Size);

+    else if (f.PropID == kpidPackSize)

+      PrintNumber(f.TextAdjustment, f.Width, stat.PackSize);

+    else if (f.PropID == kpidMTime)

     {

-      wchar_t textString[32];

-      ConvertUInt64ToString(numFiles, textString);

-      UString temp = textString;

-      temp += L" ";

-      temp += kFilesMessage;

-      temp += L", ";

-      ConvertUInt64ToString(numDirs, textString);

-      temp += textString;

-      temp += L" ";

-      temp += kDirsMessage;

-      PrintString(fieldInfo.TextAdjustment, 0, temp);

+      char s[64];

+      s[0] = 0;

+      if (stat.MTime.Def)

+        PrintTime(s, &stat.MTime.Val);

+      PrintString(f.TextAdjustment, f.Width, s);

+    }

+    else if (f.PropID == kpidPath)

+    {

+      AString s;

+      PrintNumberAndString(s, stat.NumFiles, str);

+      if (numDirs != 0)

+      {

+        s += ", ";

+        PrintNumberAndString(s, numDirs, kString_Dirs);

+      }

+      PrintString(f.TextAdjustment, 0, s);

     }

     else

-      PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");

+      PrintString(f.TextAdjustment, f.Width, L"");

   }

+  g_StdOut << endl;

+}

+

+void CFieldPrinter::PrintSum(const CListStat2 &stat2)

+{

+  PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files);

+  if (stat2.AltStreams.NumFiles != 0)

+  {

+    PrintSum(stat2.AltStreams, 0, kString_AltStreams);;

+    CListStat stat = stat2.MainFiles;

+    stat.Update(stat2.AltStreams);

+    PrintSum(stat, 0, kString_Streams);

+  }

+}

+

+static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value)

+{

+  value.Val = 0;

+  value.Def = false;

+  CPropVariant prop;

+  RINOK(archive->GetProperty(index, propID, &prop));

+  value.Def = ConvertPropVariantToUInt64(prop, value.Val);

   return S_OK;

 }

 

-bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)

+static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t)

 {

-  NCOM::CPropVariant prop;

-  if (archive->GetProperty(index, propID, &prop) != S_OK)

-    throw "GetPropertyValue error";

-  if (prop.vt == VT_EMPTY)

-    return false;

-  value = ConvertPropVariantToUInt64(prop);

-  return true;

+  t.Val.dwLowDateTime = 0;

+  t.Val.dwHighDateTime = 0;

+  t.Def = false;

+  CPropVariant prop;

+  RINOK(archive->GetProperty(index, kpidMTime, &prop));

+  if (prop.vt == VT_FILETIME)

+  {

+    t.Val = prop.filetime;

+    t.Def = true;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

 }

 

-static void PrintPropPair(const wchar_t *name, const wchar_t *value)

+static void PrintPropNameAndNumber(const char *name, UInt64 val)

 {

-  g_StdOut << name << " = " << value << endl;

+  g_StdOut << name << ": " << val << endl;

 }

 

-HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,

+static void PrintPropName_and_Eq(PROPID propID)

+{

+  const char *s;

+  char temp[16];

+  if (propID < ARRAY_SIZE(kPropIdToName))

+    s = kPropIdToName[propID];

+  else

+  {

+    ConvertUInt32ToString(propID, temp);

+    s = temp;

+  }

+  g_StdOut << s << " = ";

+}

+

+static void PrintPropNameAndNumber(PROPID propID, UInt64 val)

+{

+  PrintPropName_and_Eq(propID);

+  g_StdOut << val << endl;

+}

+

+static void PrintPropNameAndNumber_Signed(PROPID propID, Int64 val)

+{

+  PrintPropName_and_Eq(propID);

+  g_StdOut << val << endl;

+}

+

+static void PrintPropPair(const char *name, const wchar_t *val)

+{

+  g_StdOut << name << " = " << val << endl;

+}

+

+

+static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVariant &prop)

+{

+  UString s;

+  ConvertPropertyToString(s, prop, propID);

+  if (!s.IsEmpty())

+  {

+    AString nameA;

+    UString nameU;

+    GetPropName(propID, name, nameA, nameU);

+    if (!nameA.IsEmpty())

+      PrintPropPair(nameA, s);

+    else

+      g_StdOut << nameU << " = " << s << endl;

+  }

+}

+

+static HRESULT PrintArcProp(IInArchive *archive, PROPID propID, const wchar_t *name)

+{

+  CPropVariant prop;

+  RINOK(archive->GetArchiveProperty(propID, &prop));

+  PrintPropertyPair2(propID, name, prop);

+  return S_OK;

+}

+

+static void PrintArcTypeError(const UString &type, bool isWarning)

+{

+  g_StdOut << "Open " << (isWarning ? "Warning" : "Error")

+    << ": Can not open the file as ["

+    << type

+    << "] archive"

+    << endl;

+}

+

+int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);

+

+AString GetOpenArcErrorMessage(UInt32 errorFlags);

+

+static void PrintErrorFlags(const char *s, UInt32 errorFlags)

+{

+  g_StdOut << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;

+}

+

+static void ErrorInfo_Print(const CArcErrorInfo &er)

+{

+  if (er.AreThereErrors())

+    PrintErrorFlags("Errors:", er.GetErrorFlags());

+  if (!er.ErrorMessage.IsEmpty())

+    PrintPropPair("Error", er.ErrorMessage);

+  if (er.AreThereWarnings())

+    PrintErrorFlags("Warnings:", er.GetWarningFlags());

+  if (!er.WarningMessage.IsEmpty())

+    PrintPropPair("Warning", er.WarningMessage);

+}

+

+HRESULT ListArchives(CCodecs *codecs,

+    const CObjectVector<COpenType> &types,

+    const CIntVector &excludedFormats,

     bool stdInMode,

     UStringVector &arcPaths, UStringVector &arcPathsFull,

+    bool processAltStreams, bool showAltStreams,

     const NWildcard::CCensorNode &wildcardCensor,

     bool enableHeaders, bool techMode,

     #ifndef _NO_CRYPTO

     bool &passwordEnabled, UString &password,

     #endif

-    UInt64 &numErrors)

+    #ifndef _SFX

+    const CObjectVector<CProperty> *props,

+    #endif

+    UInt64 &numErrors,

+    UInt64 &numWarnings)

 {

-  numErrors = 0;

-  CFieldPrinter fieldPrinter;

-  if (!techMode)

-    fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));

+  bool AllFilesAreAllowed = wildcardCensor.AreAllAllowed();

 

-  UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;

-  UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;

-  int numArcs = /* stdInMode ? 1 : */ arcPaths.Size();

-  for (int i = 0; i < numArcs; i++)

+  numErrors = 0;

+  numWarnings = 0;

+

+  CFieldPrinter fp;

+  if (!techMode)

+    fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable));

+

+  CListStat2 stat2;

+  

+  CBoolArr skipArcs(arcPaths.Size());

+  unsigned arcIndex;

+  for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)

+    skipArcs[arcIndex] = false;

+  UInt64 numVolumes = 0;

+  UInt64 numArcs = 0;

+  UInt64 totalArcSizes = 0;

+

+  for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)

   {

-    const UString &archiveName = arcPaths[i];

+    if (skipArcs[arcIndex])

+      continue;

+    const UString &archiveName = arcPaths[arcIndex];

     UInt64 arcPackSize = 0;

     if (!stdInMode)

     {

-      NFile::NFind::CFileInfoW fi;

-      if (!fi.Find(archiveName) || fi.IsDir())

+      NFile::NFind::CFileInfo fi;

+      if (!fi.Find(us2fs(archiveName)) || fi.IsDir())

       {

         g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;

         numErrors++;

         continue;

       }

       arcPackSize = fi.Size;

+      totalArcSizes += arcPackSize;

     }

 

-    CArchiveLink archiveLink;

+    CArchiveLink arcLink;

 

     COpenCallbackConsole openCallback;

     openCallback.OutStream = &g_StdOut;

@@ -459,7 +915,24 @@
 

     #endif

 

-    HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback);

+    /*

+    CObjectVector<COptionalOpenProperties> optPropsVector;

+    COptionalOpenProperties &optProps = optPropsVector.AddNew();

+    optProps.Props = *props;

+    */

+    

+    COpenOptions options;

+    #ifndef _SFX

+    options.props = props;

+    #endif

+    options.codecs = codecs;

+    options.types = &types;

+    options.excludedFormats = &excludedFormats;

+    options.stdInMode = stdInMode;

+    options.stream = NULL;

+    options.filePath = archiveName;

+    HRESULT result = arcLink.Open2(options, &openCallback);

+

     if (result != S_OK)

     {

       if (result == E_ABORT)

@@ -472,7 +945,16 @@
           g_StdOut << "Can not open encrypted archive. Wrong password?";

         else

         #endif

-          g_StdOut << "Can not open file as archive";

+        {

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

       }

       else if (result == E_OUTOFMEMORY)

         g_StdOut << "Can't allocate required memory";

@@ -482,35 +964,76 @@
       numErrors++;

       continue;

     }

-

-    if (!stdInMode)

-    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)

     {

-      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);

-      if (index >= 0 && index > i)

+      if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+        numErrors++;

+      

+      FOR_VECTOR (r, arcLink.Arcs)

       {

-        arcPaths.Delete(index);

-        arcPathsFull.Delete(index);

-        numArcs = arcPaths.Size();

+        const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo;

+        if (!arc.WarningMessage.IsEmpty())

+          numWarnings++;

+        if (arc.AreThereWarnings())

+          numWarnings++;

+        if (arc.ErrorFormatIndex >= 0)

+          numWarnings++;

+        if (arc.AreThereErrors())

+        {

+          numErrors++;

+          // break;

+        }

+        if (!arc.ErrorMessage.IsEmpty())

+          numErrors++;

       }

     }

 

+    numArcs++;

+    numVolumes++;

+

+    if (!stdInMode)

+    {

+      numVolumes += arcLink.VolumePaths.Size();

+      totalArcSizes += arcLink.VolumesSize;

+      FOR_VECTOR (v, arcLink.VolumePaths)

+      {

+        int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);

+        if (index >= 0 && (unsigned)index > arcIndex)

+          skipArcs[index] = true;

+      }

+    }

+

+

     if (enableHeaders)

     {

       g_StdOut << endl << kListing << archiveName << endl << endl;

 

-      for (int i = 0; i < archiveLink.Arcs.Size(); i++)

+      FOR_VECTOR (r, arcLink.Arcs)

       {

-        const CArc &arc = archiveLink.Arcs[i];

+        const CArc &arc = arcLink.Arcs[r];

+        const CArcErrorInfo &er = arc.ErrorInfo;

         

         g_StdOut << "--\n";

-        PrintPropPair(L"Path", arc.Path);

-        PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);

-        if (!arc.ErrorMessage.IsEmpty())

-          PrintPropPair(L"Error", arc.ErrorMessage);

-        UInt32 numProps;

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

-        if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)

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

           {

@@ -518,35 +1041,28 @@
             PROPID propID;

             VARTYPE vt;

             RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));

-            NCOM::CPropVariant prop;

-            RINOK(archive->GetArchiveProperty(propID, &prop));

-            UString s = ConvertPropertyToString(prop, propID);

-            if (!s.IsEmpty())

-              PrintPropPair(GetPropName(propID, name), s);

+            RINOK(PrintArcProp(archive, propID, name));

           }

         }

-        if (i != archiveLink.Arcs.Size() - 1)

+        if (r != arcLink.Arcs.Size() - 1)

         {

           UInt32 numProps;

           g_StdOut << "----\n";

           if (archive->GetNumberOfProperties(&numProps) == S_OK)

           {

-            UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;

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

-              NCOM::CPropVariant prop;

+              CPropVariant prop;

               RINOK(archive->GetProperty(mainIndex, propID, &prop));

-              UString s = ConvertPropertyToString(prop, propID);

-              if (!s.IsEmpty())

-                PrintPropPair(GetPropName(propID, name), s);

+              PrintPropertyPair2(propID, name, prop);

             }

           }

         }

-        

       }

       g_StdOut << endl;

       if (techMode)

@@ -555,20 +1071,28 @@
 

     if (enableHeaders && !techMode)

     {

-      fieldPrinter.PrintTitle();

+      fp.PrintTitle();

       g_StdOut << endl;

-      fieldPrinter.PrintTitleLines();

+      fp.PrintTitleLines();

       g_StdOut << endl;

     }

 

-    const CArc &arc = archiveLink.Arcs.Back();

+    const CArc &arc = arcLink.Arcs.Back();

+    fp.Arc = &arc;

+    fp.TechMode = techMode;

     IInArchive *archive = arc.Archive;

     if (techMode)

     {

-      RINOK(fieldPrinter.Init(archive));

+      fp.Clear();

+      RINOK(fp.AddMainProps(archive));

+      if (arc.GetRawProps)

+      {

+        RINOK(fp.AddRawProps(arc.GetRawProps));

+      }

     }

-    UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;

-    UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;

+    

+    CListStat2 stat;

+    

     UInt32 numItems;

     RINOK(archive->GetNumberOfItems(&numItems));

     for (UInt32 i = 0; i < numItems; i++)

@@ -576,79 +1100,93 @@
       if (NConsoleClose::TestBreakSignal())

         return E_ABORT;

 

-      UString filePath;

-      HRESULT res = arc.GetItemPath(i, filePath);

+      HRESULT res = arc.GetItemPath2(i, fp.FilePath);

+

       if (stdInMode && res == E_INVALIDARG)

         break;

       RINOK(res);

 

-      bool isFolder;

-      RINOK(IsArchiveItemFolder(archive, i, isFolder));

-      if (!wildcardCensor.CheckPath(filePath, !isFolder))

+      if (arc.Ask_Aux)

+      {

+        bool isAux;

+        RINOK(Archive_IsItem_Aux(archive, i, isAux));

+        if (isAux)

+          continue;

+      }

+

+      bool isAltStream = false;

+      if (arc.Ask_AltStream)

+      {

+        RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));

+        if (isAltStream && !processAltStreams)

+          continue;

+      }

+

+      RINOK(Archive_IsItem_Folder(archive, i, fp.IsFolder));

+

+      if (!AllFilesAreAllowed)

+      {

+        if (!wildcardCensor.CheckPath(isAltStream, fp.FilePath, !fp.IsFolder))

+          continue;

+      }

+      

+      CListStat st;

+      

+      RINOK(GetUInt64Value(archive, i, kpidSize, st.Size));

+      RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize));

+      RINOK(GetItemMTime(archive, i, st.MTime));

+

+      if (fp.IsFolder)

+        stat.NumDirs++;

+      else

+        st.NumFiles = 1;

+      stat.GetStat(isAltStream).Update(st);

+

+      if (isAltStream && !showAltStreams)

         continue;

-      

-      fieldPrinter.PrintItemInfo(arc, i, techMode);

-      

-      UInt64 packSize, unpackSize;

-      if (!GetUInt64Value(archive, i, kpidSize, unpackSize))

-        unpackSize = 0;

-      else

-        totalUnPackSizePointer = &totalUnPackSize;

-      if (!GetUInt64Value(archive, i, kpidPackSize, packSize))

-        packSize = 0;

-      else

-        totalPackSizePointer = &totalPackSize;

-      

-      g_StdOut << endl;

-

-      if (isFolder)

-        numDirs++;

-      else

-        numFiles++;

-      totalPackSize += packSize;

-      totalUnPackSize += unpackSize;

+      RINOK(fp.PrintItemInfo(i, st));

     }

 

-    if (!stdInMode && totalPackSizePointer == 0)

+    UInt64 numStreams = stat.GetNumStreams();

+    if (!stdInMode

+        && !stat.MainFiles.PackSize.Def

+        && !stat.AltStreams.PackSize.Def)

     {

-      if (archiveLink.VolumePaths.Size() != 0)

-        arcPackSize += archiveLink.VolumesSize;

-      totalPackSize = (numFiles == 0) ? 0 : arcPackSize;

-      totalPackSizePointer = &totalPackSize;

+      if (arcLink.VolumePaths.Size() != 0)

+        arcPackSize += arcLink.VolumesSize;

+      stat.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);

     }

-    if (totalUnPackSizePointer == 0 && numFiles == 0)

-    {

-      totalUnPackSize = 0;

-      totalUnPackSizePointer = &totalUnPackSize;

-    }

+    stat.MainFiles.SetSizeDefIfNoFiles();

+    stat.AltStreams.SetSizeDefIfNoFiles();

     if (enableHeaders && !techMode)

     {

-      fieldPrinter.PrintTitleLines();

+      fp.PrintTitleLines();

       g_StdOut << endl;

-      fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);

-      g_StdOut << endl;

+      fp.PrintSum(stat);

     }

-    if (totalPackSizePointer != 0)

+

+    if (enableHeaders)

     {

-      totalPackSizePointer2 = &totalPackSize2;

-      totalPackSize2 += totalPackSize;

+      if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)

+      {

+        g_StdOut << "----------\n";

+        PrintPropPair("Path", arcLink.NonOpen_ArcPath);

+        PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);

+      }

     }

-    if (totalUnPackSizePointer != 0)

-    {

-      totalUnPackSizePointer2 = &totalUnPackSize2;

-      totalUnPackSize2 += totalUnPackSize;

-    }

-    numFiles2 += numFiles;

-    numDirs2 += numDirs;

+    stat2.Update(stat);

+    fflush(stdout);

   }

-  if (enableHeaders && !techMode && numArcs > 1)

+  if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))

   {

     g_StdOut << endl;

-    fieldPrinter.PrintTitleLines();

+    fp.PrintTitleLines();

     g_StdOut << endl;

-    fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);

+    fp.PrintSum(stat2);

     g_StdOut << endl;

-    g_StdOut << "Archives: " << numArcs << endl;

+    PrintPropNameAndNumber("Archives", numArcs);

+    PrintPropNameAndNumber("Volumes", numVolumes);

+    PrintPropNameAndNumber("Total archives size", totalArcSizes);

   }

   return S_OK;

 }

diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h
old mode 100755
new mode 100644
index 7ea02cc..dabbc2a
--- a/CPP/7zip/UI/Console/List.h
+++ b/CPP/7zip/UI/Console/List.h
@@ -3,18 +3,25 @@
 #ifndef __LIST_H

 #define __LIST_H

 

-#include "Common/Wildcard.h"

+#include "../../../Common/Wildcard.h"

+

 #include "../Common/LoadCodecs.h"

 

-HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,

+HRESULT ListArchives(CCodecs *codecs,

+    const CObjectVector<COpenType> &types,

+    const CIntVector &excludedFormats,

     bool stdInMode,

     UStringVector &archivePaths, UStringVector &archivePathsFull,

+    bool processAltStreams, bool showAltStreams,

     const NWildcard::CCensorNode &wildcardCensor,

     bool enableHeaders, bool techMode,

     #ifndef _NO_CRYPTO

     bool &passwordEnabled, UString &password,

     #endif

-    UInt64 &errors);

+    #ifndef _SFX

+    const CObjectVector<CProperty> *props,

+    #endif

+    UInt64 &errors,

+    UInt64 &numWarnings);

 

 #endif

-

diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
old mode 100755
new mode 100644
index 8946772..f092f36
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -2,24 +2,31 @@
 

 #include "StdAfx.h"

 

+#include <Psapi.h>

+

 #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)

 #include "../../../../C/Alloc.h"

 #endif

 

-#include "Common/MyInitGuid.h"

+#include "../../../Common/MyInitGuid.h"

 

-#include "Common/CommandLineParser.h"

-#include "Common/IntToString.h"

-#include "Common/MyException.h"

-#include "Common/StdOutStream.h"

-#include "Common/StringConvert.h"

-#include "Common/StringToInt.h"

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/MyException.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/StringToInt.h"

 

-#include "Windows/Error.h"

+#include "../../../Windows/ErrorMsg.h"

 #ifdef _WIN32

-#include "Windows/MemoryLock.h"

+#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"

@@ -28,23 +35,36 @@
 #endif

 

 #include "BenchCon.h"

+#include "ConsoleClose.h"

 #include "ExtractCallbackConsole.h"

 #include "List.h"

 #include "OpenCallbackConsole.h"

 #include "UpdateCallbackConsole.h"

 

+#include "HashCon.h"

+

+#ifdef PROG_VARIANT_R

+#include "../../../../C/7zVersion.h"

+#else

 #include "../../MyVersion.h"

+#endif

 

 using namespace NWindows;

 using namespace NFile;

 using namespace NCommandLineParser;

 

+#ifdef _WIN32

 HINSTANCE g_hInstance = 0;

+#endif

 extern CStdOutStream *g_StdStream;

 

 static const char *kCopyrightString = "\n7-Zip"

 #ifndef EXTERNAL_CODECS

-" (A)"

+#ifdef PROG_VARIANT_R

+" (r)"

+#else

+" (a)"

+#endif

 #endif

 

 #ifdef _WIN64

@@ -55,10 +75,10 @@
 

 static const char *kHelpString =

     "\nUsage: 7z"

-#ifdef _NO_CRYPTO

+#ifndef EXTERNAL_CODECS

+#ifdef PROG_VARIANT_R

     "r"

 #else

-#ifndef EXTERNAL_CODECS

     "a"

 #endif

 #endif

@@ -66,42 +86,45 @@
     "       [<@listfiles...>]\n"

     "\n"

     "<Commands>\n"

-    "  a: Add files to archive\n"

-    "  b: Benchmark\n"

-    "  d: Delete files from archive\n"

-    "  e: Extract files from archive (without using directory names)\n"

-    "  l: List contents of archive\n"

-//    "  l[a|t][f]: List contents of archive\n"

+    "  a : Add files to archive\n"

+    "  b : Benchmark\n"

+    "  d : Delete files from archive\n"

+    "  e : Extract files from archive (without using directory names)\n"

+    "  h : Calculate hash values for files\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"

-    "  t: Test integrity of archive\n"

-    "  u: Update files to archive\n"

-    "  x: eXtract files with full paths\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"

     "<Switches>\n"

-    "  -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"

-    "  -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"

-    "  -bd: Disable percentage indicator\n"

-    "  -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"

-    "  -m{Parameters}: set compression Method\n"

-    "  -o{Directory}: set Output directory\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"

+    "  -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"

+    "  -m{Parameters} : set compression Method\n"

+    "  -o{Directory} : set Output directory\n"

     #ifndef _NO_CRYPTO

-    "  -p{Password}: set Password\n"

+    "  -p{Password} : set Password\n"

     #endif

-    "  -r[-|0]: Recurse subdirectories\n"

-    "  -scs{UTF-8 | WIN | DOS}: set charset for list files\n"

-    "  -sfx[{name}]: Create SFX archive\n"

-    "  -si[{name}]: read data from stdin\n"

-    "  -slt: show technical information for l (List) command\n"

-    "  -so: write data to stdout\n"

-    "  -ssc[-]: set sensitive case mode\n"

-    "  -ssw: compress shared files\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"

-    "  -y: assume Yes on all queries\n";

+    "  -r[-|0] : Recurse subdirectories\n"

+    "  -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"

+    "  -sfx[{name}] : Create SFX archive\n"

+    "  -si[{name}] : read data from stdin\n"

+    "  -slt : show technical information for l (List) command\n"

+    "  -so : write data to stdout\n"

+    "  -ssc[-] : set sensitive case mode\n"

+    "  -ssw : compress shared files\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"

+    "  -y : assume Yes on all queries\n";

 

 // ---------------------------

 // exception messages

@@ -110,21 +133,16 @@
 static const char *kUserErrorMessage = "Incorrect command line";

 static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";

 static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";

+// static const char *kUnsupportedUpdateArcType = "Can't create archive for that type";

 

-static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";

+static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx");

 

 static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)

 {

-  s << message << endl;

+  s << endl << "Error: " << message << endl;

   throw code;

 }

 

-static void PrintHelpAndExit(CStdOutStream &s)

-{

-  s << kHelpString;

-  ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);

-}

-

 #ifndef _WIN32

 static void GetArguments(int numArgs, const char *args[], UStringVector &parts)

 {

@@ -146,26 +164,253 @@
 }

 

 #ifdef EXTERNAL_CODECS

+

 static void PrintString(CStdOutStream &stdStream, const AString &s, int size)

 {

-  int len = s.Length();

-  stdStream << s;

+  int len = s.Len();

   for (int i = len; i < size; i++)

     stdStream << ' ';

+  stdStream << s;

 }

+

+static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size)

+{

+  char s[16];

+  ConvertUInt32ToString(val, s);

+  PrintString(stdStream, s, size);

+}

+

+static void PrintLibIndex(CStdOutStream &stdStream, int libIndex)

+{

+  if (libIndex >= 0)

+    PrintUInt32(stdStream, libIndex, 2);

+  else

+    stdStream << "  ";

+  stdStream << ' ';

+}

+

 #endif

 

 static void PrintString(CStdOutStream &stdStream, const UString &s, int size)

 {

-  int len = s.Length();

+  int len = s.Len();

   stdStream << s;

   for (int i = len; i < size; i++)

     stdStream << ' ';

 }

 

-static inline char GetHex(Byte value)

+static inline char GetHex(unsigned val)

 {

-  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+  return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10)));

+}

+

+static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,

+    const CErrorInfo &errorInfo, CStdOutStream &stdStream)

+{

+  int exitCode = NExitCode::kSuccess;

+  

+  if (callback.CantFindFiles.Size() > 0)

+  {

+    stdStream << endl;

+    stdStream << "WARNINGS for files:" << endl << endl;

+    unsigned numErrors = callback.CantFindFiles.Size();

+    for (unsigned i = 0; i < numErrors; i++)

+    {

+      stdStream << callback.CantFindFiles[i] << " : ";

+      stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl;

+    }

+    stdStream << "----------------" << endl;

+    stdStream << "WARNING: Cannot find " << numErrors << " file";

+    if (numErrors > 1)

+      stdStream << "s";

+    stdStream << endl;

+    exitCode = NExitCode::kWarning;

+  }

+  

+  if (result != S_OK)

+  {

+    UString message;

+    if (!errorInfo.Message.IsEmpty())

+    {

+      message += errorInfo.Message;

+      message += L"\n";

+    }

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

+  if (numErrors == 0)

+  {

+    if (callback.CantFindFiles.Size() == 0)

+      stdStream << kEverythingIsOk << endl;

+  }

+  else

+  {

+    stdStream << endl;

+    stdStream << "WARNINGS for files:" << endl << endl;

+    for (unsigned i = 0; i < numErrors; i++)

+    {

+      stdStream << callback.FailedFiles[i] << " : ";

+      stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl;

+    }

+    stdStream << "----------------" << endl;

+    stdStream << "WARNING: Cannot open " << numErrors << " file";

+    if (numErrors > 1)

+      stdStream << "s";

+    stdStream << endl;

+    exitCode = NExitCode::kWarning;

+  }

+  return exitCode;

+}

+

+static void ThrowException_if_Error(HRESULT res)

+{

+  if (res != S_OK)

+    throw CSystemException(res);

+}

+

+

+static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ')

+{

+  char temp[64];

+  char *p = temp + 32;

+  ConvertUInt64ToString(val, p);

+  unsigned len = MyStringLen(p);

+  for (; len < numDigits; len++)

+    *--p = c;

+  *g_StdStream << p;

+}

+

+static void PrintTime(const char *s, UInt64 val, UInt64 total)

+{

+  *g_StdStream << endl << s << " Time =";

+  const UInt32 kFreq = 10000000;

+  UInt64 sec = val / kFreq;

+  PrintNum(sec, 6);

+  *g_StdStream << '.';

+  UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000);

+  PrintNum(ms, 3, '0');

+  

+  while (val > ((UInt64)1 << 56))

+  {

+    val >>= 1;

+    total >>= 1;

+  }

+

+  UInt64 percent = 0;

+  if (total != 0)

+    percent = val * 100 / total;

+  *g_StdStream << " =";

+  PrintNum(percent, 5);

+  *g_StdStream << '%';

+}

+

+#ifndef UNDER_CE

+

+#define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num))

+

+static void PrintMemUsage(const char *s, UInt64 val)

+{

+  *g_StdStream << "    " << s << " Memory =";

+  PrintNum(SHIFT_SIZE_VALUE(val, 20), 7);

+  *g_StdStream << " MB";

+}

+

+EXTERN_C_BEGIN

+typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process,

+    PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);

+EXTERN_C_END

+

+#endif

+

+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }

+

+static void PrintStat()

+{

+  FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT;

+  if (!

+      #ifdef UNDER_CE

+        ::GetThreadTimes(::GetCurrentThread()

+      #else

+        // NT 3.5

+        ::GetProcessTimes(::GetCurrentProcess()

+      #endif

+      , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT))

+    return;

+  FILETIME curTimeFT;

+  NTime::GetCurUtcFileTime(curTimeFT);

+

+  #ifndef UNDER_CE

+  

+  PROCESS_MEMORY_COUNTERS m;

+  memset(&m, 0, sizeof(m));

+  BOOL memDefined = FALSE;

+  {

+    /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll

+       Win7: new function K32GetProcessMemoryInfo() in kernel32.dll

+       It's faster to call kernel32.dll code than Psapi.dll code

+       GetProcessMemoryInfo() requires Psapi.lib

+       Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll

+       The program with K32GetProcessMemoryInfo will not work on systems before Win7

+       // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));

+    */

+

+    Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)

+        ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo");

+    if (!my_GetProcessMemoryInfo)

+    {

+      HMODULE lib = LoadLibraryW(L"Psapi.dll");

+      if (lib)

+        my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo");

+    }

+    if (my_GetProcessMemoryInfo)

+      memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));

+    // FreeLibrary(lib);

+  }

+

+  #endif

+

+  UInt64 curTime = GetTime64(curTimeFT);

+  UInt64 creationTime = GetTime64(creationTimeFT);

+  UInt64 kernelTime = GetTime64(kernelTimeFT);

+  UInt64 userTime = GetTime64(userTimeFT);

+

+  UInt64 totalTime = curTime - creationTime;

+  

+  PrintTime("Kernel ", kernelTime, totalTime);

+  PrintTime("User   ", userTime, totalTime);

+  

+  PrintTime("Process", kernelTime + userTime, totalTime);

+  #ifndef UNDER_CE

+  if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage);

+  #endif

+  

+  PrintTime("Global ", totalTime, totalTime);

+  #ifndef UNDER_CE

+  if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize);

+  #endif

+  

+  *g_StdStream << endl;

 }

 

 int Main2(

@@ -177,7 +422,7 @@
   #if defined(_WIN32) && !defined(UNDER_CE)

   SetFileApisToOEM();

   #endif

-  

+

   UStringVector commandStrings;

   #ifdef _WIN32

   NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);

@@ -190,11 +435,12 @@
     ShowCopyrightAndHelp(g_StdOut, true);

     return 0;

   }

+

   commandStrings.Delete(0);

 

-  CArchiveCommandLineOptions options;

+  CArcCmdLineOptions options;

 

-  CArchiveCommandLineParser parser;

+  CArcCmdLineParser parser;

 

   parser.Parse1(commandStrings, options);

 

@@ -204,11 +450,16 @@
     return 0;

   }

 

-  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  NSecurity::EnablePrivilege_SymLink();

+  #endif

+  #ifdef _7ZIP_LARGE_PAGES

   if (options.LargePages)

   {

     SetLargePageSize();

-    NSecurity::EnableLockMemoryPrivilege();

+    #if defined(_WIN32) && !defined(UNDER_CE)

+    NSecurity::EnablePrivilege_LockMemory();

+    #endif

   }

   #endif

 

@@ -221,55 +472,98 @@
   parser.Parse2(options);

 

   CCodecs *codecs = new CCodecs;

-  CMyComPtr<

-    #ifdef EXTERNAL_CODECS

-    ICompressCodecsInfo

-    #else

-    IUnknown

-    #endif

-    > compressCodecsInfo = codecs;

-  HRESULT result = codecs->Load();

-  if (result != S_OK)

-    throw CSystemException(result);

+  #ifdef EXTERNAL_CODECS

+  CExternalCodecs __externalCodecs;

+  __externalCodecs.GetCodecs = codecs;

+  __externalCodecs.GetHashers = codecs;

+  #else

+  CMyComPtr<IUnknown> compressCodecsInfo = codecs;

+  #endif

+  codecs->CaseSensitiveChange = options.CaseSensitiveChange;

+  codecs->CaseSensitive = options.CaseSensitive;

+  ThrowException_if_Error(codecs->Load());

 

   bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

 

   if (codecs->Formats.Size() == 0 &&

-        (isExtractGroupCommand ||

-        options.Command.CommandType == NCommandType::kList ||

-        options.Command.IsFromUpdateGroup()))

+        (isExtractGroupCommand

+        || options.Command.CommandType == NCommandType::kList

+        || options.Command.IsFromUpdateGroup()))

     throw kNoFormats;

 

-  CIntVector formatIndices;

-  if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices))

+  CObjectVector<COpenType> types;

+  if (!ParseOpenTypes(*codecs, options.ArcType, types))

     throw kUnsupportedArcTypeMessage;

 

+  CIntVector excludedFormats;

+  FOR_VECTOR (k, options.ExcludedArcTypes)

+  {

+    CIntVector tempIndices;

+    if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)

+        || tempIndices.Size() != 1)

+      throw kUnsupportedArcTypeMessage;

+    excludedFormats.AddToUniqueSorted(tempIndices[0]);

+    // excludedFormats.Sort();

+  }

+

+  

+  #ifdef EXTERNAL_CODECS

+  if (isExtractGroupCommand

+      || options.Command.CommandType == NCommandType::kHash

+      || options.Command.CommandType == NCommandType::kBenchmark)

+    ThrowException_if_Error(__externalCodecs.LoadCodecs());

+  #endif

+

+  int retCode = NExitCode::kSuccess;

+  HRESULT hresultMain = S_OK;

+

+  bool showStat = true;

+  if (!options.EnableHeaders ||

+      options.TechMode)

+    showStat = false;

+  

+

   if (options.Command.CommandType == NCommandType::kInfo)

   {

+    unsigned i;

+

+    #ifdef EXTERNAL_CODECS

+    stdStream << endl << "Libs:" << endl;

+    for (i = 0; i < codecs->Libs.Size(); i++)

+    {

+      PrintLibIndex(stdStream, i);

+      stdStream << ' ' << codecs->Libs[i].Path << endl;

+    }

+    #endif

+

     stdStream << endl << "Formats:" << endl;

-    int i;

+    

+    const char *kArcFlags = "KSNFMGOPBELH";

+    const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);

+    

     for (i = 0; i < codecs->Formats.Size(); i++)

     {

       const CArcInfoEx &arc = codecs->Formats[i];

       #ifdef EXTERNAL_CODECS

-      if (arc.LibIndex >= 0)

-      {

-        char s[16];

-        ConvertUInt32ToString(arc.LibIndex, s);

-        PrintString(stdStream, s, 2);

-      }

-      else

+      PrintLibIndex(stdStream, arc.LibIndex);

+      #else

+      stdStream << "  ";

       #endif

-        stdStream << "  ";

-      stdStream << ' ';

       stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');

-      stdStream << (char)(arc.KeepName ? 'K' : ' ');

-      stdStream << "  ";

-      PrintString(stdStream, arc.Name, 6);

-      stdStream << "  ";

-      UString s;

-      for (int t = 0; t < arc.Exts.Size(); t++)

+      for (unsigned b = 0; b < kNumArcFlags; b++)

       {

+        stdStream << (char)

+          ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' ');

+      }

+        

+      stdStream << ' ';

+      PrintString(stdStream, arc.Name, 8);

+      stdStream << ' ';

+      UString s;

+      FOR_VECTOR (t, arc.Exts)

+      {

+        if (t != 0)

+          s += L' ';

         const CArcExtInfo &ext = arc.Exts[t];

         s += ext.Ext;

         if (!ext.AddExt.IsEmpty())

@@ -278,44 +572,46 @@
           s += ext.AddExt;

           s += L')';

         }

-        s += L' ';

       }

-      PrintString(stdStream, s, 14);

-      stdStream << "  ";

-      const CByteBuffer &sig = arc.StartSignature;

-      for (size_t j = 0; j < sig.GetCapacity(); j++)

+      PrintString(stdStream, s, 13);

+      stdStream << ' ';

+      if (arc.SignatureOffset != 0)

+        stdStream << "offset=" << arc.SignatureOffset << ' ';

+

+      FOR_VECTOR(si, arc.Signatures)

       {

-        Byte b = sig[j];

-        if (b > 0x20 && b < 0x80)

+        if (si != 0)

+          stdStream << "  ||  ";

+

+        const CByteBuffer &sig = arc.Signatures[si];

+        

+        for (size_t j = 0; j < sig.Size(); j++)

         {

-          stdStream << (char)b;

+          if (j != 0)

+            stdStream << ' ';

+          Byte b = sig[j];

+          if (b > 0x20 && b < 0x80)

+          {

+            stdStream << (char)b;

+          }

+          else

+          {

+            stdStream << GetHex((b >> 4) & 0xF);

+            stdStream << GetHex(b & 0xF);

+          }

         }

-        else

-        {

-          stdStream << GetHex((Byte)((b >> 4) & 0xF));

-          stdStream << GetHex((Byte)(b & 0xF));

-        }

-        stdStream << ' ';

       }

       stdStream << endl;

     }

-    stdStream << endl << "Codecs:" << endl;

 

     #ifdef EXTERNAL_CODECS

+

+    stdStream << endl << "Codecs:" << endl << "Lib         ID  Name" << endl;

     UInt32 numMethods;

     if (codecs->GetNumberOfMethods(&numMethods) == S_OK)

     for (UInt32 j = 0; j < numMethods; j++)

     {

-      int libIndex = codecs->GetCodecLibIndex(j);

-      if (libIndex >= 0)

-      {

-        char s[16];

-        ConvertUInt32ToString(libIndex, s);

-        PrintString(stdStream, s, 2);

-      }

-      else

-        stdStream << "  ";

-      stdStream << ' ';

+      PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j));

       stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');

       UInt64 id;

       stdStream << "  ";

@@ -323,57 +619,36 @@
       if (res != S_OK)

         id = (UInt64)(Int64)-1;

       char s[32];

-      ConvertUInt64ToString(id, s, 16);

+      ConvertUInt64ToHex(id, s);

       PrintString(stdStream, s, 8);

-      stdStream << "  ";

-      PrintString(stdStream, codecs->GetCodecName(j), 11);

-      stdStream << endl;

-      /*

-      if (res != S_OK)

-        throw "incorrect Codec ID";

-      */

+      stdStream << "  " << codecs->GetCodecName(j) << endl;

     }

+    

+    stdStream << endl << "Hashers:" << endl << " L Size     ID  Name" << endl;

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

+    }

+

     #endif

-    return S_OK;

+    

   }

   else if (options.Command.CommandType == NCommandType::kBenchmark)

   {

-    if (options.Method.CompareNoCase(L"CRC") == 0)

+    hresultMain = BenchCon(EXTERNAL_CODECS_VARS

+        options.Properties, options.NumIterations, (FILE *)stdStream);

+    if (hresultMain == S_FALSE)

     {

-      HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);

-      if (res != S_OK)

-      {

-        if (res == S_FALSE)

-        {

-          stdStream << "\nCRC Error\n";

-          return NExitCode::kFatalError;

-        }

-        throw CSystemException(res);

-      }

-    }

-    else

-    {

-      HRESULT res;

-      #ifdef EXTERNAL_CODECS

-      CObjectVector<CCodecInfoEx> externalCodecs;

-      res = LoadExternalCodecs(compressCodecsInfo, externalCodecs);

-      if (res != S_OK)

-        throw CSystemException(res);

-      #endif

-      res = LzmaBenchCon(

-          #ifdef EXTERNAL_CODECS

-          compressCodecsInfo, &externalCodecs,

-          #endif

-        (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);

-      if (res != S_OK)

-      {

-        if (res == S_FALSE)

-        {

-          stdStream << "\nDecoding Error\n";

-          return NExitCode::kFatalError;

-        }

-        throw CSystemException(res);

-      }

+      stdStream << "\nDecoding Error\n";

+      retCode = NExitCode::kFatalError;

+      hresultMain = S_OK;

     }

   }

   else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)

@@ -401,90 +676,145 @@
       #endif

 

       CExtractOptions eo;

+      (CExtractOptionsBase &)eo = options.ExtractOptions;

       eo.StdInMode = options.StdInMode;

       eo.StdOutMode = options.StdOutMode;

-      eo.PathMode = options.Command.GetPathMode();

-      eo.TestMode = options.Command.IsTestMode();

-      eo.OverwriteMode = options.OverwriteMode;

-      eo.OutputDir = options.OutputDir;

       eo.YesToAll = options.YesToAll;

-      eo.CalcCrc = options.CalcCrc;

-      #if !defined(_7ZIP_ST) && !defined(_SFX)

-      eo.Properties = options.ExtractProperties;

+      eo.TestMode = options.Command.IsTestCommand();

+      

+      #ifndef _SFX

+      eo.Properties = options.Properties;

       #endif

+

       UString errorMessage;

       CDecompressStat stat;

-      HRESULT result = DecompressArchives(

+      CHashBundle hb;

+      IHashCalc *hashCalc = NULL;

+

+      if (!options.HashMethods.IsEmpty())

+      {

+        hashCalc = &hb;

+        ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods));

+        hb.Init();

+      }

+      hresultMain = Extract(

           codecs,

-          formatIndices,

+          types,

+          excludedFormats,

           options.ArchivePathsSorted,

           options.ArchivePathsFullSorted,

-          options.WildcardCensor.Pairs.Front().Head,

-          eo, &openCallback, ecs, errorMessage, stat);

+          options.Censor.Pairs.Front().Head,

+          eo, &openCallback, ecs, hashCalc, errorMessage, stat);

       if (!errorMessage.IsEmpty())

       {

         stdStream << endl << "Error: " << errorMessage;

-        if (result == S_OK)

-          result = E_FAIL;

+        if (hresultMain == S_OK)

+          hresultMain = E_FAIL;

       }

 

       stdStream << endl;

-      if (ecs->NumArchives > 1)

-        stdStream << "Archives: " << ecs->NumArchives << endl;

-      if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)

+

+      if (ecs->NumTryArcs > 1)

       {

-        if (ecs->NumArchives > 1)

+        stdStream << "Archives: " << ecs->NumTryArcs << endl;

+        stdStream << "OK archives: " << ecs->NumOkArcs << endl;

+      }

+      bool isError = false;

+      if (ecs->NumCantOpenArcs != 0)

+      {

+        isError = true;

+        stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;

+      }

+      if (ecs->NumArcsWithError != 0)

+      {

+        isError = true;

+        stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl;

+      }

+      if (ecs->NumArcsWithWarnings != 0)

+        stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;

+      

+      if (ecs->NumOpenArcWarnings != 0)

+      {

+        stdStream << endl;

+        if (ecs->NumOpenArcWarnings != 0)

+          stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl;

+      }

+      

+      if (ecs->NumOpenArcErrors != 0)

+      {

+        isError = true;

+        stdStream << endl;

+        if (ecs->NumOpenArcErrors != 0)

+          stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl;

+      }

+

+      if (isError)

+        retCode = NExitCode::kFatalError;

+      

+      if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)

+      {

+        // if (ecs->NumArchives > 1)

         {

           stdStream << endl;

-          if (ecs->NumArchiveErrors != 0)

-            stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;

           if (ecs->NumFileErrors != 0)

             stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;

         }

-        if (result != S_OK)

-          throw CSystemException(result);

-        return NExitCode::kFatalError;

       }

-      if (result != S_OK)

-        throw CSystemException(result);

+      else if (hresultMain == S_OK)

+      {

+     

       if (stat.NumFolders != 0)

         stdStream << "Folders: " << stat.NumFolders << endl;

-      if (stat.NumFiles != 1 || stat.NumFolders != 0)

-          stdStream << "Files: " << stat.NumFiles << 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 (options.CalcCrc)

-      {

-        char s[16];

-        ConvertUInt32ToHexWithZeros(stat.CrcSum, s);

-        stdStream << "CRC: " << s << endl;

+      if (hashCalc)

+        PrintHashStat(stdStream, hb);

       }

     }

     else

     {

       UInt64 numErrors = 0;

-      HRESULT result = ListArchives(

+      UInt64 numWarnings = 0;

+      

+      // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed

+

+      hresultMain = ListArchives(

           codecs,

-          formatIndices,

+          types,

+          excludedFormats,

           options.StdInMode,

           options.ArchivePathsSorted,

           options.ArchivePathsFullSorted,

-          options.WildcardCensor.Pairs.Front().Head,

+          options.ExtractOptions.NtOptions.AltStreams.Val,

+          options.AltStreams.Val, // we don't want to show AltStreams by default

+          options.Censor.Pairs.Front().Head,

           options.EnableHeaders,

           options.TechMode,

           #ifndef _NO_CRYPTO

           options.PasswordEnabled,

           options.Password,

           #endif

-          numErrors);

+          &options.Properties,

+          numErrors, numWarnings);

+

+        if (options.EnableHeaders)

+          if (numWarnings > 0)

+            g_StdOut << endl << "Warnings: " << numWarnings << endl;

       if (numErrors > 0)

       {

-        g_StdOut << endl << "Errors: " << numErrors;

-        return NExitCode::kFatalError;

+        if (options.EnableHeaders)

+          g_StdOut << endl << "Errors: " << numErrors << endl;

+        retCode = NExitCode::kFatalError;

       }

-      if (result != S_OK)

-        throw CSystemException(result);

     }

   }

   else if (options.Command.IsFromUpdateGroup())

@@ -516,83 +846,42 @@
 

     CUpdateErrorInfo errorInfo;

 

-    if (!uo.Init(codecs, formatIndices, options.ArchiveName))

-      throw kUnsupportedArcTypeMessage;

-    HRESULT result = UpdateArchive(codecs,

-        options.WildcardCensor, uo,

-        errorInfo, &openCallback, &callback);

+    /*

+    if (!uo.Init(codecs, types, options.ArchiveName))

+      throw kUnsupportedUpdateArcType;

+    */

+    hresultMain = UpdateArchive(codecs,

+        types,

+        options.ArchiveName,

+        options.Censor,

+        uo,

+        errorInfo, &openCallback, &callback, true);

+    retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);

+  }

+  else if (options.Command.CommandType == NCommandType::kHash)

+  {

+    const CHashOptions &uo = options.HashOptions;

 

-    int exitCode = NExitCode::kSuccess;

-    if (callback.CantFindFiles.Size() > 0)

-    {

-      stdStream << endl;

-      stdStream << "WARNINGS for files:" << endl << endl;

-      int numErrors = callback.CantFindFiles.Size();

-      for (int i = 0; i < numErrors; i++)

-      {

-        stdStream << callback.CantFindFiles[i] << " : ";

-        stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;

-      }

-      stdStream << "----------------" << endl;

-      stdStream << "WARNING: Cannot find " << numErrors << " file";

-      if (numErrors > 1)

-        stdStream << "s";

-      stdStream << endl;

-      exitCode = NExitCode::kWarning;

-    }

+    CHashCallbackConsole callback;

+    callback.EnablePercents = options.EnablePercents;

 

-    if (result != S_OK)

-    {

-      UString message;

-      if (!errorInfo.Message.IsEmpty())

-      {

-        message += errorInfo.Message;

-        message += L"\n";

-      }

-      if (!errorInfo.FileName.IsEmpty())

-      {

-        message += errorInfo.FileName;

-        message += L"\n";

-      }

-      if (!errorInfo.FileName2.IsEmpty())

-      {

-        message += errorInfo.FileName2;

-        message += L"\n";

-      }

-      if (errorInfo.SystemError != 0)

-      {

-        message += NError::MyFormatMessageW(errorInfo.SystemError);

-        message += L"\n";

-      }

-      if (!message.IsEmpty())

-        stdStream << L"\nError:\n" << message;

-      throw CSystemException(result);

-    }

-    int numErrors = callback.FailedFiles.Size();

-    if (numErrors == 0)

-    {

-      if (callback.CantFindFiles.Size() == 0)

-        stdStream << kEverythingIsOk << endl;

-    }

-    else

-    {

-      stdStream << endl;

-      stdStream << "WARNINGS for files:" << endl << endl;

-      for (int i = 0; i < numErrors; i++)

-      {

-        stdStream << callback.FailedFiles[i] << " : ";

-        stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;

-      }

-      stdStream << "----------------" << endl;

-      stdStream << "WARNING: Cannot open " << numErrors << " file";

-      if (numErrors > 1)

-        stdStream << "s";

-      stdStream << endl;

-      exitCode = NExitCode::kWarning;

-    }

-    return exitCode;

+    callback.Init(&stdStream);

+

+    UString errorInfoString;

+    hresultMain = HashCalc(EXTERNAL_CODECS_VARS

+        options.Censor, uo,

+        errorInfoString, &callback);

+    CErrorInfo errorInfo;

+    errorInfo.Message = errorInfoString;

+    retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);

   }

   else

-    PrintHelpAndExit(stdStream);

-  return 0;

+    ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError);

+

+  if (showStat)

+    PrintStat();

+

+  ThrowException_if_Error(hresultMain);

+

+  return retCode;

 }

diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
old mode 100755
new mode 100644
index b6681b4..0e5cebc
--- a/CPP/7zip/UI/Console/MainAr.cpp
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -2,11 +2,11 @@
 

 #include "StdAfx.h"

 

-#include "Common/MyException.h"

-#include "Common/StdOutStream.h"

+#include "../../../Common/MyException.h"

+#include "../../../Common/StdOutStream.h"

 

-#include "Windows/Error.h"

-#include "Windows/NtCheck.h"

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/NtCheck.h"

 

 #include "../Common/ArchiveCommandLine.h"

 #include "../Common/ExitCode.h"

@@ -23,6 +23,7 @@
   #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";

@@ -62,9 +63,9 @@
     (*g_StdStream) << endl << kUserBreak;

     return (NExitCode::kUserBreak);

   }

-  catch(const CArchiveCommandLineException &e)

+  catch(const CArcCmdLineException &e)

   {

-    (*g_StdStream) << kExceptionErrorMessage << e << endl;

+    (*g_StdStream) << kException_CmdLine_Error_Message << e << endl;

     return (NExitCode::kUserError);

   }

   catch(const CSystemException &systemError)

@@ -79,9 +80,8 @@
       (*g_StdStream) << endl << kUserBreak;

       return (NExitCode::kUserBreak);

     }

-    UString message;

-    NError::MyFormatMessage(systemError.ErrorCode, message);

-    (*g_StdStream) << endl << endl << "System error:" << endl << message << endl;

+    (*g_StdStream) << endl << endl << "System error:" << endl <<

+        NError::MyFormatMessage(systemError.ErrorCode) << endl;

     return (NExitCode::kFatalError);

   }

   catch(NExitCode::EEnum &exitCode)

@@ -121,5 +121,5 @@
     (*g_StdStream) << kUnknownExceptionMessage;

     return (NExitCode::kFatalError);

   }

-  return  res;

+  return res;

 }

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
old mode 100755
new mode 100644
index 986a592..6552d5d
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -38,10 +38,10 @@
   return StringToBstr(Password, password);

 }

 

-HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password)

+HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)

 {

-  if (PasswordIsDefined)

-    password = Password;

+  passwordIsDefined = PasswordIsDefined;

+  password = Password;

   return S_OK;

 }

 

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
old mode 100755
new mode 100644
index 99e8c04..25d3f72
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.h
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -1,9 +1,10 @@
 // OpenCallbackConsole.h

 

-#ifndef __OPENCALLBACKCONSOLE_H

-#define __OPENCALLBACKCONSOLE_H

+#ifndef __OPEN_CALLBACK_CONSOLE_H

+#define __OPEN_CALLBACK_CONSOLE_H

 

-#include "Common/StdOutStream.h"

+#include "../../../Common/StdOutStream.h"

+

 #include "../Common/ArchiveOpenCallback.h"

 

 class COpenCallbackConsole: public IOpenCallbackUI

diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
old mode 100755
new mode 100644
index 111ae25..edf88b9
--- a/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -2,18 +2,18 @@
 

 #include "StdAfx.h"

 

-#include "Common/IntToString.h"

-#include "Common/MyString.h"

+#include "../../../Common/Defs.h"

+#include "../../../Common/IntToString.h"

 

 #include "PercentPrinter.h"

 

-const int kPaddingSize = 2;

-const int kPercentsSize = 4;

-const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;

+static const unsigned kPaddingSize = 2;

+static const unsigned kPercentsSize = 4;

+static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;

 

-static void ClearPrev(char *p, int num)

+static void ClearPrev(char *p, unsigned num)

 {

-  int i;

+  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';

@@ -51,18 +51,30 @@
 void CPercentPrinter::RePrintRatio()

 {

   char s[32];

-  ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);

-  int size = (int)strlen(s);

-  s[size++] = '%';

-  s[size] = '\0';

+  unsigned size;

+  {

+    char c = '%';

+    UInt64 value = 0;

+    if (m_Total == (UInt64)(Int64)-1)

+    {

+      value = m_CurValue >> 20;

+      c = 'M';

+    }

+    else if (m_Total != 0)

+      value = m_CurValue * 100 / m_Total;

+    ConvertUInt64ToString(value, s);

+    size = (unsigned)strlen(s);

+    s[size++] = c;

+    s[size] = '\0';

+  }

 

-  int extraSize = kPaddingSize + MyMax(size, kPercentsSize);

+  unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize);

   if (extraSize < m_NumExtraChars)

     extraSize = m_NumExtraChars;

 

   char fullString[kMaxExtraSize * 3];

   char *p = fullString;

-  int i;

+  unsigned i;

   if (m_NumExtraChars == 0)

   {

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

@@ -73,7 +85,7 @@
   for (i = 0; i < m_NumExtraChars; i++)

     *p++ = '\b';

   m_NumExtraChars = extraSize;

-  for (; size < m_NumExtraChars; size++)

+  for (; size < extraSize; size++)

     *p++ = ' ';

   MyStringCopy(p, s);

   (*OutStream) << fullString;

diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
old mode 100755
new mode 100644
index 212e11e..b6b357a
--- a/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/CPP/7zip/UI/Console/PercentPrinter.h
@@ -1,10 +1,9 @@
 // PercentPrinter.h

 

-#ifndef __PERCENTPRINTER_H

-#define __PERCENTPRINTER_H

+#ifndef __PERCENT_PRINTER_H

+#define __PERCENT_PRINTER_H

 

-#include "Common/Types.h"

-#include "Common/StdOutStream.h"

+#include "../../../Common/StdOutStream.h"

 

 class CPercentPrinter

 {

@@ -12,12 +11,12 @@
   UInt64 m_PrevValue;

   UInt64 m_CurValue;

   UInt64 m_Total;

-  int m_NumExtraChars;

+  unsigned m_NumExtraChars;

 public:

   CStdOutStream *OutStream;

 

   CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),

-      m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}

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

diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h
old mode 100755
new mode 100644
index a4e6173..59d9ac1
--- a/CPP/7zip/UI/Console/StdAfx.h
+++ b/CPP/7zip/UI/Console/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../../../Common/MyWindows.h"

-#include "../../../Common/NewHandler.h"

+#include "../../../Common/Common.h"

 

 #endif

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
old mode 100755
new mode 100644
index c482676..033d70b
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -2,15 +2,14 @@
 

 #include "StdAfx.h"

 

-#include "UpdateCallbackConsole.h"

-

-#include "Windows/Error.h"

+#include "../../../Windows/ErrorMsg.h"

 #ifndef _7ZIP_ST

-#include "Windows/Synchronization.h"

+#include "../../../Windows/Synchronization.h"

 #endif

 

 #include "ConsoleClose.h"

 #include "UserInputUtils.h"

+#include "UpdateCallbackConsole.h"

 

 using namespace NWindows;

 

@@ -28,11 +27,18 @@
 static const char *kScanningMessage = "Scanning";

 

 

-HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)

+HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType)

 {

   (*OutStream) << endl;

   if (result != S_OK)

-    (*OutStream) << "Error: " << name << " is not supported archive" << endl;

+  {

+    (*OutStream) << "Error: " << name;

+    if (errorArcType)

+      (*OutStream) << " : can not open the file as [" << errorArcType << "] archive";

+    else

+      (*OutStream) << " is not supported archive";

+    (*OutStream) << endl;

+  }

   return S_OK;

 }

 

@@ -42,12 +48,12 @@
   return S_OK;

 }

 

-HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */)

+HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)

 {

   return CheckBreak();

 }

 

-HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)

+HRESULT CCallbackConsoleBase::CanNotFindError_Base(const wchar_t *name, DWORD systemError)

 {

   CantFindFiles.Add(name);

   CantFindCodes.Add(systemError);

@@ -60,11 +66,16 @@
   }

   m_PercentPrinter.PrintString(name);

   m_PercentPrinter.PrintString(":  WARNING: ");

-  m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));

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

@@ -176,15 +187,19 @@
   MT_LOCK

   FailedCodes.Add(systemError);

   FailedFiles.Add(name);

-  // if (systemError == ERROR_SHARING_VIOLATION)

+  /*

+  if (systemError == ERROR_SHARING_VIOLATION)

   {

+  */

     m_PercentPrinter.ClosePrint();

     m_PercentPrinter.PrintNewLine();

     m_PercentPrinter.PrintString("WARNING: ");

-    m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));

+    m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError));

     return S_FALSE;

+  /*

   }

-  // return systemError;

+  return systemError;

+  */

 }

 

 HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
old mode 100755
new mode 100644
index 59581f3..c73de67
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -3,55 +3,39 @@
 #ifndef __UPDATE_CALLBACK_CONSOLE_H

 #define __UPDATE_CALLBACK_CONSOLE_H

 

-#include "Common/StdOutStream.h"

+#include "../../../Common/StdOutStream.h"

 

 #include "../Common/Update.h"

 

 #include "PercentPrinter.h"

 

-class CUpdateCallbackConsole: public IUpdateCallbackUI2

+class CCallbackConsoleBase

 {

-  CPercentPrinter m_PercentPrinter;

-  bool m_NeedBeClosed;

-  bool m_NeedNewLine;

-

   bool m_WarningsMode;

+protected:

+  CPercentPrinter m_PercentPrinter;

 

   CStdOutStream *OutStream;

+  HRESULT CanNotFindError_Base(const wchar_t *name, DWORD systemError);

 public:

   bool EnablePercents;

   bool StdOutMode;

 

-  #ifndef _NO_CRYPTO

-  bool PasswordIsDefined;

-  UString Password;

-  bool AskPassword;

-  #endif

-

-  CUpdateCallbackConsole():

+  CCallbackConsoleBase():

       m_PercentPrinter(1 << 16),

-      #ifndef _NO_CRYPTO

-      PasswordIsDefined(false),

-      AskPassword(false),

-      #endif

       StdOutMode(false),

       EnablePercents(true),

       m_WarningsMode(false)

       {}

   

-  ~CUpdateCallbackConsole() { Finilize(); }

   void Init(CStdOutStream *outStream)

   {

-    m_NeedBeClosed = false;

-    m_NeedNewLine = false;

     FailedFiles.Clear();

     FailedCodes.Clear();

     OutStream = outStream;

     m_PercentPrinter.OutStream = outStream;

   }

 

-  INTERFACE_IUpdateCallbackUI2(;)

-

   UStringVector FailedFiles;

   CRecordVector<HRESULT> FailedCodes;

 

@@ -59,4 +43,33 @@
   CRecordVector<HRESULT> CantFindCodes;

 };

 

+class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase

+{

+  bool m_NeedBeClosed;

+  bool m_NeedNewLine;

+public:

+  #ifndef _NO_CRYPTO

+  bool PasswordIsDefined;

+  UString Password;

+  bool AskPassword;

+  #endif

+

+  CUpdateCallbackConsole()

+      #ifndef _NO_CRYPTO

+      :

+      PasswordIsDefined(false),

+      AskPassword(false)

+      #endif

+      {}

+  

+  void Init(CStdOutStream *outStream)

+  {

+    m_NeedBeClosed = false;

+    m_NeedNewLine = false;

+    CCallbackConsoleBase::Init(outStream);

+  }

+  ~CUpdateCallbackConsole() { Finilize(); }

+  INTERFACE_IUpdateCallbackUI2(;)

+};

+

 #endif

diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
old mode 100755
new mode 100644
index 68481c2..b060fb0
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -2,17 +2,17 @@
 

 #include "StdAfx.h"

 

-#include "Common/StdInStream.h"

-#include "Common/StringConvert.h"

+#include "../../../Common/StdInStream.h"

+#include "../../../Common/StringConvert.h"

 

 #include "UserInputUtils.h"

 

-static const char kYes = 'Y';

-static const char kNo = 'N';

-static const char kYesAll = 'A';

-static const char kNoAll = 'S';

-static const char kAutoRenameAll = 'U';

-static const char kQuit = 'Q';

+static const char kYes = 'y';

+static const char kNo = 'n';

+static const char kYesAll = 'a';

+static const char kNoAll = 's';

+static const char kAutoRenameAll = 'u';

+static const char kQuit = 'q';

 

 static const char *kFirstQuestionMessage = "?\n";

 static const char *kHelpQuestionMessage =

@@ -30,25 +30,14 @@
     AString scannedString = g_StdIn.ScanStringUntilNewLine();

     scannedString.Trim();

     if (!scannedString.IsEmpty())

-      switch(

-        ::MyCharUpper(

-        #ifdef UNDER_CE

-        (wchar_t)

-        #endif

-        scannedString[0]))

+      switch(::MyCharLower_Ascii(scannedString[0]))

       {

-        case kYes:

-          return NUserAnswerMode::kYes;

-        case kNo:

-          return NUserAnswerMode::kNo;

-        case kYesAll:

-          return NUserAnswerMode::kYesAll;

-        case kNoAll:

-          return NUserAnswerMode::kNoAll;

-        case kAutoRenameAll:

-          return NUserAnswerMode::kAutoRenameAll;

-        case kQuit:

-          return NUserAnswerMode::kQuit;

+        case kYes:    return NUserAnswerMode::kYes;

+        case kNo:     return NUserAnswerMode::kNo;

+        case kYesAll: return NUserAnswerMode::kYesAll;

+        case kNoAll:  return NUserAnswerMode::kNoAll;

+        case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll;

+        case kQuit:   return NUserAnswerMode::kQuit;

       }

   }

 }

diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h
old mode 100755
new mode 100644
index 3740ad7..df2773d
--- a/CPP/7zip/UI/Console/UserInputUtils.h
+++ b/CPP/7zip/UI/Console/UserInputUtils.h
@@ -1,9 +1,9 @@
 // UserInputUtils.h

 

-#ifndef __USERINPUTUTILS_H

-#define __USERINPUTUTILS_H

+#ifndef __USER_INPUT_UTILS_H

+#define __USER_INPUT_UTILS_H

 

-#include "Common/StdOutStream.h"

+#include "../../../Common/StdOutStream.h"

 

 namespace NUserAnswerMode {

 

diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
old mode 100755
new mode 100644
index 0d40eb5..0181c52
--- a/CPP/7zip/UI/Console/makefile
+++ b/CPP/7zip/UI/Console/makefile
@@ -1,24 +1,13 @@
 PROG = 7z.exe

 MY_CONSOLE = 1

-CFLAGS = $(CFLAGS) -I ../../../  \

+CFLAGS = $(CFLAGS)  \

   -DEXTERNAL_CODECS \

 

 !IFNDEF UNDER_CE

 CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE

 !ENDIF

 

-

-CONSOLE_OBJS = \

-  $O\ConsoleClose.obj \

-  $O\ExtractCallbackConsole.obj \

-  $O\List.obj \

-  $O\BenchCon.obj \

-  $O\Main.obj \

-  $O\MainAr.obj \

-  $O\OpenCallbackConsole.obj \

-  $O\PercentPrinter.obj \

-  $O\UpdateCallbackConsole.obj \

-  $O\UserInputUtils.obj \

+CURRENT_OBJS = \

 

 COMMON_OBJS = \

   $O\CommandLineParser.obj \

@@ -37,88 +26,46 @@
 

 WIN_OBJS = \

   $O\DLL.obj \

-  $O\Error.obj \

+  $O\ErrorMsg.obj \

   $O\FileDir.obj \

   $O\FileFind.obj \

   $O\FileIO.obj \

+  $O\FileLink.obj \

   $O\FileName.obj \

+  $O\FileSystem.obj \

   $O\MemoryLock.obj \

   $O\PropVariant.obj \

-  $O\PropVariantConversions.obj \

+  $O\PropVariantConv.obj \

   $O\Registry.obj \

   $O\System.obj \

-  $O\Time.obj \

+  $O\TimeUtils.obj \

 

 7ZIP_COMMON_OBJS = \

   $O\CreateCoder.obj \

   $O\FilePathAutoRename.obj \

   $O\FileStreams.obj \

   $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\MethodProps.obj \

   $O\ProgressUtils.obj \

+  $O\PropId.obj \

+  $O\StreamObjects.obj \

   $O\StreamUtils.obj \

-

-UI_COMMON_OBJS = \

-  $O\ArchiveCommandLine.obj \

-  $O\ArchiveExtractCallback.obj \

-  $O\ArchiveOpenCallback.obj \

-  $O\DefaultName.obj \

-  $O\EnumDirItems.obj \

-  $O\Extract.obj \

-  $O\ExtractingFilePath.obj \

-  $O\Bench.obj \

-  $O\LoadCodecs.obj \

-  $O\OpenArchive.obj \

-  $O\PropIDUtils.obj \

-  $O\SetProperties.obj \

-  $O\SortUtils.obj \

-  $O\TempFiles.obj \

-  $O\Update.obj \

-  $O\UpdateAction.obj \

-  $O\UpdateCallback.obj \

-  $O\UpdatePair.obj \

-  $O\UpdateProduce.obj \

-  $O\WorkDir.obj \

+  $O\UniqBlocks.obj \

 

 AR_COMMON_OBJS = \

   $O\OutStreamWithCRC.obj \

 

+COMPRESS_OBJS = \

+  $O\CopyCoder.obj \

+

 C_OBJS = \

   $O\Alloc.obj \

   $O\CpuArch.obj \

+  $O\Sort.obj \

   $O\Threads.obj \

 

 !include "../../Crc.mak"

+!include "Console.mak"

 

-OBJS = \

-  $O\StdAfx.obj \

-  $(CONSOLE_OBJS) \

-  $(COMMON_OBJS) \

-  $(WIN_OBJS) \

-  $(7ZIP_COMMON_OBJS) \

-  $(UI_COMMON_OBJS) \

-  $(AR_COMMON_OBJS) \

-  $O\CopyCoder.obj \

-  $(C_OBJS) \

-  $(ASM_OBJS) \

-  $O\resource.res

-

-!include "../../../Build.mak"

-

-$(CONSOLE_OBJS): $(*B).cpp

-	$(COMPL)

-$(COMMON_OBJS): ../../../Common/$(*B).cpp

-	$(COMPL)

-$(WIN_OBJS): ../../../Windows/$(*B).cpp

-	$(COMPL)

-$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

-	$(COMPL)

-$(UI_COMMON_OBJS): ../Common/$(*B).cpp

-	$(COMPL)

-$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

-	$(COMPL)

-$O\CopyCoder.obj: ../../Compress/$(*B).cpp

-	$(COMPL)

-$(C_OBJS): ../../../../C/$(*B).c

-	$(COMPL_O2)

-

-!include "../../Asm.mak"

+!include "../../7zip.mak"

diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc
old mode 100755
new mode 100644
diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp
new file mode 100644
index 0000000..1ef0d9c
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MyMessages.cpp
@@ -0,0 +1,37 @@
+// MyMessages.cpp

+

+#include "StdAfx.h"

+

+#include "MyMessages.h"

+

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/ResourceString.h"

+

+#include "../FileManager/LangUtils.h"

+

+using namespace NWindows;

+

+void ShowErrorMessage(HWND window, LPCWSTR message)

+{

+  ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP);

+}

+

+void ShowErrorMessageHwndRes(HWND window, UINT resID)

+{

+  ShowErrorMessage(window, LangString(resID));

+}

+

+void ShowErrorMessageRes(UINT resID)

+{

+  ShowErrorMessageHwndRes(0, resID);

+}

+

+void ShowErrorMessageDWORD(HWND window, DWORD errorCode)

+{

+  ShowErrorMessage(window, NError::MyFormatMessage(errorCode));

+}

+

+void ShowLastErrorMessage(HWND window)

+{

+  ShowErrorMessageDWORD(window, ::GetLastError());

+}

diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h
new file mode 100644
index 0000000..c175e8a
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MyMessages.h
@@ -0,0 +1,16 @@
+// MyMessages.h

+

+#ifndef __MY_MESSAGES_H

+#define __MY_MESSAGES_H

+

+#include "../../../Common/MyString.h"

+

+void ShowErrorMessage(HWND window, LPCWSTR message);

+inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); }

+

+void ShowErrorMessageHwndRes(HWND window, UInt32 langID);

+void ShowErrorMessageRes(UInt32 langID);

+

+void ShowLastErrorMessage(HWND window = 0);

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
new file mode 100644
index 0000000..fb63835
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -0,0 +1,1008 @@
+// BrowseDialog.cpp

+ 

+#include "StdAfx.h"

+

+#ifndef UNDER_CE

+#include "../../../Windows/CommonDialog.h"

+#include "../../../Windows/Shell.h"

+#endif

+

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/FileFind.h"

+

+#ifdef UNDER_CE

+#include <commdlg.h>

+#endif

+

+#include "BrowseDialog.h"

+

+#define USE_MY_BROWSE_DIALOG

+

+#ifdef USE_MY_BROWSE_DIALOG

+

+#include "../../../Common/Defs.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/PropVariantConv.h"

+

+#include "../../../Windows/Control/ComboBox.h"

+#include "../../../Windows/Control/Dialog.h"

+#include "../../../Windows/Control/Edit.h"

+#include "../../../Windows/Control/ListView.h"

+

+#include "BrowseDialogRes.h"

+#include "PropertyNameRes.h"

+#include "SysIconUtils.h"

+

+#ifndef _SFX

+#include "RegistryUtils.h"

+#endif

+

+#endif

+

+#include "ComboDialog.h"

+#include "LangUtils.h"

+

+#include "resource.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+using namespace NFind;

+

+#ifdef USE_MY_BROWSE_DIALOG

+

+extern bool g_LVN_ITEMACTIVATE_Support;

+

+static const int kParentIndex = -1;

+static const UINT k_Message_RefreshPathEdit = WM_APP + 1;

+

+static HRESULT GetNormalizedError()

+{

+  DWORD errorCode = GetLastError();

+  return errorCode == 0 ? E_FAIL : errorCode;

+}

+

+extern UString HResultToMessage(HRESULT errorCode);

+

+static void MessageBox_Error_Global(HWND wnd, const wchar_t *message)

+{

+  ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR);

+}

+

+static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name)

+{

+  UString s = HResultToMessage(errorCode);

+  if (name)

+  {

+    s += L'\n';

+    s += name;

+  }

+  MessageBox_Error_Global(wnd, s);

+}

+

+class CBrowseDialog: public NControl::CModalDialog

+{

+  NControl::CListView _list;

+  NControl::CEdit _pathEdit;

+  NControl::CComboBox _filterCombo;

+

+  CObjectVector<CFileInfo> _files;

+

+  CExtToIconMap _extToIconMap;

+  int _sortIndex;

+  bool _ascending;

+  bool _showDots;

+  UString _topDirPrefix; // we don't open parent of that folder

+  UString DirPrefix;

+

+  virtual bool OnInit();

+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);

+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+  virtual bool OnNotify(UINT controlID, LPNMHDR header);

+  virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);

+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  virtual void OnOK();

+

+  void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); }

+

+  bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);

+  // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter

+  HRESULT Reload(const UString &pathPrefix, const UString &selectedName);

+  HRESULT Reload();

+  

+  void OpenParentFolder();

+  void SetPathEditText();

+  void OnCreateDir();

+  void OnItemEnter();

+  void FinishOnOK();

+

+  int GetRealItemIndex(int indexInListView) const

+  {

+    LPARAM param;

+    if (!_list.GetItemParam(indexInListView, param))

+      return (int)-1;

+    return (int)param;

+  }

+

+public:

+  bool FolderMode;

+  UString Title;

+  UString FilePath;  // input/ result path

+  bool ShowAllFiles;

+  UStringVector Filters;

+  UString FilterDescription;

+

+  CBrowseDialog(): FolderMode(false), _showDots(false), ShowAllFiles(true) {}

+  void SetFilter(const UString &s);

+  INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); }

+  int CompareItems(LPARAM lParam1, LPARAM lParam2);

+};

+

+void CBrowseDialog::SetFilter(const UString &s)

+{

+  Filters.Clear();

+  UString mask;

+  unsigned i;

+  for (i = 0; i < s.Len(); i++)

+  {

+    wchar_t c = s[i];

+    if (c == ';')

+    {

+      if (!mask.IsEmpty())

+        Filters.Add(mask);

+      mask.Empty();

+    }

+    else

+      mask += c;

+  }

+  if (!mask.IsEmpty())

+    Filters.Add(mask);

+  ShowAllFiles = Filters.IsEmpty();

+  for (i = 0; i < Filters.Size(); i++)

+  {

+    const UString &f = Filters[i];

+    if (f == L"*.*" || f == L"*")

+    {

+      ShowAllFiles = true;

+      break;

+    }

+  }

+}

+

+bool CBrowseDialog::OnInit()

+{

+  #ifdef LANG

+  LangSetDlgItems(*this, NULL, 0);

+  #endif

+  if (!Title.IsEmpty())

+    SetText(Title);

+  _list.Attach(GetItem(IDL_BROWSE));

+  _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER));

+  _pathEdit.Attach(GetItem(IDE_BROWSE_PATH));

+

+  if (FolderMode)

+    HideItem(IDC_BROWSE_FILTER);

+  else

+    EnableItem(IDC_BROWSE_FILTER, false);

+

+  #ifndef UNDER_CE

+  _list.SetUnicodeFormat();

+  #endif

+

+  #ifndef _SFX

+  if (ReadSingleClick())

+    _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);

+  _showDots = ReadShowDots();

+  #endif

+

+  {

+    UString s;

+    if (!FilterDescription.IsEmpty())

+      s = FilterDescription;

+    else if (ShowAllFiles)

+      s = L"*.*";

+    else

+    {

+      FOR_VECTOR (i, Filters)

+      {

+        if (i != 0)

+          s += L' ';

+        s += Filters[i];

+      }

+    }

+    _filterCombo.AddString(s);

+    _filterCombo.SetCurSel(0);

+  }

+

+  _list.SetImageList(GetSysImageList(true), LVSIL_SMALL);

+  _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);

+

+  _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);

+  _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);

+  {

+    LV_COLUMNW column;

+    column.iSubItem = 2;

+    column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

+    column.fmt = LVCFMT_RIGHT;

+    column.cx = 100;

+    const UString s = LangString(IDS_PROP_SIZE);

+    column.pszText = (wchar_t *)(const wchar_t *)s;

+    _list.InsertColumn(2, &column);

+  }

+

+  _list.InsertItem(0, L"12345678901234567"

+      #ifndef UNDER_CE

+      L"1234567890"

+      #endif

+      );

+  _list.SetSubItem(0, 1, L"2009-09-09"

+      #ifndef UNDER_CE

+      L" 09:09"

+      #endif

+      );

+  _list.SetSubItem(0, 2, L"9999 MB");

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

+    _list.SetColumnWidthAuto(i);

+  _list.DeleteAllItems();

+

+  _ascending = true;

+  _sortIndex = 0;

+

+  NormalizeSize();

+

+  _topDirPrefix.Empty();

+  {

+    int rootSize = GetRootPrefixSize(FilePath);

+    // We can go up from root folder to drives list

+    if (NName::IsDrivePath(FilePath))

+      rootSize = 0;

+    else if (IsSuperPath(FilePath))

+    {

+      if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize]))

+        rootSize = kSuperPathPrefixSize;

+    }

+    _topDirPrefix.SetFrom(FilePath, rootSize);

+  }

+

+  UString name;

+  if (!GetParentPath(FilePath, DirPrefix, name))

+    DirPrefix = _topDirPrefix;

+

+  for(;;)

+  {

+    UString baseFolder = DirPrefix;

+    if (Reload(baseFolder, name) == S_OK)

+      break;

+    name.Empty();

+    if (DirPrefix.IsEmpty())

+      break;

+    UString parent, name2;

+    GetParentPath(DirPrefix, parent, name2);

+    DirPrefix = parent;

+  }

+

+  if (name.IsEmpty())

+    name = FilePath;

+  if (FolderMode)

+    NormalizeDirPathPrefix(name);

+  _pathEdit.SetText(name);

+

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

+  #endif

+

+  return CModalDialog::OnInit();

+}

+

+bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)

+{

+  int mx, my;

+  {

+    RECT r;

+    GetClientRectOfItem(IDB_BROWSE_PARENT, r);

+    mx = r.left;

+    my = r.top;

+  }

+  InvalidateRect(NULL);

+

+  int xLim = xSize - mx;

+  {

+    RECT r;

+    GetClientRectOfItem(IDT_BROWSE_FOLDER, r);

+    MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r));

+  }

+

+  int bx1, bx2, by;

+  GetItemSizes(IDCANCEL, bx1, by);

+  GetItemSizes(IDOK, bx2, by);

+  int y = ySize - my - by;

+  int x = xLim - bx1;

+  MoveItem(IDCANCEL, x, y, bx1, by);

+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);

+

+  // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead

+

+  int yPathSize;

+  {

+    RECT r;

+    GetClientRectOfItem(IDE_BROWSE_PATH, r);

+    yPathSize = RECT_SIZE_Y(r);

+    _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize);

+  }

+

+  {

+    RECT r;

+    GetClientRectOfItem(IDC_BROWSE_FILTER, r);

+    _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r));

+  }

+

+  {

+    RECT r;

+    GetClientRectOfItem(IDL_BROWSE, r);

+    _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top);

+  }

+

+  return false;

+}

+

+bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  if (message == k_Message_RefreshPathEdit)

+  {

+    SetPathEditText();

+    return true;

+  }

+  return CModalDialog::OnMessage(message, wParam, lParam);

+}

+

+bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)

+{

+  if (header->hwndFrom != _list)

+    return false;

+  switch (header->code)

+  {

+    case LVN_ITEMACTIVATE:

+      if (g_LVN_ITEMACTIVATE_Support)

+        OnItemEnter();

+      break;

+    case NM_DBLCLK:

+    case NM_RETURN: // probabably it's unused

+      if (!g_LVN_ITEMACTIVATE_Support)

+        OnItemEnter();

+      break;

+    case LVN_COLUMNCLICK:

+    {

+      int index = LPNMLISTVIEW(header)->iSubItem;

+      if (index == _sortIndex)

+        _ascending = !_ascending;

+      else

+      {

+        _ascending = (index == 0);

+        _sortIndex = index;

+      }

+      Reload();

+      return false;

+    }

+    case LVN_KEYDOWN:

+    {

+      bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header));

+      Post_RefreshPathEdit();

+      return boolResult;

+    }

+    case NM_RCLICK:

+    case NM_CLICK:

+    case LVN_BEGINDRAG:

+      Post_RefreshPathEdit();

+      break;

+  }

+  return false;

+}

+

+bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo)

+{

+  bool ctrl = IsKeyDown(VK_CONTROL);

+

+  switch (keyDownInfo->wVKey)

+  {

+    case VK_BACK:

+      OpenParentFolder();

+      return true;

+    case 'R':

+      if (ctrl)

+      {

+        Reload();

+        return true;

+      }

+      return false;

+    case VK_F7:

+      OnCreateDir();

+      return true;

+  }

+  return false;

+}

+

+bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch (buttonID)

+  {

+    case IDB_BROWSE_PARENT: OpenParentFolder(); break;

+    case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break;

+    default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND);

+  }

+  _list.SetFocus();

+  return true;

+}

+

+void CBrowseDialog::OnOK()

+{

+  /* When we press "Enter" in listview, Windows sends message to first Button.

+     We check that message was from ListView; */

+  if (GetFocus() == _list)

+  {

+    OnItemEnter();

+    return;

+  }

+  FinishOnOK();

+}

+

+

+bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name)

+{

+  parentPrefix.Empty();

+  name.Empty();

+  if (path.IsEmpty())

+    return false;

+  if (_topDirPrefix == path)

+    return false;

+  UString s = path;

+  if (s.Back() == WCHAR_PATH_SEPARATOR)

+    s.DeleteBack();

+  if (s.IsEmpty())

+    return false;

+  if (s.Back() == WCHAR_PATH_SEPARATOR)

+    return false;

+  int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);

+  parentPrefix.SetFrom(s, pos + 1);

+  name = s.Ptr(pos + 1);

+  return true;

+}

+

+int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2)

+{

+  if (lParam1 == kParentIndex) return -1;

+  if (lParam2 == kParentIndex) return 1;

+  const CFileInfo &f1 = _files[(int)lParam1];

+  const CFileInfo &f2 = _files[(int)lParam2];

+

+  bool isDir1 = f1.IsDir();

+  bool isDir2 = f2.IsDir();

+  if (isDir1 && !isDir2) return -1;

+  if (isDir2 && !isDir1) return 1;

+  

+  int res = 0;

+  switch (_sortIndex)

+  {

+    case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break;

+    case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break;

+    case 2: res = MyCompare(f1.Size, f2.Size); break;

+  }

+  return _ascending ? res: -res;

+}

+

+static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)

+{

+  return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2);

+}

+

+static void ConvertSizeToString(UInt64 v, wchar_t *s)

+{

+  Byte c = 0;

+       if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; }

+  else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; }

+  else if (v >= ((UInt64)10000 <<  0)) { v >>= 10; c = 'K'; }

+  ConvertUInt64ToString(v, s);

+  if (c != 0)

+  {

+    s += MyStringLen(s);

+    *s++ = ' ';

+    *s++ = c;

+    *s++ = 0;

+  }

+}

+

+// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter

+

+HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)

+{

+  CObjectVector<CFileInfo> files;

+  

+  #ifndef UNDER_CE

+  bool isDrive = false;

+  if (pathPrefix.IsEmpty() || pathPrefix == kSuperPathPrefix)

+  {

+    isDrive = true;

+    FStringVector drives;

+    if (!MyGetLogicalDriveStrings(drives))

+      return GetNormalizedError();

+    FOR_VECTOR (i, drives)

+    {

+      FString d = drives[i];

+      if (d.Len() < 3 || d.Back() != '\\')

+        return E_FAIL;

+      d.DeleteBack();

+      CFileInfo &fi = files.AddNew();

+      fi.SetAsDir();

+      fi.Name = d;

+    }

+  }

+  else

+  #endif

+  {

+    CEnumerator enumerator(us2fs(pathPrefix + L'*'));

+    for (;;)

+    {

+      bool found;

+      CFileInfo fi;

+      if (!enumerator.Next(fi, found))

+        return GetNormalizedError();

+      if (!found)

+        break;

+      if (!fi.IsDir())

+      {

+        if (FolderMode)

+          continue;

+        if (!ShowAllFiles)

+        {

+          unsigned i;

+          for (i = 0; i < Filters.Size(); i++)

+            if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name)))

+              break;

+          if (i == Filters.Size())

+            continue;

+        }

+      }

+      files.Add(fi);

+    }

+  }

+

+  DirPrefix = pathPrefix;

+

+  _files = files;

+

+  SetItemText(IDT_BROWSE_FOLDER, DirPrefix);

+

+  _list.SetRedraw(false);

+  _list.DeleteAllItems();

+

+  LVITEMW item;

+

+  int index = 0;

+  int cursorIndex = -1;

+

+  #ifndef _SFX

+  if (_showDots && _topDirPrefix != DirPrefix)

+  {

+    item.iItem = index;

+    const UString itemName = L"..";

+    if (selectedName.IsEmpty())

+      cursorIndex = index;

+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;

+    int subItem = 0;

+    item.iSubItem = subItem++;

+    item.lParam = kParentIndex;

+    item.pszText = (wchar_t *)(const wchar_t *)itemName;

+    item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix);

+    if (item.iImage < 0)

+      item.iImage = 0;

+    _list.InsertItem(&item);

+    _list.SetSubItem(index, subItem++, L"");

+    _list.SetSubItem(index, subItem++, L"");

+    index++;

+  }

+  #endif

+

+  for (unsigned i = 0; i < _files.Size(); i++, index++)

+  {

+    item.iItem = index;

+    const CFileInfo &fi = _files[i];

+    const UString name = fs2us(fi.Name);

+    if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0)

+      cursorIndex = index;

+    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;

+    int subItem = 0;

+    item.iSubItem = subItem++;

+    item.lParam = i;

+    item.pszText = (wchar_t *)(const wchar_t *)name;

+

+    const UString fullPath = DirPrefix + name;

+    #ifndef UNDER_CE

+    if (isDrive)

+    {

+      if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)

+        item.iImage = 0;

+    }

+    else

+    #endif

+      item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);

+    if (item.iImage < 0)

+      item.iImage = 0;

+    _list.InsertItem(&item);

+    wchar_t s[32];

+    {

+      FILETIME ft;

+      s[0] = 0;

+      if (FileTimeToLocalFileTime(&fi.MTime, &ft))

+        ConvertFileTimeToString(ft, s,

+            #ifndef UNDER_CE

+              true

+            #else

+              false

+            #endif

+            , false);

+      _list.SetSubItem(index, subItem++, s);

+    }

+    {

+      s[0] = 0;

+      if (!fi.IsDir())

+        ConvertSizeToString(fi.Size, s);

+      _list.SetSubItem(index, subItem++, s);

+    }

+  }

+

+  if (_list.GetItemCount() > 0 && cursorIndex >= 0)

+    _list.SetItemState_FocusedSelected(cursorIndex);

+  _list.SortItems(CompareItems2, (LPARAM)this);

+  if (_list.GetItemCount() > 0 && cursorIndex < 0)

+    _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);

+  _list.EnsureVisible(_list.GetFocusedItem(), false);

+  _list.SetRedraw(true);

+  _list.InvalidateRect(NULL, true);

+  return S_OK;

+}

+

+HRESULT CBrowseDialog::Reload()

+{

+  UString selected;

+  int index = _list.GetNextSelectedItem(-1);

+  if (index >= 0)

+  {

+    int fileIndex = GetRealItemIndex(index);

+    if (fileIndex != kParentIndex)

+      selected = fs2us(_files[fileIndex].Name);

+  }

+  UString dirPathTemp = DirPrefix;

+  return Reload(dirPathTemp, selected);

+}

+

+void CBrowseDialog::OpenParentFolder()

+{

+  UString parent, selected;

+  if (GetParentPath(DirPrefix, parent, selected))

+  {

+    Reload(parent, selected);

+    SetPathEditText();

+  }

+}

+

+void CBrowseDialog::SetPathEditText()

+{

+  int index = _list.GetNextSelectedItem(-1);

+  if (index < 0)

+  {

+    if (FolderMode)

+      _pathEdit.SetText(DirPrefix);

+    return;

+  }

+  int fileIndex = GetRealItemIndex(index);

+  if (fileIndex == kParentIndex)

+  {

+    if (FolderMode)

+      _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR);

+    return;

+  }

+  const CFileInfo &file = _files[fileIndex];

+  if (file.IsDir())

+  {

+    if (!FolderMode)

+      return;

+    _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR);

+  }

+  else

+    _pathEdit.SetText(fs2us(file.Name));

+}

+

+void CBrowseDialog::OnCreateDir()

+{

+  UString name;

+  {

+    UString enteredName;

+    Dlg_CreateFolder((HWND)*this, enteredName);

+    if (enteredName.IsEmpty())

+      return;

+    if (!CorrectFsPath(DirPrefix, enteredName, name))

+    {

+      MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name);

+      return;

+    }

+  }

+  if (name.IsEmpty())

+    return;

+

+  FString destPath;

+  if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath))

+  {

+    if (!NDir::CreateComplexDir(destPath))

+    {

+      MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath));

+    }

+    else

+    {

+      UString tempPath = DirPrefix;

+      Reload(tempPath, name);

+      SetPathEditText();

+    }

+    _list.SetFocus();

+  }

+}

+

+void CBrowseDialog::OnItemEnter()

+{

+  int index = _list.GetNextSelectedItem(-1);

+  if (index < 0)

+    return;

+  int fileIndex = GetRealItemIndex(index);

+  if (fileIndex == kParentIndex)

+    OpenParentFolder();

+  else

+  {

+    const CFileInfo &file = _files[fileIndex];

+    if (!file.IsDir())

+    {

+      if (!FolderMode)

+        FinishOnOK();

+      /*

+      MessageBox_Error_Global(*this, FolderMode ?

+            L"You must select some folder":

+            L"You must select some file");

+      */

+      return;

+    }

+    UString s = DirPrefix + fs2us(file.Name) + WCHAR_PATH_SEPARATOR;

+    HRESULT res = Reload(s, L"");

+    if (res != S_OK)

+      MessageBox_HResError(*this, res, s);

+    SetPathEditText();

+  }

+}

+

+void CBrowseDialog::FinishOnOK()

+{

+  UString s;

+  _pathEdit.GetText(s);

+  FString destPath;

+  if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath))

+  {

+    MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s);

+    return;

+  }

+  FilePath = fs2us(destPath);

+  if (FolderMode)

+    NormalizeDirPathPrefix(FilePath);

+  End(IDOK);

+}

+

+#endif

+

+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath)

+{

+  resultPath.Empty();

+

+  #ifndef UNDER_CE

+

+  #ifdef USE_MY_BROWSE_DIALOG

+  if (!IsSuperOrDevicePath(path))

+  #endif

+    return NShell::BrowseForFolder(owner, title, path, resultPath);

+

+  #endif

+

+  #ifdef USE_MY_BROWSE_DIALOG

+

+  CBrowseDialog dialog;

+  dialog.FolderMode = true;

+  if (title)

+    dialog.Title = title;

+  if (path)

+    dialog.FilePath = path;

+  if (dialog.Create(owner) != IDOK)

+    return false;

+  resultPath = dialog.FilePath;

+  #endif

+

+  return true;

+}

+

+bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,

+    LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath)

+{

+  resultPath.Empty();

+

+  #ifndef UNDER_CE

+

+  #ifdef USE_MY_BROWSE_DIALOG

+  if (!IsSuperOrDevicePath(path))

+  #endif

+  {

+    if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath))

+      return true;

+    #ifdef UNDER_CE

+    return false;

+    #else

+    // maybe we must use GetLastError in WinCE.

+    DWORD errorCode = CommDlgExtendedError();

+    const wchar_t *errorMessage = NULL;

+    switch (errorCode)

+    {

+      case 0: return false; // cancel or close obn dialog

+      case FNERR_INVALIDFILENAME: errorMessage = L"Invalid File Name"; break;

+      default: errorMessage = L"Open Dialog Error";

+    }

+    if (!errorMessage)

+      return false;

+    {

+      UString s = errorMessage;

+      s += L"\n";

+      s += path;

+      MessageBox_Error_Global(owner, s);

+    }

+    #endif

+  }

+

+  #endif

+  

+  #ifdef USE_MY_BROWSE_DIALOG

+  CBrowseDialog dialog;

+  if (title)

+    dialog.Title = title;

+  if (path)

+    dialog.FilePath = path;

+  dialog.FolderMode = false;

+  if (filter)

+    dialog.SetFilter(filter);

+  if (filterDescription)

+    dialog.FilterDescription = filterDescription;

+  if (dialog.Create(owner) != IDOK)

+    return false;

+  resultPath = dialog.FilePath;

+  #endif

+

+  return true;

+}

+

+

+#ifdef _WIN32

+

+static void RemoveDotsAndSpaces(UString &path)

+{

+  while (!path.IsEmpty())

+  {

+    wchar_t c = path.Back();

+    if (c != ' ' && c != '.')

+      return;

+    path.DeleteBack();

+  }

+}

+

+

+bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result)

+{

+  result.Empty();

+

+  UString path = path2;

+  path.Replace('/', WCHAR_PATH_SEPARATOR);

+  unsigned start = 0;

+  UString base;

+  if (NName::IsAbsolutePath(path))

+  {

+    if (IsSuperOrDevicePath(path))

+    {

+      result = path;

+      return true;

+    }

+    int pos = GetRootPrefixSize(path);

+    if (pos > 0)

+      start = pos;

+  }

+  else

+  {

+    if (IsSuperOrDevicePath(relBase))

+    {

+      result = path;

+      return true;

+    }

+    base = relBase;

+  }

+

+  /* We can't use backward, since we must change only disk paths */

+  /*

+  for (;;)

+  {

+    if (path.Len() <= start)

+      break;

+    if (DoesFileOrDirExist(us2fs(path)))

+      break;

+    if (path.Back() == WCHAR_PATH_SEPARATOR)

+    {

+      path.DeleteBack();

+      result.Insert(0, WCHAR_PATH_SEPARATOR);;

+    }

+    int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1;

+    UString cur = path.Ptr(pos);

+    RemoveDotsAndSpaces(cur);

+    result.Insert(0, cur);

+    path.DeleteFrom(pos);

+  }

+  result.Insert(0, path);

+  return true;

+  */

+

+  result += path.Left(start);

+  bool checkExist = true;

+  UString cur;

+  for (;;)

+  {

+    if (start == path.Len())

+      break;

+    int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start);

+    cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start);

+    if (checkExist)

+    {

+      CFileInfo fi;

+      if (fi.Find(us2fs(base + result + cur)))

+      {

+        if (!fi.IsDir())

+        {

+          result = path;

+          break;

+        }

+      }

+      else

+        checkExist = false;

+    }

+    if (!checkExist)

+      RemoveDotsAndSpaces(cur);

+    result += cur;

+    if (slashPos < 0)

+      break;

+    result += WCHAR_PATH_SEPARATOR;

+    start = slashPos + 1;

+  }

+  

+  return true;

+}

+

+#else

+bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result)

+{

+  result = path;

+  return true;

+}

+#endif

+

+bool Dlg_CreateFolder(HWND wnd, UString &destName)

+{

+  destName.Empty();

+  CComboDialog dlg;

+  LangString(IDS_CREATE_FOLDER, dlg.Title);

+  LangString(IDS_CREATE_FOLDER_NAME, dlg.Static);

+  LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value);

+  if (dlg.Create(wnd) != IDOK)

+    return false;

+  destName = dlg.Value;

+  return true;

+}

diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h
new file mode 100644
index 0000000..306d19f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.h
@@ -0,0 +1,21 @@
+// BrowseDialog.h

+

+#ifndef __BROWSE_DIALOG_H

+#define __BROWSE_DIALOG_H

+

+#include "../../../Common/MyString.h"

+

+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);

+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:

+     - 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 */

+

+bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);

+

+bool Dlg_CreateFolder(HWND wnd, UString &destName);

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/CPP/7zip/UI/FileManager/BrowseDialogRes.h
new file mode 100644
index 0000000..f211b73
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialogRes.h
@@ -0,0 +1,9 @@
+#define IDD_BROWSE  95

+

+#define IDL_BROWSE         100

+#define IDT_BROWSE_FOLDER  101

+#define IDE_BROWSE_PATH    102

+#define IDC_BROWSE_FILTER  103

+

+#define IDB_BROWSE_PARENT     110

+#define IDB_BROWSE_CREATE_DIR 112

diff --git a/CPP/7zip/UI/FileManager/ComboDialog.cpp b/CPP/7zip/UI/FileManager/ComboDialog.cpp
new file mode 100644
index 0000000..e846c56
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialog.cpp
@@ -0,0 +1,64 @@
+// ComboDialog.cpp

+

+#include "StdAfx.h"

+#include "ComboDialog.h"

+

+#include "../../../Windows/Control/Static.h"

+

+#ifdef LANG

+#include "LangUtils.h"

+#endif

+

+using namespace NWindows;

+

+bool CComboDialog::OnInit()

+{

+  #ifdef LANG

+  LangSetDlgItems(*this, NULL, 0);

+  #endif

+  _comboBox.Attach(GetItem(IDC_COMBO));

+

+  /*

+  // why it doesn't work ?

+  DWORD style = _comboBox.GetStyle();

+  if (Sorted)

+    style |= CBS_SORT;

+  else

+    style &= ~CBS_SORT;

+  _comboBox.SetStyle(style);

+  */

+  SetText(Title);

+  

+  NControl::CStatic staticContol;

+  staticContol.Attach(GetItem(IDT_COMBO));

+  staticContol.SetText(Static);

+  _comboBox.SetText(Value);

+  FOR_VECTOR (i, Strings)

+    _comboBox.AddString(Strings[i]);

+  NormalizeSize();

+  return CModalDialog::OnInit();

+}

+

+bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)

+{

+  int mx, my;

+  GetMargins(8, mx, my);

+  int bx1, bx2, by;

+  GetItemSizes(IDCANCEL, bx1, by);

+  GetItemSizes(IDOK, bx2, by);

+  int y = ySize - my - by;

+  int x = xSize - mx - bx1;

+

+  InvalidateRect(NULL);

+

+  MoveItem(IDCANCEL, x, y, bx1, by);

+  MoveItem(IDOK, x - mx - bx2, y, bx2, by);

+  ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);

+  return false;

+}

+

+void CComboDialog::OnOK()

+{

+  _comboBox.GetText(Value);

+  CModalDialog::OnOK();

+}

diff --git a/CPP/7zip/UI/FileManager/ComboDialog.h b/CPP/7zip/UI/FileManager/ComboDialog.h
new file mode 100644
index 0000000..6869cff
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialog.h
@@ -0,0 +1,28 @@
+// ComboDialog.h

+

+#ifndef __COMBO_DIALOG_H

+#define __COMBO_DIALOG_H

+

+#include "../../../Windows/Control/ComboBox.h"

+#include "../../../Windows/Control/Dialog.h"

+

+#include "ComboDialogRes.h"

+

+class CComboDialog: public NWindows::NControl::CModalDialog

+{

+  NWindows::NControl::CComboBox _comboBox;

+  virtual void OnOK();

+  virtual bool OnInit();

+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);

+public:

+  // bool Sorted;

+  UString Title;

+  UString Static;

+  UString Value;

+  UStringVector Strings;

+  

+  // CComboDialog(): Sorted(false) {};

+  INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); }

+};

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/ComboDialogRes.h b/CPP/7zip/UI/FileManager/ComboDialogRes.h
new file mode 100644
index 0000000..98938b6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialogRes.h
@@ -0,0 +1,4 @@
+#define IDD_COMBO   98

+

+#define IDT_COMBO  100

+#define IDC_COMBO  101

diff --git a/CPP/7zip/UI/FileManager/DialogSize.h b/CPP/7zip/UI/FileManager/DialogSize.h
new file mode 100644
index 0000000..bbce159
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/DialogSize.h
@@ -0,0 +1,16 @@
+// DialogSize.h

+

+#ifndef __DIALOG_SIZE_H

+#define __DIALOG_SIZE_H

+

+#include "../../../Windows/Control/Dialog.h"

+

+#ifdef UNDER_CE

+#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);

+#define SIZED_DIALOG(big) (isBig ? big : big ## _2)

+#else

+#define BIG_DIALOG_SIZE(x, y)

+#define SIZED_DIALOG(big) big

+#endif

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
new file mode 100644
index 0000000..bb14e52
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -0,0 +1,898 @@
+// ExtractCallback.cpp

+

+#include "StdAfx.h"

+

+

+#include "../../../Common/ComTry.h"

+#include "../../../Common/IntToString.h"

+#include "../../../Common/Lang.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/PropVariantConv.h"

+

+#include "../../Common/FilePathAutoRename.h"

+#include "../../Common/StreamUtils.h"

+#include "../Common/ExtractingFilePath.h"

+

+#ifndef _SFX

+#include "../Common/ZipRegistry.h"

+#endif

+

+#include "../GUI/ExtractRes.h"

+

+#include "ExtractCallback.h"

+#include "FormatUtils.h"

+#include "LangUtils.h"

+#include "OverwriteDialog.h"

+#ifndef _NO_CRYPTO

+#include "PasswordDialog.h"

+#endif

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NFind;

+

+CExtractCallbackImp::~CExtractCallbackImp() {}

+

+void CExtractCallbackImp::Init()

+{

+  NumArchiveErrors = 0;

+  ThereAreMessageErrors = false;

+  #ifndef _SFX

+  NumFolders = NumFiles = 0;

+  NeedAddFile = false;

+  #endif

+}

+

+void CExtractCallbackImp::AddError_Message(LPCWSTR s)

+{

+  ThereAreMessageErrors = true;

+  ProgressDialog->Sync.AddError_Message(s);

+}

+

+#ifndef _SFX

+

+STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64

+  #ifndef _SFX

+  numFiles

+  #endif

+  )

+{

+  #ifndef _SFX

+  ProgressDialog->Sync.Set_NumFilesTotal(numFiles);

+  #endif

+  return S_OK;

+}

+

+#endif

+

+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total)

+{

+  ProgressDialog->Sync.Set_NumBytesTotal(total);

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value)

+{

+  return ProgressDialog->Sync.Set_NumBytesCur(value);

+}

+

+HRESULT CExtractCallbackImp::Open_CheckBreak()

+{

+  return ProgressDialog->Sync.CheckStop();

+}

+

+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+{

+  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesTotal(*numFiles);

+  return S_OK;

+}

+

+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)

+{

+  // if (numFiles != NULL) ProgressDialog->Sync.SetNumFilesCur(*numFiles);

+  return ProgressDialog->Sync.CheckStop();

+}

+

+#ifndef _NO_CRYPTO

+

+HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)

+{

+  return CryptoGetTextPassword(password);

+}

+

+HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)

+{

+  passwordIsDefined = PasswordIsDefined;

+  password = Password;

+  return S_OK;

+}

+

+bool CExtractCallbackImp::Open_WasPasswordAsked()

+{

+  return PasswordWasAsked;

+}

+

+void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()

+{

+  PasswordWasAsked = false;

+}

+

+#endif

+

+

+#ifndef _SFX

+STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  ProgressDialog->Sync.Set_Ratio(inSize, outSize);

+  return S_OK;

+}

+#endif

+

+/*

+STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total)

+{

+  ProgressDialog->Sync.SetNumFilesTotal(total);

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)

+{

+  if (value != NULL)

+    ProgressDialog->Sync.SetNumFilesCur(*value);

+  return S_OK;

+}

+*/

+

+STDMETHODIMP CExtractCallbackImp::AskOverwrite(

+    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

+    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

+    Int32 *answer)

+{

+  COverwriteDialog dialog;

+

+  dialog.OldFileInfo.SetTime(existTime);

+  dialog.OldFileInfo.SetSize(existSize);

+  dialog.OldFileInfo.Name = existName;

+

+  dialog.NewFileInfo.SetTime(newTime);

+  dialog.NewFileInfo.SetSize(newSize);

+  dialog.NewFileInfo.Name = newName;

+  

+  ProgressDialog->WaitCreating();

+  INT_PTR writeAnswer = dialog.Create(*ProgressDialog);

+  

+  switch (writeAnswer)

+  {

+    case IDCANCEL:        *answer = NOverwriteAnswer::kCancel; return E_ABORT;

+    case IDYES:           *answer = NOverwriteAnswer::kYes; break;

+    case IDNO:            *answer = NOverwriteAnswer::kNo; break;

+    case IDB_YES_TO_ALL:  *answer = NOverwriteAnswer::kYesToAll; break;

+    case IDB_NO_TO_ALL:   *answer = NOverwriteAnswer::kNoToAll; break;

+    case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;

+    default: return E_FAIL;

+  }

+  return S_OK;

+}

+

+

+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)

+{

+  _isFolder = isFolder;

+  return SetCurrentFilePath2(name);

+}

+

+STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s)

+{

+  AddError_Message(s);

+  return S_OK;

+}

+

+HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path)

+{

+  ThereAreMessageErrors = true;

+  ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path));

+  return S_OK;

+}

+

+#ifndef _SFX

+

+STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s)

+{

+  AddError_Message(s);

+  return S_OK;

+}

+

+#endif

+

+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted)

+{

+  switch (opRes)

+  {

+    case NArchive::NExtract::NOperationResult::kOK:

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

+      }

+

+      AddError_Message(s);

+    }

+  }

+  

+  #ifndef _SFX

+  if (_isFolder)

+    NumFolders++;

+  else

+    NumFiles++;

+  ProgressDialog->Sync.Set_NumFilesCur(NumFiles);

+  #endif

+  

+  return S_OK;

+}

+

+////////////////////////////////////////

+// IExtractCallbackUI

+

+HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)

+{

+  #ifndef _SFX

+  RINOK(ProgressDialog->Sync.CheckStop());

+  ProgressDialog->Sync.Set_TitleFileName(name);

+  #endif

+  _currentArchivePath = name;

+  return S_OK;

+}

+

+HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)

+{

+  _currentFilePath = path;

+  #ifndef _SFX

+  ProgressDialog->Sync.Set_FilePath(path);

+  #endif

+  return S_OK;

+}

+

+#ifndef _SFX

+

+HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)

+{

+  #ifndef _SFX

+  if (NeedAddFile)

+    NumFiles++;

+  NeedAddFile = true;

+  ProgressDialog->Sync.Set_NumFilesCur(NumFiles);

+  #endif

+  return SetCurrentFilePath2(path);

+}

+

+#endif

+

+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,

+  IDS_EXTRACT_MSG_HEADERS_ERROR,

+  IDS_EXTRACT_MSG_HEADERS_ERROR,

+  IDS_OPEN_MSG_UNAVAILABLE_START,

+  IDS_OPEN_MSG_UNCONFIRMED_START,

+  IDS_EXTRACT_MSG_UEXPECTED_END,

+  IDS_EXTRACT_MSG_DATA_AFTER_END,

+  IDS_EXTRACT_MSG_UNSUPPORTED_METHOD,

+  IDS_OPEN_MSG_UNSUPPORTED_FEATURE,

+  IDS_EXTRACT_MSG_DATA_ERROR,

+  IDS_EXTRACT_MSG_CRC_ERROR

+};

+

+UString GetOpenArcErrorMessage(UInt32 errorFlags)

+{

+  UString s;

+  for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++)

+  {

+    UInt32 f = ((UInt32)1 << i);

+    if ((errorFlags & f) == 0)

+      continue;

+    UInt32 id = k_ErrorFlagsIds[i];

+    UString m = LangString(id);

+    if (m.IsEmpty())

+      continue;

+    if (f == kpv_ErrorFlags_EncryptedHeadersError)

+    {

+      m += L" : ";

+      m += LangString(IDS_EXTRACT_MSG_WRONG_PSW);

+    }

+    if (!s.IsEmpty())

+      s += L'\n';

+    s += m;

+    errorFlags &= ~f;

+  }

+  if (errorFlags != 0)

+  {

+    char sz[16];

+    sz[0] = '0';

+    sz[1] = 'x';

+    ConvertUInt32ToHex(errorFlags, sz + 2);

+    if (!s.IsEmpty())

+      s += L'\n';

+    s += GetUnicodeString(AString(sz));

+  }

+  return s;

+}

+

+HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name,

+    UInt32 errorFlags, const wchar_t *errors,

+    UInt32 warningFlags, const wchar_t *warnings)

+{

+  NumArchiveErrors++;

+

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

+{

+  if (result == S_OK)

+    return result;

+  NumArchiveErrors++;

+  if (result == E_ABORT || result == ERROR_DISK_FULL)

+    return result;

+  MessageError(_currentFilePath);

+  MessageError(NError::MyFormatMessage(result));

+  return S_OK;

+}

+

+#ifndef _NO_CRYPTO

+

+HRESULT CExtractCallbackImp::SetPassword(const UString &password)

+{

+  PasswordIsDefined = true;

+  Password = password;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)

+{

+  PasswordWasAsked = true;

+  if (!PasswordIsDefined)

+  {

+    CPasswordDialog dialog;

+    #ifndef _SFX

+    bool showPassword = NExtract::Read_ShowPassword();

+    dialog.ShowPassword = showPassword;

+    #endif

+    ProgressDialog->WaitCreating();

+    if (dialog.Create(*ProgressDialog) != IDOK)

+      return E_ABORT;

+    Password = dialog.Password;

+    PasswordIsDefined = true;

+    #ifndef _SFX

+    if (dialog.ShowPassword != showPassword)

+      NExtract::Save_ShowPassword(dialog.ShowPassword);

+    #endif

+  }

+  return StringToBstr(Password, password);

+}

+

+#endif

+

+#ifndef _SFX

+

+STDMETHODIMP CExtractCallbackImp::AskWrite(

+    const wchar_t *srcPath, Int32 srcIsFolder,

+    const FILETIME *srcTime, const UInt64 *srcSize,

+    const wchar_t *destPath,

+    BSTR *destPathResult,

+    Int32 *writeAnswer)

+{

+  UString destPathResultTemp = destPath;

+

+  // RINOK(StringToBstr(destPath, destPathResult));

+

+  *destPathResult = 0;

+  *writeAnswer = BoolToInt(false);

+

+  FString destPathSys = us2fs(destPath);

+  bool srcIsFolderSpec = IntToBool(srcIsFolder);

+  CFileInfo destFileInfo;

+  

+  if (destFileInfo.Find(destPathSys))

+  {

+    if (srcIsFolderSpec)

+    {

+      if (!destFileInfo.IsDir())

+      {

+        RINOK(MessageError("can not replace file with folder with same name: ", destPathSys));

+        return E_ABORT;

+      }

+      *writeAnswer = BoolToInt(false);

+      return S_OK;

+    }

+  

+    if (destFileInfo.IsDir())

+    {

+      RINOK(MessageError("can not replace folder with file with same name: ", destPathSys));

+      return E_FAIL;

+    }

+

+    switch (OverwriteMode)

+    {

+      case NExtract::NOverwriteMode::kSkip:

+        return S_OK;

+      case NExtract::NOverwriteMode::kAsk:

+      {

+        Int32 overwiteResult;

+        UString destPathSpec = destPath;

+        int slashPos = destPathSpec.ReverseFind(L'/');

+        #ifdef _WIN32

+        int slash1Pos = destPathSpec.ReverseFind(L'\\');

+        slashPos = MyMax(slashPos, slash1Pos);

+        #endif

+        destPathSpec.DeleteFrom(slashPos + 1);

+        destPathSpec += fs2us(destFileInfo.Name);

+

+        RINOK(AskOverwrite(

+            destPathSpec,

+            &destFileInfo.MTime, &destFileInfo.Size,

+            srcPath,

+            srcTime, srcSize,

+            &overwiteResult));

+        

+        switch (overwiteResult)

+        {

+          case NOverwriteAnswer::kCancel: return E_ABORT;

+          case NOverwriteAnswer::kNo: return S_OK;

+          case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;

+          case NOverwriteAnswer::kYes: break;

+          case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break;

+          case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break;

+          default:

+            return E_FAIL;

+        }

+      }

+    }

+    

+    if (OverwriteMode == NExtract::NOverwriteMode::kRename)

+    {

+      if (!AutoRenamePath(destPathSys))

+      {

+        RINOK(MessageError("can not create name for file: ", destPathSys));

+        return E_ABORT;

+      }

+      destPathResultTemp = fs2us(destPathSys);

+    }

+    else

+      if (!NDir::DeleteFileAlways(destPathSys))

+      {

+        RINOK(MessageError("can not delete output file: ", destPathSys));

+        return E_ABORT;

+      }

+  }

+  *writeAnswer = BoolToInt(true);

+  return StringToBstr(destPathResultTemp, destPathResult);

+}

+

+

+STDMETHODIMP CExtractCallbackImp::UseExtractToStream(Int32 *res)

+{

+  *res = BoolToInt(StreamMode);

+  return S_OK;

+}

+

+static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined)

+{

+  ftDefined = false;

+  NCOM::CPropVariant prop;

+  RINOK(getProp->GetProp(propID, &prop));

+  if (prop.vt == VT_FILETIME)

+  {

+    ft = prop.filetime;

+    ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0);

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+

+static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result)

+{

+  NCOM::CPropVariant prop;

+  result = false;

+  RINOK(getProp->GetProp(propID, &prop));

+  if (prop.vt == VT_BOOL)

+    result = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+

+STDMETHODIMP CExtractCallbackImp::GetStream7(const wchar_t *name,

+    Int32 isDir,

+    ISequentialOutStream **outStream, Int32 askExtractMode,

+    IGetProp *getProp)

+{

+  COM_TRY_BEGIN

+  *outStream = 0;

+  _newVirtFileWasAdded = false;

+  _hashStreamWasUsed = false;

+  _needUpdateStat = false;

+

+  if (_hashStream)

+    _hashStreamSpec->ReleaseStream();

+

+  GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream);

+

+  if (!ProcessAltStreams && _isAltStream)

+    return S_OK;

+

+  _filePath = name;

+  _isFolder = IntToBool(isDir);

+  _curSize = 0;

+  _curSizeDefined = false;

+

+  UInt64 size = 0;

+  bool sizeDefined;

+  {

+    NCOM::CPropVariant prop;

+    RINOK(getProp->GetProp(kpidSize, &prop));

+    sizeDefined = ConvertPropVariantToUInt64(prop, size);

+  }

+

+  if (sizeDefined)

+  {

+    _curSize = size;

+    _curSizeDefined = true;

+  }

+

+  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract &&

+      askExtractMode != NArchive::NExtract::NAskMode::kTest)

+    return S_OK;

+

+  _needUpdateStat = true;

+  

+  CMyComPtr<ISequentialOutStream> outStreamLoc;

+  

+  if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract)

+  {

+    CVirtFile &file = VirtFileSystemSpec->AddNewFile();

+    _newVirtFileWasAdded = true;

+    file.Name = name;

+    file.IsDir = IntToBool(isDir);

+    file.IsAltStream = _isAltStream;

+    file.Size = 0;

+

+    RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined));

+    RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined));

+    RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined));

+

+    NCOM::CPropVariant prop;

+    RINOK(getProp->GetProp(kpidAttrib, &prop));

+    if (prop.vt == VT_UI4)

+    {

+      file.Attrib = prop.ulVal;

+      file.AttribDefined = true;

+    }

+    // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY;

+

+    file.ExpectedSize = 0;

+    if (sizeDefined)

+      file.ExpectedSize = size;

+    outStreamLoc = VirtFileSystem;

+  }

+

+  if (_hashStream)

+  {

+    {

+      _hashStreamSpec->SetStream(outStreamLoc);

+      outStreamLoc = _hashStream;

+      _hashStreamSpec->Init(true);

+      _hashStreamWasUsed = true;

+    }

+  }

+

+  if (outStreamLoc)

+    *outStream = outStreamLoc.Detach();

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)

+{

+  COM_TRY_BEGIN

+  _needUpdateStat = (

+      askExtractMode == NArchive::NExtract::NAskMode::kExtract ||

+      askExtractMode == NArchive::NExtract::NAskMode::kTest);

+

+  /*

+  _extractMode = false;

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract:

+      if (_testMode)

+        askExtractMode = NArchive::NExtract::NAskMode::kTest;

+      else

+        _extractMode = true;

+      break;

+  };

+  */

+  return SetCurrentFilePath2(_filePath);

+  COM_TRY_END

+}

+

+STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted)

+{

+  COM_TRY_BEGIN

+  if (VirtFileSystem && _newVirtFileWasAdded)

+  {

+    // FIXME: probably we must request file size from VirtFileSystem

+    // _curSize = VirtFileSystem->GetLastFileSize()

+    // _curSizeDefined = true;

+    RINOK(VirtFileSystemSpec->CloseMemFile());

+  }

+  if (_hashStream && _hashStreamWasUsed)

+  {

+    _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath);

+    _curSize = _hashStreamSpec->GetSize();

+    _curSizeDefined = true;

+    _hashStreamSpec->ReleaseStream();

+    _hashStreamWasUsed = false;

+  }

+  else if (_hashCalc && _needUpdateStat)

+  {

+    _hashCalc->SetSize(_curSize);

+    _hashCalc->Final(_isFolder, _isAltStream, _filePath);

+  }

+  return SetOperationResult(opRes, encrypted);

+  COM_TRY_END

+}

+

+

+static const size_t k_SizeT_MAX = (size_t)((size_t)0 - 1);

+

+static const UInt32 kBlockSize = ((UInt32)1 << 31);

+

+STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (!_fileMode)

+  {

+    CVirtFile &file = Files.Back();

+    size_t rem = file.Data.Size() - (size_t)file.Size;

+    bool useMem = true;

+    if (rem < size)

+    {

+      UInt64 b = 0;

+      if (file.Data.Size() == 0)

+        b = file.ExpectedSize;

+      UInt64 a = file.Size + size;

+      if (b < a)

+        b = a;

+      a = (UInt64)file.Data.Size() * 2;

+      if (b < a)

+        b = a;

+      useMem = false;

+      if (b <= k_SizeT_MAX && b <= MaxTotalAllocSize)

+        useMem = file.Data.ReAlloc_KeepData((size_t)b, (size_t)file.Size);

+    }

+    if (useMem)

+    {

+      memcpy(file.Data + file.Size, data, size);

+      file.Size += size;

+      if (processedSize)

+        *processedSize = (UInt32)size;

+      return S_OK;

+    }

+    _fileMode = true;

+  }

+  RINOK(FlushToDisk(false));

+  return _outFileStream->Write(data, size, processedSize);

+}

+

+HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)

+{

+  if (!_outFileStream)

+  {

+    _outFileStreamSpec = new COutFileStream;

+    _outFileStream = _outFileStreamSpec;

+  }

+  while (_numFlushed < Files.Size())

+  {

+    const CVirtFile &file = Files[_numFlushed];

+    const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name));

+    if (!_fileIsOpen)

+    {

+      if (!_outFileStreamSpec->Create(path, false))

+      {

+        _outFileStream.Release();

+        return E_FAIL;

+        // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath));

+      }

+      _fileIsOpen = true;

+      RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size));

+    }

+    if (_numFlushed == Files.Size() - 1 && !closeLast)

+      break;

+    if (file.CTimeDefined ||

+        file.ATimeDefined ||

+        file.MTimeDefined)

+      _outFileStreamSpec->SetTime(

+          file.CTimeDefined ? &file.CTime : NULL,

+          file.ATimeDefined ? &file.ATime : NULL,

+          file.MTimeDefined ? &file.MTime : NULL);

+    _outFileStreamSpec->Close();

+    _numFlushed++;

+    _fileIsOpen = false;

+    if (file.AttribDefined)

+      NDir::SetFileAttrib(path, file.Attrib);

+  }

+  return S_OK;

+}

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
new file mode 100644
index 0000000..fea83d6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -0,0 +1,330 @@
+// ExtractCallback.h

+

+#ifndef __EXTRACT_CALLBACK_H

+#define __EXTRACT_CALLBACK_H

+

+#include "../../../../C/Alloc.h"

+

+#include "../../../Common/MyCom.h"

+#include "../../../Common/StringConvert.h"

+

+#ifndef _SFX

+#include "../Agent/IFolderArchive.h"

+#endif

+

+#include "../Common/ArchiveExtractCallback.h"

+#include "../Common/ArchiveOpenCallback.h"

+

+#ifndef _NO_CRYPTO

+#include "../../IPassword.h"

+#endif

+

+#ifndef _SFX

+#include "IFolder.h"

+#endif

+

+#include "ProgressDialog2.h"

+

+#ifdef LANG

+#include "LangUtils.h"

+#endif

+

+#ifndef _SFX

+

+class CGrowBuf

+{

+  Byte *_items;

+  size_t _size;

+

+  CGrowBuf(const CGrowBuf &buffer);

+  void operator=(const CGrowBuf &buffer);

+

+public:

+  bool ReAlloc_KeepData(size_t newSize, size_t keepSize)

+  {

+    void *buf = MyAlloc(newSize);

+    if (!buf)

+      return false;

+    memcpy(buf, _items, keepSize);

+    MyFree(_items);

+    _items = (Byte *)buf;

+    _size = newSize;

+    return true;

+  }

+

+  CGrowBuf(): _items(0), _size(0) {}

+  ~CGrowBuf() { MyFree(_items); }

+

+  operator Byte *() { return _items; };

+  operator const Byte *() const { return _items; };

+  size_t Size() const { return _size; }

+};

+

+struct CVirtFile

+{

+  CGrowBuf Data;

+  

+  UInt64 Size; // real size

+  UInt64 ExpectedSize; // the size from props request. 0 if unknown

+

+  UString Name;

+

+  bool CTimeDefined;

+  bool ATimeDefined;

+  bool MTimeDefined;

+  bool AttribDefined;

+  

+  bool IsDir;

+  bool IsAltStream;

+  

+  DWORD Attrib;

+

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+

+  CVirtFile():

+    CTimeDefined(false),

+    ATimeDefined(false),

+    MTimeDefined(false),

+    AttribDefined(false),

+    IsDir(false),

+    IsAltStream(false) {}

+};

+

+class CVirtFileSystem:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  UInt64 _totalAllocSize;

+

+  size_t _pos;

+  unsigned _numFlushed;

+  bool _fileIsOpen;

+  bool _fileMode;

+  COutFileStream *_outFileStreamSpec;

+  CMyComPtr<ISequentialOutStream> _outFileStream;

+public:

+  CObjectVector<CVirtFile> Files;

+  UInt64 MaxTotalAllocSize;

+  FString DirPrefix;

+ 

+  CVirtFile &AddNewFile()

+  {

+    if (!Files.IsEmpty())

+    {

+      MaxTotalAllocSize -= Files.Back().Data.Size();

+    }

+    return Files.AddNew();

+  }

+  HRESULT CloseMemFile()

+  {

+    if (_fileMode)

+    {

+      return FlushToDisk(true);

+    }

+    CVirtFile &file = Files.Back();

+    if (file.Data.Size() != file.Size)

+    {

+      file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);

+    }

+    return S_OK;

+  }

+

+  bool IsStreamInMem() const

+  {

+    if (_fileMode)

+      return false;

+    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) {}

+

+  void Init()

+  {

+    _totalAllocSize = 0;

+    _fileMode = false;

+    _pos = 0;

+    _numFlushed = 0;

+    _fileIsOpen = false;

+  }

+

+  HRESULT CloseFile(const FString &path);

+  HRESULT FlushToDisk(bool closeLast);

+  size_t GetPos() const { return _pos; }

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+#endif

+  

+class CExtractCallbackImp:

+  public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback

+  public IOpenCallbackUI,

+  #ifndef _SFX

+  public IFolderOperationsExtractCallback,

+  public IFolderExtractToStreamCallback,

+  public ICompressProgressInfo,

+  #endif

+  #ifndef _NO_CRYPTO

+  public ICryptoGetTextPassword,

+  #endif

+  public CMyUnknownImp

+{

+  HRESULT MessageError(const char *message, const FString &path);

+public:

+  MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)

+  #ifndef _SFX

+  MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)

+  MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)

+  MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)

+  #endif

+  #ifndef _NO_CRYPTO

+  MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)

+  #endif

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  INTERFACE_IProgress(;)

+  INTERFACE_IOpenCallbackUI(;)

+

+  // IFolderArchiveExtractCallback

+  // 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

+

+  #ifndef _SFX

+  // IFolderOperationsExtractCallback

+  STDMETHOD(AskWrite)(

+      const wchar_t *srcPath,

+      Int32 srcIsFolder,

+      const FILETIME *srcTime,

+      const UInt64 *srcSize,

+      const wchar_t *destPathRequest,

+      BSTR *destPathResult,

+      Int32 *writeAnswer);

+  STDMETHOD(ShowMessage)(const wchar_t *message);

+  STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);

+  STDMETHOD(SetNumFiles)(UInt64 numFiles);

+  INTERFACE_IFolderExtractToStreamCallback(;)

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+  #endif

+

+  // ICryptoGetTextPassword

+  #ifndef _NO_CRYPTO

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+  #endif

+

+private:

+  UString _currentArchivePath;

+  bool _needWriteArchivePath;

+

+  UString _currentFilePath;

+  bool _isFolder;

+

+  bool _isAltStream;

+  UInt64 _curSize;

+  bool _curSizeDefined;

+  UString _filePath;

+  // bool _extractMode;

+  // bool _testMode;

+  bool _newVirtFileWasAdded;

+  bool _needUpdateStat;

+

+

+  HRESULT SetCurrentFilePath2(const wchar_t *filePath);

+  void AddError_Message(LPCWSTR message);

+

+  #ifndef _SFX

+  bool _hashStreamWasUsed;

+  COutStreamWithHash *_hashStreamSpec;

+  CMyComPtr<ISequentialOutStream> _hashStream;

+  IHashCalc *_hashCalc; // it's for stat in Test operation

+  #endif

+

+public:

+

+  #ifndef _SFX

+  CVirtFileSystem *VirtFileSystemSpec;

+  CMyComPtr<ISequentialOutStream> VirtFileSystem;

+  #endif

+

+  bool ProcessAltStreams;

+

+  bool StreamMode;

+

+  CProgressDialog *ProgressDialog;

+  #ifndef _SFX

+  UInt64 NumFolders;

+  UInt64 NumFiles;

+  bool NeedAddFile;

+  #endif

+  UInt32 NumArchiveErrors;

+  bool ThereAreMessageErrors;

+  NExtract::NOverwriteMode::EEnum OverwriteMode;

+

+  #ifndef _NO_CRYPTO

+  bool PasswordIsDefined;

+  bool PasswordWasAsked;

+  UString Password;

+  #endif

+

+  CExtractCallbackImp():

+    #ifndef _NO_CRYPTO

+    PasswordIsDefined(false),

+    PasswordWasAsked(false),

+    #endif

+    OverwriteMode(NExtract::NOverwriteMode::kAsk),

+    StreamMode(false),

+    ProcessAltStreams(true)

+    #ifndef _SFX

+    , _hashCalc(NULL)

+    #endif

+    {}

+   

+  ~CExtractCallbackImp();

+  void Init();

+

+  #ifndef _SFX

+  void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }

+

+  void SetHashMethods(IHashCalc *hash)

+  {

+    if (!hash)

+      return;

+    _hashStreamSpec = new COutStreamWithHash;

+    _hashStream = _hashStreamSpec;

+    _hashStreamSpec->_hash = hash;

+  }

+  #endif

+

+  bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }

+};

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp
new file mode 100644
index 0000000..4f7ef74
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FormatUtils.cpp
@@ -0,0 +1,28 @@
+// FormatUtils.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+

+#include "FormatUtils.h"

+

+#include "LangUtils.h"

+

+UString NumberToString(UInt64 number)

+{

+  wchar_t numberString[32];

+  ConvertUInt64ToString(number, numberString);

+  return numberString;

+}

+

+UString MyFormatNew(const UString &format, const UString &argument)

+{

+  UString result = format;

+  result.Replace(L"{0}", argument);

+  return result;

+}

+

+UString MyFormatNew(UINT resourceID, const UString &argument)

+{

+  return MyFormatNew(LangString(resourceID), argument);

+}

diff --git a/CPP/7zip/UI/FileManager/FormatUtils.h b/CPP/7zip/UI/FileManager/FormatUtils.h
new file mode 100644
index 0000000..f221cd2
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FormatUtils.h
@@ -0,0 +1,14 @@
+// FormatUtils.h

+

+#ifndef __FORMAT_UTILS_H

+#define __FORMAT_UTILS_H

+

+#include "../../../Common/MyTypes.h"

+#include "../../../Common/MyString.h"

+

+UString NumberToString(UInt64 number);

+

+UString MyFormatNew(const UString &format, const UString &argument);

+UString MyFormatNew(UINT resourceID, const UString &argument);

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h
new file mode 100644
index 0000000..d1d1477
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangUtils.h
@@ -0,0 +1,38 @@
+// LangUtils.h

+

+#ifndef __LANG_UTILS_H

+#define __LANG_UTILS_H

+

+#include "../../../Windows/ResourceString.h"

+

+#ifdef LANG

+

+extern UString g_LangID;

+

+struct CIDLangPair

+{

+  UInt32 ControlID;

+  UInt32 LangID;

+};

+

+void ReloadLang();

+void LoadLangOneTime();

+FString GetLangDirPrefix();

+

+void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);

+void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);

+void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);

+void LangSetWindowText(HWND window, UInt32 langID);

+

+UString LangString(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); }

+

+#endif

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/MyWindowsNew.h b/CPP/7zip/UI/FileManager/MyWindowsNew.h
new file mode 100644
index 0000000..c0fe843
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MyWindowsNew.h
@@ -0,0 +1,76 @@
+// MyWindowsNew.h

+

+#ifndef __MY_WINDOWS_NEW_H

+#define __MY_WINDOWS_NEW_H

+

+#ifdef _MSC_VER

+

+#include <ShObjIdl.h>

+

+#ifndef __ITaskbarList3_INTERFACE_DEFINED__

+#define __ITaskbarList3_INTERFACE_DEFINED__

+

+typedef enum THUMBBUTTONFLAGS

+{

+  THBF_ENABLED = 0,

+  THBF_DISABLED = 0x1,

+  THBF_DISMISSONCLICK = 0x2,

+  THBF_NOBACKGROUND = 0x4,

+  THBF_HIDDEN = 0x8,

+  THBF_NONINTERACTIVE = 0x10

+} THUMBBUTTONFLAGS;

+

+typedef enum THUMBBUTTONMASK

+{

+  THB_BITMAP = 0x1,

+  THB_ICON = 0x2,

+  THB_TOOLTIP = 0x4,

+  THB_FLAGS = 0x8

+} THUMBBUTTONMASK;

+

+// #include <pshpack8.h>

+

+typedef struct THUMBBUTTON

+{

+  THUMBBUTTONMASK dwMask;

+  UINT iId;

+  UINT iBitmap;

+  HICON hIcon;

+  WCHAR szTip[260];

+  THUMBBUTTONFLAGS dwFlags;

+} THUMBBUTTON;

+

+typedef struct THUMBBUTTON *LPTHUMBBUTTON;

+

+typedef enum TBPFLAG

+{

+  TBPF_NOPROGRESS = 0,

+  TBPF_INDETERMINATE = 0x1,

+  TBPF_NORMAL = 0x2,

+  TBPF_ERROR = 0x4,

+  TBPF_PAUSED = 0x8

+} TBPFLAG;

+

+DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF);

+

+struct ITaskbarList3: public ITaskbarList2

+{

+  STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0;

+  STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0;

+  STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0;

+  STDMETHOD(UnregisterTab)(HWND hwndTab) = 0;

+  STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0;

+  STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0;

+  STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;

+  STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;

+  STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0;

+  STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0;

+  STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0;

+  STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0;

+};

+

+#endif

+

+#endif

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
new file mode 100644
index 0000000..d945945
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -0,0 +1,119 @@
+// OverwriteDialog.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/PropVariantConv.h"

+#include "../../../Windows/ResourceString.h"

+

+#include "../../../Windows/Control/Static.h"

+

+#include "FormatUtils.h"

+#include "LangUtils.h"

+#include "OverwriteDialog.h"

+

+#include "PropertyNameRes.h"

+

+using namespace NWindows;

+

+#ifdef LANG

+static const UInt32 kLangIDs[] =

+{

+  IDT_OVERWRITE_HEADER,

+  IDT_OVERWRITE_QUESTION_BEGIN,

+  IDT_OVERWRITE_QUESTION_END,

+  IDB_YES_TO_ALL,

+  IDB_NO_TO_ALL,

+  IDB_AUTO_RENAME

+};

+#endif

+

+static const unsigned kCurrentFileNameSizeLimit = 82;

+static const unsigned kCurrentFileNameSizeLimit2 = 30;

+

+void COverwriteDialog::ReduceString(UString &s)

+{

+  unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2;

+  if (s.Len() > size)

+  {

+    s.Delete(size / 2, s.Len() - size);

+    s.Insert(size / 2, L" ... ");

+  }

+}

+

+void COverwriteDialog::SetFileInfoControl(int textID, int iconID,

+    const NOverwriteDialog::CFileInfo &fileInfo)

+{

+  UString sizeString;

+  if (fileInfo.SizeIsDefined)

+    sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));

+

+  const UString &fileName = fileInfo.Name;

+  int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);

+  UString s1 = fileName.Left(slashPos + 1);

+  UString s2 = fileName.Ptr(slashPos + 1);

+

+  ReduceString(s1);

+  ReduceString(s2);

+  

+  UString s = s1;

+  s += L'\n';

+  s += s2;

+  s += L'\n';

+  s += sizeString;

+  s += L'\n';

+

+  if (fileInfo.TimeIsDefined)

+  {

+    FILETIME localFileTime;

+    if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))

+      throw 4190402;

+    s += LangString(IDS_PROP_MTIME);

+    s += L": ";

+    wchar_t t[32];

+    ConvertFileTimeToString(localFileTime, t);

+    s += t;

+  }

+

+  NControl::CDialogChildControl control;

+  control.Init(*this, textID);

+  control.SetText(s);

+

+  SHFILEINFO shellFileInfo;

+  if (::SHGetFileInfo(

+      GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo,

+      sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON))

+  {

+    NControl::CStatic staticContol;

+    staticContol.Attach(GetItem(iconID));

+    staticContol.SetIcon(shellFileInfo.hIcon);

+  }

+}

+

+bool COverwriteDialog::OnInit()

+{

+  #ifdef LANG

+  LangSetWindowText(*this, IDD_OVERWRITE);

+  LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));

+  #endif

+  SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo);

+  SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo);

+  NormalizePosition();

+  return CModalDialog::OnInit();

+}

+

+bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch (buttonID)

+  {

+    case IDYES:

+    case IDNO:

+    case IDB_YES_TO_ALL:

+    case IDB_NO_TO_ALL:

+    case IDB_AUTO_RENAME:

+      End(buttonID);

+      return true;

+  }

+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);

+}

diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h
new file mode 100644
index 0000000..4564a47
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h
@@ -0,0 +1,69 @@
+// OverwriteDialog.h

+

+#ifndef __OVERWRITE_DIALOG_H

+#define __OVERWRITE_DIALOG_H

+

+#include "../../../Windows/Control/Dialog.h"

+

+#include "DialogSize.h"

+#include "OverwriteDialogRes.h"

+

+namespace NOverwriteDialog

+{

+  struct CFileInfo

+  {

+    bool SizeIsDefined;

+    bool TimeIsDefined;

+    UInt64 Size;

+    FILETIME Time;

+    UString Name;

+    

+    void SetTime(const FILETIME *t)

+    {

+      if (t == 0)

+        TimeIsDefined = false;

+      else

+      {

+        TimeIsDefined = true;

+        Time = *t;

+      }

+    }

+    void SetSize(const UInt64 *size)

+    {

+      if (size == 0)

+        SizeIsDefined = false;

+      else

+      {

+        SizeIsDefined = true;

+        Size = *size;

+      }

+    }

+  };

+}

+

+class COverwriteDialog: public NWindows::NControl::CModalDialog

+{

+  bool _isBig;

+

+  void SetFileInfoControl(int textID, int iconID, const NOverwriteDialog::CFileInfo &fileInfo);

+  virtual bool OnInit();

+  bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  void ReduceString(UString &s);

+

+public:

+  INT_PTR Create(HWND parent = 0)

+  {

+    BIG_DIALOG_SIZE(280, 200);

+    #ifdef UNDER_CE

+    _isBig = isBig;

+    #else

+    _isBig = true;

+    #endif

+    return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);

+  }

+

+  NOverwriteDialog::CFileInfo OldFileInfo;

+  NOverwriteDialog::CFileInfo NewFileInfo;

+};

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
new file mode 100644
index 0000000..80f48b0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
@@ -0,0 +1,91 @@
+#include "OverwriteDialogRes.h"

+#include "../../GuiCommon.rc"

+

+#define xc 280

+#define yc 200

+

+#undef iconSize

+#define iconSize 24

+

+#undef x

+#undef fx

+#undef fy

+#define x (m + iconSize + m)

+#define fx (xc - iconSize - m)

+#define fy 50

+

+#define bSizeBig 104

+#undef bx1

+#define bx1 (xs - m - bSizeBig)

+

+IDD_OVERWRITE  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Confirm File Replace"

+BEGIN

+  LTEXT  "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8

+  LTEXT  "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8

+  

+  ICON   "", IDI_OVERWRITE_OLD_FILE,             m,  44, iconSize, iconSize

+  LTEXT  "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME,   x,  44, fx, fy, SS_NOPREFIX

+  

+  LTEXT  "with this one?", IDT_OVERWRITE_QUESTION_END, m,  98, xc, 8

+

+  ICON   "", IDI_OVERWRITE_NEW_FILE,             m, 114, iconSize, iconSize

+  LTEXT  "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME,   x, 114, fx, fy, SS_NOPREFIX

+  

+  PUSHBUTTON  "&Yes",         IDYES,             bx3, by2, bxs, bys

+  PUSHBUTTON  "Yes to &All",  IDB_YES_TO_ALL,    bx2, by2, bxs, bys

+  PUSHBUTTON  "A&uto Rename", IDB_AUTO_RENAME,   bx1, by2, bSizeBig, bys

+  PUSHBUTTON  "&No",          IDNO,              bx3, by1, bxs, bys

+  PUSHBUTTON  "No to A&ll",   IDB_NO_TO_ALL,     bx2, by1, bxs, bys

+  PUSHBUTTON  "&Cancel",      IDCANCEL, xs - m - bxs, by1, bxs, bys

+END

+

+

+#ifdef UNDER_CE

+

+#undef m

+#undef xc

+#undef yc

+

+#define m 4

+#define xc 152

+#define yc 144

+

+#undef fy

+#define fy 40

+

+#undef  bxs

+#define bxs 48

+

+#undef bx1

+

+#define bx1 (xs - m - bxs)

+

+IDD_OVERWRITE_2  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Confirm File Replace"

+BEGIN

+  LTEXT  "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8

+  

+  ICON   "", IDI_OVERWRITE_OLD_FILE,             m,  20, iconSize, iconSize

+  LTEXT  "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME,   x,  20, fx, fy, SS_NOPREFIX

+  

+  LTEXT  "with this one?", IDT_OVERWRITE_QUESTION_END, m,  60, xc, 8

+

+  ICON   "", IDI_OVERWRITE_NEW_FILE,             m,  72, iconSize, iconSize

+  LTEXT  "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME,   x,  72, fx, fy, SS_NOPREFIX

+  

+  PUSHBUTTON  "&Yes",         IDYES,             bx3, by2, bxs, bys

+  PUSHBUTTON  "Yes to &All",  IDB_YES_TO_ALL,    bx2, by2, bxs, bys

+  PUSHBUTTON  "A&uto Rename", IDB_AUTO_RENAME,   bx1, by2, bxs, bys

+  PUSHBUTTON  "&No",          IDNO,              bx3, by1, bxs, bys

+  PUSHBUTTON  "No to A&ll",   IDB_NO_TO_ALL,     bx2, by1, bxs, bys

+  PUSHBUTTON  "&Cancel",      IDCANCEL,          bx1, by1, bxs, bys

+END

+

+#endif

+

+

+STRINGTABLE

+BEGIN

+  IDS_FILE_SIZE  "{0} bytes"

+END

diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
new file mode 100644
index 0000000..28bc0d0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
@@ -0,0 +1,17 @@
+#define IDD_OVERWRITE     3500

+#define IDD_OVERWRITE_2  13500

+

+#define IDT_OVERWRITE_HEADER          3501

+#define IDT_OVERWRITE_QUESTION_BEGIN  3502

+#define IDT_OVERWRITE_QUESTION_END    3503

+#define IDS_FILE_SIZE                 3504

+

+#define IDB_AUTO_RENAME               3505

+#define IDB_YES_TO_ALL                 440

+#define IDB_NO_TO_ALL                  441

+

+#define IDI_OVERWRITE_OLD_FILE             100

+#define IDI_OVERWRITE_NEW_FILE             101

+

+#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME   102

+#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME   103

diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp
new file mode 100644
index 0000000..95e83fe
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.cpp
@@ -0,0 +1,58 @@
+// PasswordDialog.cpp

+

+#include "StdAfx.h"

+

+#include "PasswordDialog.h"

+

+#ifdef LANG

+#include "LangUtils.h"

+#endif

+

+#ifdef LANG

+static const UInt32 kLangIDs[] =

+{

+  IDT_PASSWORD_ENTER,

+  IDX_PASSWORD_SHOW

+};

+#endif

+

+void CPasswordDialog::ReadControls()

+{

+  _passwordEdit.GetText(Password);

+  ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW);

+}

+

+void CPasswordDialog::SetTextSpec()

+{

+  _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*'));

+  _passwordEdit.SetText(Password);

+}

+

+bool CPasswordDialog::OnInit()

+{

+  #ifdef LANG

+  LangSetWindowText(*this, IDD_PASSWORD);

+  LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));

+  #endif

+  _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD));

+  CheckButton(IDX_PASSWORD_SHOW, ShowPassword);

+  SetTextSpec();

+  return CModalDialog::OnInit();

+}

+

+bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  if (buttonID == IDX_PASSWORD_SHOW)

+  {

+    ReadControls();

+    SetTextSpec();

+    return true;

+  }

+  return CDialog::OnButtonClicked(buttonID, buttonHWND);

+}

+

+void CPasswordDialog::OnOK()

+{

+  ReadControls();

+  CModalDialog::OnOK();

+}

diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h
new file mode 100644
index 0000000..b756a1c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.h
@@ -0,0 +1,28 @@
+// PasswordDialog.h

+

+#ifndef __PASSWORD_DIALOG_H

+#define __PASSWORD_DIALOG_H

+

+#include "../../../Windows/Control/Dialog.h"

+#include "../../../Windows/Control/Edit.h"

+

+#include "PasswordDialogRes.h"

+

+class CPasswordDialog: public NWindows::NControl::CModalDialog

+{

+  NWindows::NControl::CEdit _passwordEdit;

+

+  virtual void OnOK();

+  virtual bool OnInit();

+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  void SetTextSpec();

+  void ReadControls();

+public:

+  UString Password;

+  bool ShowPassword;

+  

+  CPasswordDialog(): ShowPassword(false) {}

+  INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); }

+};

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc
new file mode 100644
index 0000000..51dd5bc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.rc
@@ -0,0 +1,14 @@
+#include "PasswordDialogRes.h"

+#include "../../GuiCommon.rc"

+

+#define xc 140

+#define yc 72

+

+IDD_PASSWORD  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Enter password"

+BEGIN

+  LTEXT    "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8

+  EDITTEXT  IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL

+  CONTROL  "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10

+  OK_CANCEL

+END

diff --git a/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/CPP/7zip/UI/FileManager/PasswordDialogRes.h
new file mode 100644
index 0000000..f9300d6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialogRes.h
@@ -0,0 +1,5 @@
+#define IDD_PASSWORD        3800

+#define IDT_PASSWORD_ENTER  3801

+#define IDX_PASSWORD_SHOW   3803

+

+#define IDE_PASSWORD_PASSWORD  120

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
new file mode 100644
index 0000000..798b1a4
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -0,0 +1,196 @@
+// ProgressDialog.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+

+#include "resource.h"

+

+#include "ProgressDialog.h"

+

+using namespace NWindows;

+

+extern HINSTANCE g_hInstance;

+

+static const UINT_PTR kTimerID = 3;

+static const UINT kTimerElapse = 100;

+

+#ifdef LANG

+#include "LangUtils.h"

+#endif

+

+HRESULT CProgressSync::ProcessStopAndPause()

+{

+  for (;;)

+  {

+    if (GetStopped())

+      return E_ABORT;

+    if (!GetPaused())

+      break;

+    ::Sleep(100);

+  }

+  return S_OK;

+}

+

+#ifndef _SFX

+CProgressDialog::~CProgressDialog()

+{

+  AddToTitle(L"");

+}

+void CProgressDialog::AddToTitle(LPCWSTR s)

+{

+  if (MainWindow != 0)

+    MySetWindowText(MainWindow, UString(s) + MainTitle);

+}

+#endif

+

+

+bool CProgressDialog::OnInit()

+{

+  _range = (UInt64)(Int64)-1;

+  _prevPercentValue = -1;

+

+  _wasCreated = true;

+  _dialogCreatedEvent.Set();

+

+  #ifdef LANG

+  LangSetDlgItems(*this, NULL, 0);

+  #endif

+

+  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));

+

+  if (IconID >= 0)

+  {

+    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));

+    SetIcon(ICON_BIG, icon);

+  }

+

+  _timer = SetTimer(kTimerID, kTimerElapse);

+  SetText(_title);

+  CheckNeedClose();

+  return CModalDialog::OnInit();

+}

+

+void CProgressDialog::OnCancel() { Sync.SetStopped(true); }

+void CProgressDialog::OnOK() { }

+

+void CProgressDialog::SetRange(UInt64 range)

+{

+  _range = range;

+  _peviousPos = (UInt64)(Int64)-1;

+  _converter.Init(range);

+  m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100%

+}

+

+void CProgressDialog::SetPos(UInt64 pos)

+{

+  bool redraw = true;

+  if (pos < _range && pos > _peviousPos)

+  {

+    UInt64 posDelta = pos - _peviousPos;

+    if (posDelta < (_range >> 10))

+      redraw = false;

+  }

+  if (redraw)

+  {

+    m_ProgressBar.SetPos(_converter.Count(pos));  // Test it for 100%

+    _peviousPos = pos;

+  }

+}

+

+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)

+{

+  if (Sync.GetPaused())

+    return true;

+

+  CheckNeedClose();

+

+  UInt64 total, completed;

+  Sync.GetProgress(total, completed);

+  if (total != _range)

+    SetRange(total);

+  SetPos(completed);

+

+  if (total == 0)

+    total = 1;

+

+  int percentValue = (int)(completed * 100 / total);

+  if (percentValue != _prevPercentValue)

+  {

+    wchar_t s[64];

+    ConvertUInt64ToString(percentValue, s);

+    UString title = s;

+    title += L"% ";

+    SetText(title + _title);

+    #ifndef _SFX

+    AddToTitle(title + MainAddTitle);

+    #endif

+    _prevPercentValue = percentValue;

+  }

+  return true;

+}

+

+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  switch(message)

+  {

+    case kCloseMessage:

+    {

+      KillTimer(_timer);

+      _timer = 0;

+      if (_inCancelMessageBox)

+      {

+        _externalCloseMessageWasReceived = true;

+        break;

+      }

+      return OnExternalCloseMessage();

+    }

+    /*

+    case WM_SETTEXT:

+    {

+      if (_timer == 0)

+        return true;

+    }

+    */

+  }

+  return CModalDialog::OnMessage(message, wParam, lParam);

+}

+

+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch(buttonID)

+  {

+    case IDCANCEL:

+    {

+      bool paused = Sync.GetPaused();

+      Sync.SetPaused(true);

+      _inCancelMessageBox = true;

+      int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL);

+      _inCancelMessageBox = false;

+      Sync.SetPaused(paused);

+      if (res == IDCANCEL || res == IDNO)

+      {

+        if (_externalCloseMessageWasReceived)

+          OnExternalCloseMessage();

+        return true;

+      }

+      break;

+    }

+  }

+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);

+}

+

+void CProgressDialog::CheckNeedClose()

+{

+  if (_needClose)

+  {

+    PostMessage(kCloseMessage);

+    _needClose = false;

+  }

+}

+

+bool CProgressDialog::OnExternalCloseMessage()

+{

+  End(0);

+  return true;

+}

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h
new file mode 100644
index 0000000..9c6702f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -0,0 +1,170 @@
+// ProgressDialog.h

+

+#ifndef __PROGRESS_DIALOG_H

+#define __PROGRESS_DIALOG_H

+

+#include "../../../Windows/Synchronization.h"

+#include "../../../Windows/Thread.h"

+

+#include "../../../Windows/Control/Dialog.h"

+#include "../../../Windows/Control/ProgressBar.h"

+

+#include "ProgressDialogRes.h"

+

+class CProgressSync

+{

+  NWindows::NSynchronization::CCriticalSection _cs;

+  bool _stopped;

+  bool _paused;

+  UInt64 _total;

+  UInt64 _completed;

+public:

+  CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}

+

+  HRESULT ProcessStopAndPause();

+  bool GetStopped()

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    return _stopped;

+  }

+  void SetStopped(bool value)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _stopped = value;

+  }

+  bool GetPaused()

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    return _paused;

+  }

+  void SetPaused(bool value)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _paused = value;

+  }

+  void SetProgress(UInt64 total, UInt64 completed)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _total = total;

+    _completed = completed;

+  }

+  void SetPos(UInt64 completed)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _completed = completed;

+  }

+  void GetProgress(UInt64 &total, UInt64 &completed)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    total = _total;

+    completed = _completed;

+  }

+};

+

+class CU64ToI32Converter

+{

+  UInt64 _numShiftBits;

+public:

+  void Init(UInt64 range)

+  {

+    // Windows CE doesn't like big number here.

+    for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)

+      range >>= 1;

+  }

+  int Count(UInt64 value) { return int(value >> _numShiftBits); }

+};

+

+class CProgressDialog: public NWindows::NControl::CModalDialog

+{

+private:

+  UINT_PTR _timer;

+

+  UString _title;

+  CU64ToI32Converter _converter;

+  UInt64 _peviousPos;

+  UInt64 _range;

+  NWindows::NControl::CProgressBar m_ProgressBar;

+

+  int _prevPercentValue;

+

+  bool _wasCreated;

+  bool _needClose;

+  bool _inCancelMessageBox;

+  bool _externalCloseMessageWasReceived;

+

+  bool OnTimer(WPARAM timerID, LPARAM callback);

+  void SetRange(UInt64 range);

+  void SetPos(UInt64 pos);

+  virtual bool OnInit();

+  virtual void OnCancel();

+  virtual void OnOK();

+  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;

+  #ifndef _SFX

+  void AddToTitle(LPCWSTR string);

+  #endif

+  bool OnButtonClicked(int buttonID, HWND buttonHWND);

+

+  void WaitCreating() { _dialogCreatedEvent.Lock(); }

+  void CheckNeedClose();

+  bool OnExternalCloseMessage();

+public:

+  CProgressSync Sync;

+  int IconID;

+

+  #ifndef _SFX

+  HWND MainWindow;

+  UString MainTitle;

+  UString MainAddTitle;

+  ~CProgressDialog();

+  #endif

+

+  CProgressDialog(): _timer(0)

+    #ifndef _SFX

+    ,MainWindow(0)

+    #endif

+  {

+    IconID = -1;

+    _wasCreated = false;

+    _needClose = false;

+    _inCancelMessageBox = false;

+    _externalCloseMessageWasReceived = false;

+

+    if (_dialogCreatedEvent.Create() != S_OK)

+      throw 1334987;

+  }

+

+  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0)

+  {

+    _title = title;

+    INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent);

+    thread.Wait();

+    return res;

+  }

+

+  enum

+  {

+    kCloseMessage = WM_APP + 1

+  };

+

+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+

+  void ProcessWasFinished()

+  {

+    WaitCreating();

+    if (_wasCreated)

+      PostMessage(kCloseMessage);

+    else

+      _needClose = true;

+  };

+};

+

+

+class CProgressCloser

+{

+  CProgressDialog *_p;

+public:

+  CProgressCloser(CProgressDialog &p) : _p(&p) {}

+  ~CProgressCloser() { _p->ProcessWasFinished(); }

+};

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.rc b/CPP/7zip/UI/FileManager/ProgressDialog.rc
new file mode 100644
index 0000000..5af370f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.rc
@@ -0,0 +1,12 @@
+#include "ProgressDialogRes.h"

+#include "../../GuiCommon.rc"

+

+#define xc 172

+#define yc 44

+

+IDD_PROGRESS  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Progress"

+BEGIN

+  PUSHBUTTON  "Cancel", IDCANCEL, bx, by, bxs, bys

+  CONTROL     "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14

+END

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
new file mode 100644
index 0000000..aea37a4
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -0,0 +1,1293 @@
+// ProgressDialog2.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/Control/Static.h"

+#include "../../../Windows/ErrorMsg.h"

+

+#include "ProgressDialog2.h"

+#include "DialogSize.h"

+

+#include "ProgressDialog2Res.h"

+

+#include "../GUI/ExtractRes.h"

+

+using namespace NWindows;

+

+extern HINSTANCE g_hInstance;

+

+static const UINT_PTR kTimerID = 3;

+

+static const UINT kCloseMessage = WM_APP + 1;

+// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog

+

+static const UINT kTimerElapse =

+  #ifdef UNDER_CE

+  500

+  #else

+  100

+  #endif

+  ;

+

+static const UINT kCreateDelay =

+  #ifdef UNDER_CE

+  2500

+  #else

+  500

+  #endif

+  ;

+

+static const DWORD kPauseSleepTime = 100;

+

+#include "LangUtils.h"

+

+#ifdef LANG

+

+static const UInt32 kLangIDs[] =

+{

+  IDT_PROGRESS_ELAPSED,

+  IDT_PROGRESS_REMAINING,

+  IDT_PROGRESS_TOTAL,

+  IDT_PROGRESS_SPEED,

+  IDT_PROGRESS_PROCESSED,

+  IDT_PROGRESS_RATIO,

+  IDT_PROGRESS_ERRORS,

+  IDB_PROGRESS_BACKGROUND,

+  IDB_PAUSE

+};

+

+static const UInt32 kLangIDs_Colon[] =

+{

+  IDT_PROGRESS_PACKED,

+  IDT_PROGRESS_FILES

+};

+

+#endif

+

+

+#define UNDEFINED_VAL ((UInt64)(Int64)-1)

+#define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL;

+#define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL)

+#define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL)

+

+CProgressSync::CProgressSync():

+    _stopped(false), _paused(false),

+    _bytesProgressMode(true),

+    _totalBytes(UNDEFINED_VAL), _completedBytes(0),

+    _totalFiles(UNDEFINED_VAL), _curFiles(0),

+    _inSize(UNDEFINED_VAL),

+    _outSize(UNDEFINED_VAL),

+    _isDir(false)

+    {}

+

+#define CHECK_STOP  if (_stopped) return E_ABORT; if (!_paused) return S_OK;

+#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs);

+

+bool CProgressSync::Get_Paused()

+{

+  CRITICAL_LOCK

+  return _paused;

+}

+

+HRESULT CProgressSync::CheckStop()

+{

+  for (;;)

+  {

+    {

+      CRITICAL_LOCK

+      CHECK_STOP

+    }

+    ::Sleep(kPauseSleepTime);

+  }

+}

+

+HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir)

+{

+  {

+    CRITICAL_LOCK

+    _totalFiles = numFiles;

+    _totalBytes = totalSize;

+    _filePath = fileName;

+    _isDir = isDir;

+    // _completedBytes = 0;

+    CHECK_STOP

+  }

+  return CheckStop();

+}

+

+void CProgressSync::Set_NumFilesTotal(UInt64 val)

+{

+  CRITICAL_LOCK

+  _totalFiles = val;

+}

+

+void CProgressSync::Set_NumBytesTotal(UInt64 val)

+{

+  CRITICAL_LOCK

+  _totalBytes = val;

+}

+

+void CProgressSync::Set_NumFilesCur(UInt64 val)

+{

+  CRITICAL_LOCK

+  _curFiles = val;

+}

+

+HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val)

+{

+  {

+    CRITICAL_LOCK

+    if (val)

+      _completedBytes = *val;

+    CHECK_STOP

+  }

+  return CheckStop();

+}

+

+HRESULT CProgressSync::Set_NumBytesCur(UInt64 val)

+{

+  {

+    CRITICAL_LOCK

+    _completedBytes = val;

+    CHECK_STOP

+  }

+  return CheckStop();

+}

+

+void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize)

+{

+  CRITICAL_LOCK

+  if (inSize)

+    _inSize = *inSize;

+  if (outSize)

+    _outSize = *outSize;

+}

+

+void CProgressSync::Set_TitleFileName(const UString &fileName)

+{

+  CRITICAL_LOCK

+  _titleFileName = fileName;

+}

+void CProgressSync::Set_Status(const UString &s)

+{

+  CRITICAL_LOCK

+  _status = s;

+}

+

+void CProgressSync::Set_FilePath(const UString &path, bool isDir)

+{

+  CRITICAL_LOCK

+  _filePath = path;

+  _isDir = isDir;

+}

+

+

+void CProgressSync::AddError_Message(const wchar_t *message)

+{

+  CRITICAL_LOCK

+  Messages.Add(message);

+}

+

+void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name)

+{

+  UString s;

+  if (name && *name != 0)

+    s += name;

+  if (message && *message != 0 )

+  {

+    if (!s.IsEmpty())

+      s += L'\n';

+    s += message;

+    if (!s.IsEmpty() && s.Back() == L'\n')

+      s.DeleteBack();

+  }

+  AddError_Message(s);

+}

+

+void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name)

+{

+  UString s = NError::MyFormatMessage(systemError);

+  if (systemError == 0)

+    s = L"Error";

+  AddError_Message_Name(s, name);

+}

+

+CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true), MainWindow(0)

+{

+  _isDir = false;

+

+  _numMessages = 0;

+  IconID = -1;

+  MessagesDisplayed = false;

+  _wasCreated = false;

+  _needClose = false;

+  _inCancelMessageBox = false;

+  _externalCloseMessageWasReceived = false;

+  

+  _numPostedMessages = 0;

+  _numAutoSizeMessages = 0;

+  _errorsWereDisplayed = false;

+  _waitCloseByCancelButton = false;

+  _cancelWasPressed = false;

+  ShowCompressionInfo = true;

+  WaitMode = false;

+  if (_dialogCreatedEvent.Create() != S_OK)

+    throw 1334987;

+  if (_createDialogEvent.Create() != S_OK)

+    throw 1334987;

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList);

+  if (_taskbarList)

+    _taskbarList->HrInit();

+  #endif

+}

+

+#ifndef _SFX

+

+CProgressDialog::~CProgressDialog()

+{

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  SetTaskbarProgressState(TBPF_NOPROGRESS);

+  #endif

+  AddToTitle(L"");

+}

+void CProgressDialog::AddToTitle(LPCWSTR s)

+{

+  if (MainWindow != 0)

+  {

+    CWindow window(MainWindow);

+    window.SetText((UString)s + MainTitle);

+  }

+}

+

+#endif

+

+

+void CProgressDialog::SetTaskbarProgressState()

+{

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  if (_taskbarList && _hwndForTaskbar)

+  {

+    TBPFLAG tbpFlags;

+    if (Sync.Get_Paused())

+      tbpFlags = TBPF_PAUSED;

+    else

+      tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL;

+    SetTaskbarProgressState(tbpFlags);

+  }

+  #endif

+}

+

+static const unsigned kTitleFileNameSizeLimit = 36;

+static const unsigned kCurrentFileNameSizeLimit = 82;

+

+static void ReduceString(UString &s, unsigned size)

+{

+  if (s.Len() <= size)

+    return;

+  s.Delete(size / 2, s.Len() - size);

+  s.Insert(size / 2, L" ... ");

+}

+

+void CProgressDialog::EnableErrorsControls(bool enable)

+{

+  ShowItem_Bool(IDT_PROGRESS_ERRORS, enable);

+  ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable);

+  ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable);

+}

+

+bool CProgressDialog::OnInit()

+{

+  _hwndForTaskbar = MainWindow;

+  if (!_hwndForTaskbar)

+    _hwndForTaskbar = GetParent();

+  if (!_hwndForTaskbar)

+    _hwndForTaskbar = *this;

+

+  INIT_AS_UNDEFINED(_progressBar_Range);

+  INIT_AS_UNDEFINED(_progressBar_Pos);

+

+  INIT_AS_UNDEFINED(_prevPercentValue);

+  INIT_AS_UNDEFINED(_prevElapsedSec);

+  INIT_AS_UNDEFINED(_prevRemainingSec);

+

+  INIT_AS_UNDEFINED(_prevSpeed);

+  _prevSpeed_MoveBits = 0;

+  

+  _prevTime = ::GetTickCount();

+  _elapsedTime = 0;

+

+  INIT_AS_UNDEFINED(_totalBytes_Prev);

+  INIT_AS_UNDEFINED(_processed_Prev);

+  INIT_AS_UNDEFINED(_packed_Prev);

+  INIT_AS_UNDEFINED(_ratio_Prev);

+  _filesStr_Prev.Empty();

+

+  _foreground = true;

+

+  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));

+  _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES));

+  _messageList.SetUnicodeFormat();

+

+  _wasCreated = true;

+  _dialogCreatedEvent.Set();

+

+  #ifdef LANG

+  LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));

+  LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));

+  #endif

+

+  CWindow window(GetItem(IDB_PROGRESS_BACKGROUND));

+  window.GetText(_background_String);

+  _backgrounded_String = _background_String;

+  _backgrounded_String.RemoveChar(L'&');

+

+  window = GetItem(IDB_PAUSE);

+  window.GetText(_pause_String);

+

+  LangString(IDS_PROGRESS_FOREGROUND, _foreground_String);

+  LangString(IDS_CONTINUE, _continue_String);

+  LangString(IDS_PROGRESS_PAUSED, _paused_String);

+

+  SetText(_title);

+  SetPauseText();

+  SetPriorityText();

+

+  _messageList.InsertColumn(0, L"", 30);

+  _messageList.InsertColumn(1, L"", 600);

+

+  _messageList.SetColumnWidthAuto(0);

+  _messageList.SetColumnWidthAuto(1);

+

+  EnableErrorsControls(false);

+

+  GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY);

+  _numReduceSymbols = kCurrentFileNameSizeLimit;

+  NormalizeSize(true);

+

+  if (!ShowCompressionInfo)

+  {

+    HideItem(IDT_PROGRESS_PACKED);

+    HideItem(IDT_PROGRESS_PACKED_VAL);

+    HideItem(IDT_PROGRESS_RATIO);

+    HideItem(IDT_PROGRESS_RATIO_VAL);

+  }

+

+  if (IconID >= 0)

+  {

+    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));

+    // SetIcon(ICON_SMALL, icon);

+    SetIcon(ICON_BIG, icon);

+  }

+  _timer = SetTimer(kTimerID, kTimerElapse);

+  #ifdef UNDER_CE

+  Foreground();

+  #endif

+

+  CheckNeedClose();

+

+  SetTaskbarProgressState();

+

+  return CModalDialog::OnInit();

+}

+

+static const UINT kIDs[] =

+{

+  IDT_PROGRESS_ELAPSED,   IDT_PROGRESS_ELAPSED_VAL,

+  IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL,

+  IDT_PROGRESS_FILES,     IDT_PROGRESS_FILES_VAL,

+  IDT_PROGRESS_RATIO,     IDT_PROGRESS_RATIO_VAL,

+  IDT_PROGRESS_ERRORS,    IDT_PROGRESS_ERRORS_VAL,

+  

+  IDT_PROGRESS_TOTAL,     IDT_PROGRESS_TOTAL_VAL,

+  IDT_PROGRESS_SPEED,     IDT_PROGRESS_SPEED_VAL,

+  IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL,

+  IDT_PROGRESS_PACKED,    IDT_PROGRESS_PACKED_VAL

+};

+

+bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)

+{

+  int sY;

+  int sStep;

+  int mx, my;

+  {

+    RECT r;

+    GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r);

+    mx = r.left;

+    my = r.top;

+    sY = RECT_SIZE_Y(r);

+    GetClientRectOfItem(IDT_PROGRESS_REMAINING, r);

+    sStep = r.top - my;

+  }

+

+  InvalidateRect(NULL);

+

+  int xSizeClient = xSize - mx * 2;

+

+  {

+    int i;

+    for (i = 800; i > 40; i = i * 9 / 10)

+      if (Units_To_Pixels_X(i) <= xSizeClient)

+        break;

+    _numReduceSymbols = i / 4;

+  }

+

+  int yPos = ySize - my - _buttonSizeY;

+

+  ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2);

+  ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2);

+  ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2);

+

+  int bSizeX = _buttonSizeX;

+  int mx2 = mx;

+  for (;; mx2--)

+  {

+    int bSize2 = bSizeX * 3 + mx2 * 2;

+    if (bSize2 <= xSizeClient)

+      break;

+    if (mx2 < 5)

+    {

+      bSizeX = (xSizeClient - mx2 * 2) / 3;

+      break;

+    }

+  }

+  if (bSizeX < 2)

+    bSizeX = 2;

+

+  {

+    RECT r;

+    GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r);

+    int y = r.top;

+    int ySize2 = yPos - my - y;

+    const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4;

+    int xx = xSize - mx * 2;

+    if (ySize2 < kMinYSize)

+    {

+      ySize2 = kMinYSize;

+      if (xx > bSizeX * 2)

+        xx -= bSizeX;

+    }

+

+    _messageList.Move(mx, y, xx, ySize2);

+  }

+

+  {

+    int xPos = xSize - mx;

+    xPos -= bSizeX;

+    MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY);

+    xPos -= (mx2 + bSizeX);

+    MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY);

+    xPos -= (mx2 + bSizeX);

+    MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY);

+  }

+

+  int valueSize;

+  int labelSize;

+  int padSize;

+

+  labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN);

+  valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS);

+  padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS);

+  int requiredSize = (labelSize + valueSize) * 2 + padSize;

+

+  int gSize;

+  {

+    if (requiredSize < xSizeClient)

+    {

+      int incr = (xSizeClient - requiredSize) / 3;

+      labelSize += incr;

+    }

+    else

+      labelSize = (xSizeClient - valueSize * 2 - padSize) / 2;

+    if (labelSize < 0)

+      labelSize = 0;

+

+    gSize = labelSize + valueSize;

+    padSize = xSizeClient - gSize * 2;

+  }

+

+  labelSize = gSize - valueSize;

+

+  yPos = my;

+  for (int i = 0; i < ARRAY_SIZE(kIDs); i += 2)

+  {

+    int x = mx;

+    const int kNumColumn1Items = 5 * 2;

+    if (i >= kNumColumn1Items)

+    {

+      if (i == kNumColumn1Items)

+        yPos = my;

+      x = mx + gSize + padSize;

+    }

+    MoveItem(kIDs[i], x, yPos, labelSize, sY);

+    MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY);

+    yPos += sStep;

+  }

+  return false;

+}

+

+void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); }

+void CProgressDialog::OnOK() { }

+

+void CProgressDialog::SetProgressRange(UInt64 range)

+{

+  if (range == _progressBar_Range)

+    return;

+  _progressBar_Range = range;

+  INIT_AS_UNDEFINED(_progressBar_Pos);

+  _progressConv.Init(range);

+  m_ProgressBar.SetRange32(0, _progressConv.Count(range));

+}

+

+void CProgressDialog::SetProgressPos(UInt64 pos)

+{

+  if (pos >= _progressBar_Range ||

+      pos <= _progressBar_Pos ||

+      pos - _progressBar_Pos >= (_progressBar_Range >> 10))

+  {

+    m_ProgressBar.SetPos(_progressConv.Count(pos));

+    #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+    if (_taskbarList && _hwndForTaskbar)

+      _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range);

+    #endif

+    _progressBar_Pos = pos;

+  }

+}

+

+#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; }

+

+void GetTimeString(UInt64 timeValue, wchar_t *s)

+{

+  UInt64 hours = timeValue / 3600;

+  UInt32 seconds = (UInt32)(timeValue - hours * 3600);

+  UInt32 minutes = seconds / 60;

+  seconds %= 60;

+  if (hours > 99)

+  {

+    ConvertUInt64ToString(hours, s);

+    for (; *s != 0; s++);

+  }

+  else

+  {

+    UInt32 hours32 = (UInt32)hours;

+    UINT_TO_STR_2(hours32);

+  }

+  *s++ = ':'; UINT_TO_STR_2(minutes);

+  *s++ = ':'; UINT_TO_STR_2(seconds);

+  *s = 0;

+}

+

+static void ConvertSizeToString(UInt64 v, wchar_t *s)

+{

+  Byte c = 0;

+       if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; }

+  else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; }

+  else if (v >= ((UInt64)100000 <<  0)) { v >>= 10; c = 'K'; }

+  ConvertUInt64ToString(v, s);

+  if (c != 0)

+  {

+    s += MyStringLen(s);

+    *s++ = ' ';

+    *s++ = c;

+    *s++ = 0;

+  }

+}

+

+void CProgressDialog::ShowSize(int id, UInt64 val, UInt64 &prev)

+{

+  if (val == prev)

+    return;

+  prev = val;

+  wchar_t s[40];

+  s[0] = 0;

+  if (IS_DEFINED_VAL(val))

+    ConvertSizeToString(val, s);

+  SetItemText(id, s);

+}

+

+static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged)

+{

+  hasChanged = !(prevStr == newStr);

+  if (hasChanged)

+    prevStr = newStr;

+}

+

+static unsigned GetPower32(UInt32 val)

+{

+  const unsigned kStart = 32;

+  UInt32 mask = ((UInt32)1 << (kStart - 1));

+  for (unsigned i = kStart;; i--)

+  {

+    if (i == 0 || (val & mask) != 0)

+      return i;

+    mask >>= 1;

+  }

+}

+

+static unsigned GetPower64(UInt64 val)

+{

+  UInt32 high = (UInt32)(val >> 32);

+  if (high == 0)

+    return GetPower32((UInt32)val);

+  return GetPower32(high) + 32;

+

+}

+

+static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)

+{

+  unsigned pow1 = GetPower64(mult1);

+  unsigned pow2 = GetPower64(mult2);

+  while (pow1 + pow2 > 64)

+  {

+    if (pow1 > pow2) { pow1--; mult1 >>= 1; }

+    else             { pow2--; mult2 >>= 1; }

+    divider >>= 1;

+  }

+  UInt64 res = mult1 * mult2;

+  if (divider != 0)

+    res /= divider;

+  return res;

+}

+

+void CProgressDialog::UpdateStatInfo(bool showAll)

+{

+  UInt64 total, completed, totalFiles, completedFiles, inSize, outSize;

+  bool bytesProgressMode;

+

+  bool titleFileName_Changed;

+  bool curFilePath_Changed;

+  bool status_Changed;

+  unsigned numErrors;

+  {

+    NSynchronization::CCriticalSectionLock lock(Sync._cs);

+    total = Sync._totalBytes;

+    completed = Sync._completedBytes;

+    totalFiles = Sync._totalFiles;

+    completedFiles = Sync._curFiles;

+    inSize = Sync._inSize;

+    outSize = Sync._outSize;

+    bytesProgressMode = Sync._bytesProgressMode;

+

+    GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed);

+    GetChangedString(Sync._filePath, _filePath, curFilePath_Changed);

+    GetChangedString(Sync._status, _status, status_Changed);

+    if (_isDir != Sync._isDir)

+    {

+      curFilePath_Changed = true;

+      _isDir = Sync._isDir;

+    }

+    numErrors = Sync.Messages.Size();

+  }

+

+  UInt32 curTime = ::GetTickCount();

+

+  {

+    UInt64 progressTotal = bytesProgressMode ? total : totalFiles;

+    UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;

+    

+    if (IS_UNDEFINED_VAL(progressTotal))

+    {

+      // SetPos(0);

+      // SetRange(progressCompleted);

+    }

+    else

+    {

+      if (_progressBar_Pos != 0 || progressCompleted != 0 ||

+          (_progressBar_Range == 0 && progressTotal != 0))

+      {

+        SetProgressRange(progressTotal);

+        SetProgressPos(progressCompleted);

+      }

+    }

+  }

+

+  ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev);

+

+  _elapsedTime += (curTime - _prevTime);

+  _prevTime = curTime;

+  UInt64 elapsedSec = _elapsedTime / 1000;

+  bool elapsedChanged = false;

+  if (elapsedSec != _prevElapsedSec)

+  {

+    _prevElapsedSec = elapsedSec;

+    elapsedChanged = true;

+    wchar_t s[40];

+    GetTimeString(elapsedSec, s);

+    SetItemText(IDT_PROGRESS_ELAPSED_VAL, s);

+  }

+

+  bool needSetTitle = false;

+  if (elapsedChanged || showAll)

+  {

+    if (numErrors > _numPostedMessages)

+    {

+      UpdateMessagesDialog();

+      wchar_t s[32];

+      ConvertUInt64ToString(numErrors, s);

+      SetItemText(IDT_PROGRESS_ERRORS_VAL, s);

+      if (!_errorsWereDisplayed)

+      {

+        _errorsWereDisplayed = true;

+        EnableErrorsControls(true);

+        SetTaskbarProgressState();

+      }

+    }

+

+    if (completed != 0)

+    {

+      if (IS_UNDEFINED_VAL(total))

+      {

+        if (IS_DEFINED_VAL(_prevRemainingSec))

+        {

+          INIT_AS_UNDEFINED(_prevRemainingSec);

+          SetItemText(IDT_PROGRESS_REMAINING_VAL, L"");

+        }

+      }

+      else

+      {

+        UInt64 remainingTime = 0;

+        if (completed < total)

+          remainingTime = MyMultAndDiv(_elapsedTime, total - completed, completed);

+        UInt64 remainingSec = remainingTime / 1000;

+        if (remainingSec != _prevRemainingSec)

+        {

+          _prevRemainingSec = remainingSec;

+          wchar_t s[40];

+          GetTimeString(remainingSec, s);

+          SetItemText(IDT_PROGRESS_REMAINING_VAL, s);

+        }

+      }

+      {

+        UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;

+        UInt64 v = (completed * 1000) / elapsedTime;

+        Byte c = 0;

+        unsigned moveBits = 0;

+             if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }

+        else if (v >= ((UInt64)10000 <<  0)) { moveBits = 10; c = 'K'; }

+        v >>= moveBits;

+        if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed)

+        {

+          _prevSpeed_MoveBits = moveBits;

+          _prevSpeed = v;

+          wchar_t s[40];

+          ConvertUInt64ToString(v, s);

+          unsigned pos = MyStringLen(s);

+          s[pos++] = ' ';

+          if (moveBits != 0)

+            s[pos++] = c;

+          s[pos++] = 'B';

+          s[pos++] = '/';

+          s[pos++] = 's';

+          s[pos++] = 0;

+          SetItemText(IDT_PROGRESS_SPEED_VAL, s);

+        }

+      }

+    }

+

+    {

+      UInt64 percent = 0;

+      {

+        if (IS_DEFINED_VAL(total))

+        {

+          percent = completed * 100;

+          if (total != 0)

+            percent /= total;

+        }

+      }

+      if (percent != _prevPercentValue)

+      {

+        _prevPercentValue = percent;

+        needSetTitle = true;

+      }

+    }

+    

+    {

+      wchar_t s[64];

+      ConvertUInt64ToString(completedFiles, s);

+      if (IS_DEFINED_VAL(totalFiles))

+      {

+        wcscat(s, L" / ");

+        ConvertUInt64ToString(totalFiles, s + wcslen(s));

+      }

+      if (_filesStr_Prev != s)

+      {

+        _filesStr_Prev = s;

+        SetItemText(IDT_PROGRESS_FILES_VAL, s);

+      }

+    }

+    

+    const UInt64 packSize   = CompressingMode ? outSize : inSize;

+    const UInt64 unpackSize = CompressingMode ? inSize : outSize;

+

+    if (IS_UNDEFINED_VAL(unpackSize) &&

+        IS_UNDEFINED_VAL(packSize))

+    {

+      ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev);

+      ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev);

+    }

+    else

+    {

+      ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev);

+      ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev);

+      

+      if (IS_DEFINED_VAL(packSize) &&

+          IS_DEFINED_VAL(unpackSize) &&

+          unpackSize != 0)

+      {

+        wchar_t s[32];

+        UInt64 ratio = packSize * 100 / unpackSize;

+        if (_ratio_Prev != ratio)

+        {

+          _ratio_Prev = ratio;

+          ConvertUInt64ToString(ratio, s);

+          wcscat(s, L"%");

+          SetItemText(IDT_PROGRESS_RATIO_VAL, s);

+        }

+      }

+    }

+  }

+

+  if (needSetTitle || titleFileName_Changed)

+    SetTitleText();

+

+  if (status_Changed)

+  {

+    UString s = _status;

+    ReduceString(s, _numReduceSymbols);

+    SetItemText(IDT_PROGRESS_STATUS, _status);

+  }

+

+  if (curFilePath_Changed)

+  {

+    UString s1, s2;

+    if (_isDir)

+      s1 = _filePath;

+    else

+    {

+      int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);

+      if (slashPos >= 0)

+      {

+        s1.SetFrom(_filePath, slashPos + 1);

+        s2 = _filePath.Ptr(slashPos + 1);

+      }

+      else

+        s2 = _filePath;

+    }

+    ReduceString(s1, _numReduceSymbols);

+    ReduceString(s2, _numReduceSymbols);

+    s1 += L'\n';

+    s1 += s2;

+    SetItemText(IDT_PROGRESS_FILE_NAME, s1);

+  }

+}

+

+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)

+{

+  if (Sync.Get_Paused())

+    return true;

+  CheckNeedClose();

+  UpdateStatInfo(false);

+  return true;

+}

+

+struct CWaitCursor

+{

+  HCURSOR _waitCursor;

+  HCURSOR _oldCursor;

+  CWaitCursor()

+  {

+    _waitCursor = LoadCursor(NULL, IDC_WAIT);

+    if (_waitCursor != NULL)

+      _oldCursor = SetCursor(_waitCursor);

+  }

+  ~CWaitCursor()

+  {

+    if (_waitCursor != NULL)

+      SetCursor(_oldCursor);

+  }

+};

+

+INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent)

+{

+  INT_PTR res = 0;

+  try

+  {

+    if (WaitMode)

+    {

+      CWaitCursor waitCursor;

+      HANDLE h[] = { thread, _createDialogEvent };

+      

+      WRes res = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay);

+      if (res == WAIT_OBJECT_0 && !Sync.ThereIsMessage())

+        return 0;

+    }

+    _title = title;

+    BIG_DIALOG_SIZE(360, 192);

+    res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent);

+  }

+  catch(...)

+  {

+    _wasCreated = true;

+    _dialogCreatedEvent.Set();

+    res = res;

+  }

+  thread.Wait();

+  if (!MessagesDisplayed)

+    MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR);

+  return res;

+}

+

+bool CProgressDialog::OnExternalCloseMessage()

+{

+  // it doesn't work if there is MessageBox.

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  SetTaskbarProgressState(TBPF_NOPROGRESS);

+  #endif

+  // AddToTitle(L"Finished ");

+  // SetText(L"Finished2 ");

+

+  UpdateStatInfo(true);

+  

+  SetItemText(IDCANCEL, LangString(IDS_CLOSE));

+  ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));

+  HideItem(IDB_PROGRESS_BACKGROUND);

+  HideItem(IDB_PAUSE);

+  

+  bool thereAreMessages;

+  CProgressFinalMessage fm;

+  {

+    NSynchronization::CCriticalSectionLock lock(Sync._cs);

+    thereAreMessages = !Sync.Messages.IsEmpty();

+    fm = Sync.FinalMessage;

+  }

+  if (!fm.ErrorMessage.Message.IsEmpty())

+  {

+    MessagesDisplayed = true;

+    if (fm.ErrorMessage.Title.IsEmpty())

+      fm.ErrorMessage.Title = L"7-Zip";

+    MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);

+  }

+  else if (!thereAreMessages)

+  {

+    MessagesDisplayed = true;

+    if (!fm.OkMessage.Message.IsEmpty())

+    {

+      if (fm.OkMessage.Title.IsEmpty())

+        fm.OkMessage.Title = L"7-Zip";

+      MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);

+    }

+  }

+

+  if (thereAreMessages && !_cancelWasPressed)

+  {

+    _waitCloseByCancelButton = true;

+    UpdateMessagesDialog();

+    return true;

+  }

+

+  End(0);

+  return true;

+}

+

+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  switch (message)

+  {

+    case kCloseMessage:

+    {

+      KillTimer(_timer);

+      _timer = 0;

+      if (_inCancelMessageBox)

+      {

+        _externalCloseMessageWasReceived = true;

+        break;

+      }

+      return OnExternalCloseMessage();

+    }

+    /*

+    case WM_SETTEXT:

+    {

+      if (_timer == 0)

+        return true;

+      break;

+    }

+    */

+  }

+  return CModalDialog::OnMessage(message, wParam, lParam);

+}

+

+void CProgressDialog::SetTitleText()

+{

+  UString s;

+  if (Sync.Get_Paused())

+  {

+    s += _paused_String;

+    s += L' ';

+  }

+  if (IS_DEFINED_VAL(_prevPercentValue))

+  {

+    wchar_t temp[32];

+    ConvertUInt64ToString(_prevPercentValue, temp);

+    s += temp;

+    s += L'%';

+  }

+  if (!_foreground)

+  {

+    s += L' ';

+    s += _backgrounded_String;

+  }

+

+  s += L' ';

+  #ifndef _SFX

+  {

+    unsigned len = s.Len();

+    s += MainAddTitle;

+    AddToTitle(s);

+    s.DeleteFrom(len);

+  }

+  #endif

+

+  s += _title;

+  if (!_titleFileName.IsEmpty())

+  {

+    UString fileName = _titleFileName;

+    ReduceString(fileName, kTitleFileNameSizeLimit);

+    s += L' ';

+    s += fileName;

+  }

+  SetText(s);

+}

+

+void CProgressDialog::SetPauseText()

+{

+  SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String);

+  SetTitleText();

+}

+

+void CProgressDialog::OnPauseButton()

+{

+  bool paused = !Sync.Get_Paused();

+  Sync.Set_Paused(paused);

+  UInt32 curTime = ::GetTickCount();

+  if (paused)

+    _elapsedTime += (curTime - _prevTime);

+  SetTaskbarProgressState();

+  _prevTime = curTime;

+  SetPauseText();

+}

+

+void CProgressDialog::SetPriorityText()

+{

+  SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ?

+      _background_String :

+      _foreground_String);

+  SetTitleText();

+}

+

+void CProgressDialog::OnPriorityButton()

+{

+  _foreground = !_foreground;

+  #ifndef UNDER_CE

+  SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS);

+  #endif

+  SetPriorityText();

+}

+

+void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber)

+{

+  int itemIndex = _messageList.GetItemCount();

+  wchar_t sz[16];

+  sz[0] = 0;

+  if (needNumber)

+    ConvertUInt32ToString(_numMessages + 1, sz);

+  _messageList.InsertItem(itemIndex, sz);

+  _messageList.SetSubItem(itemIndex, 1, message);

+}

+

+void CProgressDialog::AddMessage(LPCWSTR message)

+{

+  UString s = message;

+  bool needNumber = true;

+  while (!s.IsEmpty())

+  {

+    int pos = s.Find(L'\n');

+    if (pos < 0)

+      break;

+    AddMessageDirect(s.Left(pos), needNumber);

+    needNumber = false;

+    s.DeleteFrontal(pos + 1);

+  }

+  AddMessageDirect(s, needNumber);

+  _numMessages++;

+}

+

+static unsigned GetNumDigits(UInt32 val)

+{

+  unsigned i;

+  for (i = 0; val >= 10; i++)

+    val /= 10;

+  return i;

+}

+

+void CProgressDialog::UpdateMessagesDialog()

+{

+  UStringVector messages;

+  {

+    NSynchronization::CCriticalSectionLock lock(Sync._cs);

+    unsigned num = Sync.Messages.Size();

+    if (num > _numPostedMessages)

+    {

+      messages.ClearAndReserve(num - _numPostedMessages);

+      for (unsigned i = _numPostedMessages; i < num; i++)

+        messages.AddInReserved(Sync.Messages[i]);

+      _numPostedMessages = num;

+    }

+  }

+  if (!messages.IsEmpty())

+  {

+    FOR_VECTOR (i, messages)

+      AddMessage(messages[i]);

+    if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages))

+    {

+      _messageList.SetColumnWidthAuto(0);

+      _messageList.SetColumnWidthAuto(1);

+      _numAutoSizeMessages = _numPostedMessages;

+    }

+  }

+}

+

+

+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch (buttonID)

+  {

+    // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON

+    case IDCANCEL:

+    {

+      if (_waitCloseByCancelButton)

+      {

+        MessagesDisplayed = true;

+        End(IDCLOSE);

+        break;

+      }

+        

+      bool paused = Sync.Get_Paused();

+      if (!paused)

+        OnPauseButton();

+      _inCancelMessageBox = true;

+      int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);

+      _inCancelMessageBox = false;

+      if (!paused)

+        OnPauseButton();

+      if (res == IDCANCEL || res == IDNO)

+      {

+        if (_externalCloseMessageWasReceived)

+          OnExternalCloseMessage();

+        return true;

+      }

+

+      _cancelWasPressed = true;

+      MessagesDisplayed = true;

+      break;

+    }

+

+    case IDB_PAUSE:

+      OnPauseButton();

+      return true;

+    case IDB_PROGRESS_BACKGROUND:

+      OnPriorityButton();

+      return true;

+  }

+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);

+}

+

+void CProgressDialog::CheckNeedClose()

+{

+  if (_needClose)

+  {

+    PostMessage(kCloseMessage);

+    _needClose = false;

+  }

+}

+

+void CProgressDialog::ProcessWasFinished()

+{

+  // Set Window title here.

+  if (!WaitMode)

+    WaitCreating();

+  

+  if (_wasCreated)

+    PostMessage(kCloseMessage);

+  else

+    _needClose = true;

+}

+

+

+HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)

+{

+  NWindows::CThread thread;

+  RINOK(thread.Create(MyThreadFunction, this));

+  ProgressDialog.Create(title, thread, parentWindow);

+  return S_OK;

+}

+

+static void AddMessageToString(UString &dest, const UString &src)

+{

+  if (!src.IsEmpty())

+  {

+    if (!dest.IsEmpty())

+      dest += L'\n';

+    dest += src;

+  }

+}

+

+void CProgressThreadVirt::Process()

+{

+  CProgressCloser closer(ProgressDialog);

+  UString m;

+  try { Result = ProcessVirt(); }

+  catch(const wchar_t *s) { m = s; }

+  catch(const UString &s) { m = s; }

+  catch(const char *s) { m = GetUnicodeString(s); }

+  catch(int v)

+  {

+    wchar_t s[16];

+    ConvertUInt32ToString(v, s);

+    m = L"Error #";

+    m += s;

+  }

+  catch(...) { m = L"Error"; }

+  if (Result != E_ABORT)

+  {

+    if (m.IsEmpty() && Result != S_OK)

+      m = HResultToMessage(Result);

+  }

+  AddMessageToString(m, FinalMessage.ErrorMessage.Message);

+  AddMessageToString(m, fs2us(ErrorPath1));

+  AddMessageToString(m, fs2us(ErrorPath2));

+

+  CProgressSync &sync = ProgressDialog.Sync;

+  NSynchronization::CCriticalSectionLock lock(sync._cs);

+  if (m.IsEmpty())

+  {

+    if (!FinalMessage.OkMessage.Message.IsEmpty())

+      sync.FinalMessage.OkMessage = FinalMessage.OkMessage;

+  }

+  else

+  {

+    sync.FinalMessage.ErrorMessage.Message = m;

+    if (Result == S_OK)

+      Result = E_FAIL;

+  }

+}

+

+UString HResultToMessage(HRESULT errorCode)

+{

+  if (errorCode == E_OUTOFMEMORY)

+    return LangString(IDS_MEM_ERROR);

+  else

+    return NError::MyFormatMessage(errorCode);

+}

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
new file mode 100644
index 0000000..35e0f17
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -0,0 +1,314 @@
+// ProgressDialog2.h

+

+#ifndef __PROGRESS_DIALOG_2_H

+#define __PROGRESS_DIALOG_2_H

+

+#include "../../../Common/MyCom.h"

+

+#include "../../../Windows/ErrorMsg.h"

+#include "../../../Windows/Synchronization.h"

+#include "../../../Windows/Thread.h"

+

+#include "../../../Windows/Control/Dialog.h"

+#include "../../../Windows/Control/ListView.h"

+#include "../../../Windows/Control/ProgressBar.h"

+

+#include "MyWindowsNew.h"

+

+struct CProgressMessageBoxPair

+{

+  UString Title;

+  UString Message;

+};

+

+struct CProgressFinalMessage

+{

+  CProgressMessageBoxPair ErrorMessage;

+  CProgressMessageBoxPair OkMessage;

+

+  bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); }

+};

+

+class CProgressSync

+{

+  bool _stopped;

+  bool _paused;

+

+public:

+  bool _bytesProgressMode;

+  UInt64 _totalBytes;

+  UInt64 _completedBytes;

+  UInt64 _totalFiles;

+  UInt64 _curFiles;

+  UInt64 _inSize;

+  UInt64 _outSize;

+  

+  UString _titleFileName;

+  UString _status;

+  UString _filePath;

+  bool _isDir;

+

+  UStringVector Messages;

+  CProgressFinalMessage FinalMessage;

+

+  NWindows::NSynchronization::CCriticalSection _cs;

+

+  CProgressSync();

+

+  bool Get_Stopped()

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    return _stopped;

+  }

+  void Set_Stopped(bool val)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _stopped = val;

+  }

+  

+  bool Get_Paused();

+  void Set_Paused(bool val)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _paused = val;

+  }

+  

+  void Set_BytesProgressMode(bool bytesProgressMode)

+  {

+    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);

+    _bytesProgressMode = bytesProgressMode;

+  }

+  

+  HRESULT CheckStop();

+  HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false);

+

+  void Set_NumFilesTotal(UInt64 val);

+  void Set_NumBytesTotal(UInt64 val);

+  void Set_NumFilesCur(UInt64 val);

+  HRESULT Set_NumBytesCur(const UInt64 *val);

+  HRESULT Set_NumBytesCur(UInt64 val);

+  void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize);

+

+  void Set_TitleFileName(const UString &fileName);

+  void Set_Status(const UString &s);

+  void Set_FilePath(const UString &path, bool isDir = false);

+

+  void AddError_Message(const wchar_t *message);

+  void AddError_Message_Name(const wchar_t *message, const wchar_t *name);

+  void AddError_Code_Name(DWORD systemError, const wchar_t *name);

+

+  bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); }

+};

+

+class CProgressDialog: public NWindows::NControl::CModalDialog

+{

+  UString _titleFileName;

+  UString _filePath;

+  UString _status;

+  bool _isDir;

+

+  UString _background_String;

+  UString _backgrounded_String;

+  UString _foreground_String;

+  UString _pause_String;

+  UString _continue_String;

+  UString _paused_String;

+

+  int _buttonSizeX;

+  int _buttonSizeY;

+

+  UINT_PTR _timer;

+

+  UString _title;

+

+  class CU64ToI32Converter

+  {

+    unsigned _numShiftBits;

+    UInt64 _range;

+  public:

+    CU64ToI32Converter(): _numShiftBits(0), _range(1) {}

+    void Init(UInt64 range)

+    {

+      _range = range;

+      // Windows CE doesn't like big number for ProgressBar.

+      for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++)

+        range >>= 1;

+    }

+    int Count(UInt64 val)

+    {

+      int res = (int)(val >> _numShiftBits);

+      if (val == _range)

+        res++;

+      return res;

+    }

+  };

+  

+  CU64ToI32Converter _progressConv;

+  UInt64 _progressBar_Pos;

+  UInt64 _progressBar_Range;

+  

+  NWindows::NControl::CProgressBar m_ProgressBar;

+  NWindows::NControl::CListView _messageList;

+  

+  int _numMessages;

+

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  CMyComPtr<ITaskbarList3> _taskbarList;

+  #endif

+  HWND _hwndForTaskbar;

+

+  UInt32 _prevTime;

+  UInt64 _elapsedTime;

+

+  UInt64 _prevPercentValue;

+  UInt64 _prevElapsedSec;

+  UInt64 _prevRemainingSec;

+

+  UInt64 _totalBytes_Prev;

+  UInt64 _processed_Prev;

+  UInt64 _packed_Prev;

+  UInt64 _ratio_Prev;

+  UString _filesStr_Prev;

+

+  unsigned _prevSpeed_MoveBits;

+  UInt64 _prevSpeed;

+

+  bool _foreground;

+

+  unsigned _numReduceSymbols;

+

+  bool _wasCreated;

+  bool _needClose;

+

+  unsigned _numPostedMessages;

+  UInt32 _numAutoSizeMessages;

+

+  bool _errorsWereDisplayed;

+

+  bool _waitCloseByCancelButton;

+  bool _cancelWasPressed;

+  

+  bool _inCancelMessageBox;

+  bool _externalCloseMessageWasReceived;

+

+

+  #ifdef __ITaskbarList3_INTERFACE_DEFINED__

+  void SetTaskbarProgressState(TBPFLAG tbpFlags)

+  {

+    if (_taskbarList && _hwndForTaskbar)

+      _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags);

+  }

+  #endif

+  void SetTaskbarProgressState();

+

+  void UpdateStatInfo(bool showAll);

+  bool OnTimer(WPARAM timerID, LPARAM callback);

+  void SetProgressRange(UInt64 range);

+  void SetProgressPos(UInt64 pos);

+  virtual bool OnInit();

+  virtual bool OnSize(WPARAM wParam, int xSize, int ySize);

+  virtual void OnCancel();

+  virtual void OnOK();

+  NWindows::NSynchronization::CManualResetEvent _createDialogEvent;

+  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;

+  #ifndef _SFX

+  void AddToTitle(LPCWSTR string);

+  #endif

+

+  void SetPauseText();

+  void SetPriorityText();

+  void OnPauseButton();

+  void OnPriorityButton();

+  bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+

+  void SetTitleText();

+  void ShowSize(int id, UInt64 val, UInt64 &prev);

+

+  void UpdateMessagesDialog();

+

+  void AddMessageDirect(LPCWSTR message, bool needNumber);

+  void AddMessage(LPCWSTR message);

+

+  bool OnExternalCloseMessage();

+  void EnableErrorsControls(bool enable);

+

+  void ShowAfterMessages(HWND wndParent);

+

+  void CheckNeedClose();

+public:

+  CProgressSync Sync;

+  bool CompressingMode;

+  bool WaitMode;

+  bool ShowCompressionInfo;

+  bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.

+  int IconID;

+

+  HWND MainWindow;

+  #ifndef _SFX

+  UString MainTitle;

+  UString MainAddTitle;

+  ~CProgressDialog();

+  #endif

+

+  CProgressDialog();

+  void WaitCreating()

+  {

+    _createDialogEvent.Set();

+    _dialogCreatedEvent.Lock();

+  }

+

+  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);

+

+  void ProcessWasFinished();

+};

+

+

+class CProgressCloser

+{

+  CProgressDialog *_p;

+public:

+  CProgressCloser(CProgressDialog &p) : _p(&p) {}

+  ~CProgressCloser() { _p->ProcessWasFinished(); }

+};

+

+class CProgressThreadVirt

+{

+  FString ErrorPath1;

+  FString ErrorPath2;

+protected:

+  CProgressFinalMessage FinalMessage;

+

+  // error if any of HRESULT, ErrorMessage, ErrorPath

+  virtual HRESULT ProcessVirt() = 0;

+  void Process();

+public:

+  HRESULT Result;

+  bool ThreadFinishedOK; // if there is no fatal exception

+  CProgressDialog ProgressDialog;

+

+  static THREAD_FUNC_DECL MyThreadFunction(void *param)

+  {

+    CProgressThreadVirt *p = (CProgressThreadVirt *)param;

+    try

+    {

+      p->Process();

+      p->ThreadFinishedOK = true;

+    }

+    catch (...) { p->Result = E_FAIL; }

+    return 0;

+  }

+

+  void SetErrorPath1(const FString &path) { ErrorPath1 = path; }

+  void SetErrorPath2(const FString &path) { ErrorPath2 = path; }

+

+  HRESULT Create(const UString &title, HWND parentWindow = 0);

+  CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}

+

+  CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }

+

+};

+

+UString HResultToMessage(HRESULT errorCode);

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc
new file mode 100644
index 0000000..535a008
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc
@@ -0,0 +1,40 @@
+#include "ProgressDialog2Res.h"

+#include "../../GuiCommon.rc"

+

+#undef DIALOG_ID

+#define DIALOG_ID  IDD_PROGRESS

+#define xc 360

+#define k 11

+#define z1s 16

+

+#include "ProgressDialog2a.rc"

+

+#ifdef UNDER_CE

+

+#include "../../GuiCommon.rc"

+

+

+#undef DIALOG_ID

+#undef m

+#undef k

+#undef z1s

+

+#define DIALOG_ID  IDD_PROGRESS_2

+#define m 4

+#define k 8

+#define z1s 12

+

+#define xc 280

+

+#include "ProgressDialog2a.rc"

+

+#endif

+

+STRINGTABLE DISCARDABLE

+{

+  IDS_PROGRESS_PAUSED     "Paused"

+  IDS_PROGRESS_FOREGROUND "&Foreground"

+  IDS_CONTINUE            "&Continue"

+  IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?"

+  IDS_CLOSE "&Close"

+}

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
new file mode 100644
index 0000000..54f02f0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
@@ -0,0 +1,48 @@
+#define IDD_PROGRESS       97

+#define IDD_PROGRESS_2  10097

+

+#define IDS_CLOSE                  408

+#define IDS_CONTINUE               411

+

+#define IDB_PROGRESS_BACKGROUND    444

+#define IDS_PROGRESS_FOREGROUND    445

+#define IDB_PAUSE                  446

+#define IDS_PROGRESS_PAUSED        447

+#define IDS_PROGRESS_ASK_CANCEL    448

+

+#define IDT_PROGRESS_PACKED       1008

+#define IDT_PROGRESS_FILES        1032

+

+#define IDT_PROGRESS_ELAPSED      3900

+#define IDT_PROGRESS_REMAINING    3901

+#define IDT_PROGRESS_TOTAL        3902

+#define IDT_PROGRESS_SPEED        3903

+#define IDT_PROGRESS_PROCESSED    3904

+#define IDT_PROGRESS_RATIO        3905

+#define IDT_PROGRESS_ERRORS       3906

+

+#define IDC_PROGRESS1              100

+#define IDL_PROGRESS_MESSAGES      101

+#define IDT_PROGRESS_FILE_NAME     102

+#define IDT_PROGRESS_STATUS        103

+

+#define IDT_PROGRESS_PACKED_VAL    110

+#define IDT_PROGRESS_FILES_VAL     111

+

+#define IDT_PROGRESS_ELAPSED_VAL   120

+#define IDT_PROGRESS_REMAINING_VAL 121

+#define IDT_PROGRESS_TOTAL_VAL     122

+#define IDT_PROGRESS_SPEED_VAL     123

+#define IDT_PROGRESS_PROCESSED_VAL 124

+#define IDT_PROGRESS_RATIO_VAL     125

+#define IDT_PROGRESS_ERRORS_VAL    126

+

+

+#ifdef UNDER_CE

+#define MY_PROGRESS_VAL_UNITS  44

+#else

+#define MY_PROGRESS_VAL_UNITS  76

+#endif

+#define MY_PROGRESS_LABEL_UNITS_MIN   60

+#define MY_PROGRESS_LABEL_UNITS_START 90

+#define MY_PROGRESS_PAD_UNITS  4

diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
new file mode 100644
index 0000000..f1daec7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
@@ -0,0 +1,80 @@
+#undef bxs

+#define bxs 80

+

+#define x0s MY_PROGRESS_LABEL_UNITS_START

+#define x1s MY_PROGRESS_VAL_UNITS

+#define x2s MY_PROGRESS_LABEL_UNITS_START

+#define x3s MY_PROGRESS_VAL_UNITS

+

+#define x1 (m + x0s)

+#define x3 (xs - m - x3s)

+#define x2 (x3 - x2s)

+

+#undef y0

+#undef y1

+#undef y2

+#undef y3

+#undef y4

+

+#undef z0

+#undef z1

+#undef z2

+#undef z3

+

+#define y0 m

+#define y1 (y0 + k)

+#define y2 (y1 + k)

+#define y3 (y2 + k)

+#define y4 (y3 + k)

+

+#define z3 (y4 + k + 1)

+

+#define z2 (z3 + k + 1)

+#define z2s 24

+

+#define z1 (z2 + z2s)

+

+#define z0 (z1 + z1s + m)

+#define z0s 48

+

+#define yc (z0 + z0s + bys)

+

+

+DIALOG_ID  DIALOG  0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT

+CAPTION "Progress"

+{

+  DEFPUSHBUTTON  "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys

+  PUSHBUTTON     "&Pause",      IDB_PAUSE                bx2, by, bxs, bys

+  PUSHBUTTON     "Cancel",      IDCANCEL,                bx1, by, bxs, bys

+

+  LTEXT  "Elapsed time:",      IDT_PROGRESS_ELAPSED,   m, y0, x0s, 8

+  LTEXT  "Remaining time:",    IDT_PROGRESS_REMAINING, m, y1, x0s, 8

+  LTEXT  "Files:",             IDT_PROGRESS_FILES,     m, y2, x0s, 8

+  LTEXT  "Compression ratio:", IDT_PROGRESS_RATIO,     m, y3, x0s, 8

+  LTEXT  "Errors:",            IDT_PROGRESS_ERRORS,    m, y4, x0s, 8

+

+  LTEXT  "Total size:",        IDT_PROGRESS_TOTAL,    x2, y0, x2s, 8

+  LTEXT  "Speed:",             IDT_PROGRESS_SPEED,    x2, y1, x2s, 8

+  LTEXT  "Processed:",         IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8

+  LTEXT  "Compressed size:"  , IDT_PROGRESS_PACKED,   x2, y3, x2s, 8

+

+  RTEXT  "",  IDT_PROGRESS_ELAPSED_VAL,   x1, y0, x1s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_FILES_VAL,     x1, y2, x1s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_RATIO_VAL,     x1, y3, x1s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_ERRORS_VAL,    x1, y4, x1s, MY_TEXT_NOPREFIX

+

+  RTEXT  "",  IDT_PROGRESS_TOTAL_VAL,     x3, y0, x3s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_SPEED_VAL,     x3, y1, x3s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX

+  RTEXT  "",  IDT_PROGRESS_PACKED_VAL,    x3, y3, x3s, MY_TEXT_NOPREFIX

+

+  LTEXT  "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX

+  CONTROL  "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s

+  

+  CONTROL  "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s

+

+  CONTROL  "List1", IDL_PROGRESS_MESSAGES, "SysListView32",

+           LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,

+           m, z0, xc, z0s

+}

diff --git a/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/CPP/7zip/UI/FileManager/ProgressDialogRes.h
new file mode 100644
index 0000000..a281418
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialogRes.h
@@ -0,0 +1,3 @@
+#define IDD_PROGRESS  97

+

+#define IDC_PROGRESS1  100

diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
new file mode 100644
index 0000000..67c9b6e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -0,0 +1,92 @@
+

+

+#define IDS_PROP_PATH             1003

+#define IDS_PROP_NAME             1004

+#define IDS_PROP_EXTENSION        1005

+#define IDS_PROP_IS_FOLDER        1006

+#define IDS_PROP_SIZE             1007

+#define IDS_PROP_PACKED_SIZE      1008

+#define IDS_PROP_ATTRIBUTES       1009

+#define IDS_PROP_CTIME            1010

+#define IDS_PROP_ATIME            1011

+#define IDS_PROP_MTIME            1012

+#define IDS_PROP_SOLID            1013

+#define IDS_PROP_C0MMENTED        1014

+#define IDS_PROP_ENCRYPTED        1015

+#define IDS_PROP_SPLIT_BEFORE     1016

+#define IDS_PROP_SPLIT_AFTER      1017

+#define IDS_PROP_DICTIONARY_SIZE  1018

+#define IDS_PROP_CRC              1019

+#define IDS_PROP_FILE_TYPE        1020

+#define IDS_PROP_ANTI             1021

+#define IDS_PROP_METHOD           1022

+#define IDS_PROP_HOST_OS          1023

+#define IDS_PROP_FILE_SYSTEM      1024

+#define IDS_PROP_USER             1025

+#define IDS_PROP_GROUP            1026

+#define IDS_PROP_BLOCK            1027

+#define IDS_PROP_COMMENT          1028

+#define IDS_PROP_POSITION         1029

+#define IDS_PROP_PREFIX           1030

+#define IDS_PROP_FOLDERS          1031

+#define IDS_PROP_FILES            1032

+#define IDS_PROP_VERSION          1033

+#define IDS_PROP_VOLUME           1034

+#define IDS_PROP_IS_VOLUME        1035

+#define IDS_PROP_OFFSET           1036

+#define IDS_PROP_LINKS            1037

+#define IDS_PROP_NUM_BLOCKS       1038

+#define IDS_PROP_NUM_VOLUMES      1039

+

+#define IDS_PROP_BIT64            1041

+#define IDS_PROP_BIG_ENDIAN       1042

+#define IDS_PROP_CPU              1043

+#define IDS_PROP_PHY_SIZE         1044

+#define IDS_PROP_HEADERS_SIZE     1045

+#define IDS_PROP_CHECKSUM         1046

+#define IDS_PROP_CHARACTS         1047

+#define IDS_PROP_VA               1048

+#define IDS_PROP_ID               1049

+#define IDS_PROP_SHORT_NAME       1050

+#define IDS_PROP_CREATOR_APP      1051

+#define IDS_PROP_SECTOR_SIZE      1052

+#define IDS_PROP_POSIX_ATTRIB     1053

+#define IDS_PROP_SYM_LINK         1054

+#define IDS_PROP_ERROR            1055

+#define IDS_PROP_TOTAL_SIZE       1056

+#define IDS_PROP_FREE_SPACE       1057

+#define IDS_PROP_CLUSTER_SIZE     1058

+#define IDS_PROP_VOLUME_NAME      1059

+#define IDS_PROP_LOCAL_NAME       1060

+#define IDS_PROP_PROVIDER         1061

+#define IDS_PROP_NT_SECURITY      1062

+#define IDS_PROP_ALT_STREAM       1063

+#define IDS_PROP_AUX              1064

+#define IDS_PROP_DELETED          1065

+#define IDS_PROP_IS_TREE          1066

+#define IDS_PROP_SHA1             1067

+#define IDS_PROP_SHA256           1068

+#define IDS_PROP_ERROR_TYPE       1069

+#define IDS_PROP_NUM_ERRORS       1070

+#define IDS_PROP_ERROR_FLAGS      1071

+#define IDS_PROP_WARNING_FLAGS    1072

+#define IDS_PROP_WARNING          1073

+#define IDS_PROP_NUM_STREAMS      1074

+#define IDS_PROP_NUM_ALT_STREAMS  1075

+#define IDS_PROP_ALT_STREAMS_SIZE 1076

+#define IDS_PROP_VIRTUAL_SIZE     1077

+#define IDS_PROP_UNPACK_SIZE      1078

+#define IDS_PROP_TOTAL_PHY_SIZE   1079

+#define IDS_PROP_VOLUME_INDEX     1080

+#define IDS_PROP_SUBTYPE          1081

+#define IDS_PROP_SHORT_COMMENT    1082

+#define IDS_PROP_CODE_PAGE        1083

+#define IDS_PROP_IS_NOT_ARC_TYPE  1084

+#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085

+#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086

+#define IDS_PROP_TAIL_SIZE        1087

+#define IDS_PROP_EMB_STUB_SIZE    1088

+#define IDS_PROP_NT_REPARSE       1089

+#define IDS_PROP_HARD_LINK        1090

+#define IDS_PROP_INODE            1091

+#define IDS_PROP_STREAM_ID        1092

diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
new file mode 100644
index 0000000..4cc99ec
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -0,0 +1,253 @@
+// SysIconUtils.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../../../Common/StringConvert.h"

+#endif

+

+#include "../../../Windows/FileDir.h"

+

+#include "SysIconUtils.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+int GetIconIndexForCSIDL(int csidl)

+{

+  LPITEMIDLIST pidl = 0;

+  SHGetSpecialFolderLocation(NULL, csidl, &pidl);

+  if (pidl)

+  {

+    SHFILEINFO shellInfo;

+    SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL,

+      &shellInfo, sizeof(shellInfo),

+      SHGFI_PIDL | SHGFI_SYSICONINDEX);

+    IMalloc  *pMalloc;

+    SHGetMalloc(&pMalloc);

+    if (pMalloc)

+    {

+      pMalloc->Free(pidl);

+      pMalloc->Release();

+    }

+    return shellInfo.iIcon;

+  }

+  return 0;

+}

+

+#ifndef _UNICODE

+typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);

+

+struct CSHGetFileInfoInit

+{

+  SHGetFileInfoWP shGetFileInfoW;

+  CSHGetFileInfoInit()

+  {

+    shGetFileInfoW = (SHGetFileInfoWP)

+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");

+  }

+} g_SHGetFileInfoInit;

+#endif

+

+static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)

+{

+  #ifdef _UNICODE

+  return SHGetFileInfo

+  #else

+  if (g_SHGetFileInfoInit.shGetFileInfoW == 0)

+    return 0;

+  return g_SHGetFileInfoInit.shGetFileInfoW

+  #endif

+  (pszPath, attrib, psfi, cbFileInfo, uFlags);

+}

+

+DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    SHFILEINFO shellInfo;

+    DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,

+      sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);

+    iconIndex = shellInfo.iIcon;

+    return res;

+  }

+  else

+  #endif

+  {

+    SHFILEINFOW shellInfo;

+    DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,

+      sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);

+    iconIndex = shellInfo.iIcon;

+    return res;

+  }

+}

+

+/*

+DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    SHFILEINFO shellInfo;

+    shellInfo.szTypeName[0] = 0;

+    DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,

+        sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);

+    if (typeName)

+      *typeName = GetUnicodeString(shellInfo.szTypeName);

+    iconIndex = shellInfo.iIcon;

+    return res;

+  }

+  else

+  #endif

+  {

+    SHFILEINFOW shellInfo;

+    shellInfo.szTypeName[0] = 0;

+    DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,

+        sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);

+    if (typeName)

+      *typeName = shellInfo.szTypeName;

+    iconIndex = shellInfo.iIcon;

+    return res;

+  }

+}

+*/

+

+static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, int &insertPos)

+{

+  unsigned left = 0, right = vect.Size();

+  while (left != right)

+  {

+    unsigned mid = (left + right) / 2;

+    DWORD midAttrib = vect[mid].Attrib;

+    if (attrib == midAttrib)

+      return mid;

+    if (attrib < midAttrib)

+      right = mid;

+    else

+      left = mid + 1;

+  }

+  insertPos = left;

+  return -1;

+}

+

+static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos)

+{

+  unsigned left = 0, right = vect.Size();

+  while (left != right)

+  {

+    unsigned mid = (left + right) / 2;

+    int compare = MyStringCompareNoCase(ext, vect[mid].Ext);

+    if (compare == 0)

+      return mid;

+    if (compare < 0)

+      right = mid;

+    else

+      left = mid + 1;

+  }

+  insertPos = left;

+  return -1;

+}

+

+int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)

+{

+  int dotPos = -1;

+  unsigned i;

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

+  {

+    wchar_t c = fileName[i];

+    if (c == 0)

+      break;

+    if (c == '.')

+      dotPos = i;

+  }

+

+  /*

+  if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)

+  {

+    char s[256];

+    sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);

+    OutputDebugStringA(s);

+    OutputDebugStringW(fileName);

+  }

+  */

+

+  if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)

+  {

+    int insertPos = 0;

+    int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);

+    if (index >= 0)

+    {

+      // if (typeName) *typeName = _attribMap[index].TypeName;

+      return _attribMap[index].IconIndex;

+    }

+    CAttribIconPair pair;

+    GetRealIconIndex(

+        #ifdef UNDER_CE

+        FTEXT("\\")

+        #endif

+        FTEXT("__DIR__")

+        , attrib, pair.IconIndex

+        // , pair.TypeName

+        );

+

+    /*

+    char s[256];

+    sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);

+    OutputDebugStringA(s);

+    */

+

+    pair.Attrib = attrib;

+    _attribMap.Insert(insertPos, pair);

+    // if (typeName) *typeName = pair.TypeName;

+    return pair.IconIndex;

+  }

+

+  const wchar_t *ext = fileName + dotPos + 1;

+  int insertPos = 0;

+  int index = FindInSorted_Ext(_extMap, ext, insertPos);

+  if (index >= 0)

+  {

+    const CExtIconPair &pa = _extMap[index];

+    // if (typeName) *typeName = pa.TypeName;

+    return pa.IconIndex;

+  }

+

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

+  {

+    wchar_t c = ext[i];

+    if (c == 0)

+      break;

+    if (c < L'0' || c > L'9')

+      break;

+  }

+  if (i != 0 && ext[i] == 0)

+  {

+    // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003

+    if (!SplitIconIndex_Defined)

+    {

+      GetRealIconIndex(

+          #ifdef UNDER_CE

+          FTEXT("\\")

+          #endif

+          FTEXT("__FILE__.001"), 0, SplitIconIndex);

+      SplitIconIndex_Defined = true;

+    }

+    return SplitIconIndex;

+  }

+

+  CExtIconPair pair;

+  pair.Ext = ext;

+  GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);

+  _extMap.Insert(insertPos, pair);

+  // if (typeName) *typeName = pair.TypeName;

+  return pair.IconIndex;

+}

+

+/*

+int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)

+{

+  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
new file mode 100644
index 0000000..5655c76
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -0,0 +1,58 @@
+// SysIconUtils.h

+

+#ifndef __SYS_ICON_UTILS_H

+#define __SYS_ICON_UTILS_H

+

+#include "../../../Common/MyString.h"

+

+struct CExtIconPair

+{

+  UString Ext;

+  int IconIndex;

+  // UString TypeName;

+

+  // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }

+};

+

+struct CAttribIconPair

+{

+  DWORD Attrib;

+  int IconIndex;

+  // UString TypeName;

+

+  // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }

+};

+

+class CExtToIconMap

+{

+public:

+  CRecordVector<CAttribIconPair> _attribMap;

+  CObjectVector<CExtIconPair> _extMap;

+  int SplitIconIndex;

+  int SplitIconIndex_Defined;

+  

+  CExtToIconMap(): SplitIconIndex_Defined(false) {}

+

+  void Clear()

+  {

+    SplitIconIndex_Defined = false;

+    _extMap.Clear();

+    _attribMap.Clear();

+  }

+  int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);

+  // int GetIconIndex(DWORD attrib, const UString &fileName);

+};

+

+DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex);

+int GetIconIndexForCSIDL(int csidl);

+

+inline HIMAGELIST GetSysImageList(bool smallIcons)

+{

+  SHFILEINFO shellInfo;

+  return (HIMAGELIST)SHGetFileInfo(TEXT(""),

+      FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY,

+      &shellInfo, sizeof(shellInfo),

+      SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));

+}

+

+#endif

diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
new file mode 100644
index 0000000..bffdc97
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -0,0 +1,171 @@
+#include "resourceGui.h"

+

+#define IDR_MENUBAR1      70

+#define IDM_MENU          71

+#define IDR_ACCELERATOR1  72

+

+#define IDB_ADD      100

+#define IDB_EXTRACT  101

+#define IDB_TEST     102

+#define IDB_COPY     103

+#define IDB_MOVE     104

+#define IDB_DELETE   105

+#define IDB_INFO     106

+

+#define IDB_ADD2     150

+#define IDB_EXTRACT2 151

+#define IDB_TEST2    152

+#define IDB_COPY2    153

+#define IDB_MOVE2    154

+#define IDB_DELETE2  155

+#define IDB_INFO2    156

+

+#define IDM_HASH_ALL             101

+#define IDM_CRC32                102

+#define IDM_CRC64                103

+#define IDM_SHA1                 104

+#define IDM_SHA256               105

+

+#define IDM_OPEN                 540

+#define IDM_OPEN_INSIDE          541

+#define IDM_OPEN_OUTSIDE         542

+#define IDM_FILE_VIEW            543

+#define IDM_FILE_EDIT            544

+#define IDM_RENAME               545

+#define IDM_COPY_TO              546

+#define IDM_MOVE_TO              547

+#define IDM_DELETE               548

+#define IDM_SPLIT                549

+#define IDM_COMBINE              550

+#define IDM_PROPERTIES           551

+#define IDM_COMMENT              552

+#define IDM_CRC                  553

+#define IDM_DIFF                 554

+#define IDM_CREATE_FOLDER        555

+#define IDM_CREATE_FILE          556

+// #define IDM_EXIT                 557

+#define IDM_LINK                 558

+

+#define IDM_SELECT_ALL           600

+#define IDM_DESELECT_ALL         601

+#define IDM_INVERT_SELECTION     602

+#define IDM_SELECT               603

+#define IDM_DESELECT             604

+#define IDM_SELECT_BY_TYPE       605

+#define IDM_DESELECT_BY_TYPE     606

+

+#define IDM_VIEW_LARGE_ICONS     700

+#define IDM_VIEW_SMALL_ICONS     701

+#define IDM_VIEW_LIST            702

+#define IDM_VIEW_DETAILS         703

+

+#define IDM_VIEW_ARANGE_BY_NAME  710

+#define IDM_VIEW_ARANGE_BY_TYPE  711

+#define IDM_VIEW_ARANGE_BY_DATE  712

+#define IDM_VIEW_ARANGE_BY_SIZE  713

+

+#define IDM_VIEW_ARANGE_NO_SORT  730

+#define IDM_VIEW_FLAT_VIEW       731

+#define IDM_VIEW_TWO_PANELS      732

+#define IDM_VIEW_TOOLBARS        733

+#define IDM_OPEN_ROOT_FOLDER     734

+#define IDM_OPEN_PARENT_FOLDER   735

+#define IDM_FOLDERS_HISTORY      736

+#define IDM_VIEW_REFRESH         737

+#define IDM_VIEW_AUTO_REFRESH    738

+// #define IDM_VIEW_SHOW_DELETED    739

+// #define IDM_VIEW_SHOW_STREAMS    740

+

+#define IDM_VIEW_ARCHIVE_TOOLBAR            750

+#define IDM_VIEW_STANDARD_TOOLBAR           751

+#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS     752

+#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753

+

+#define IDS_BOOKMARK             801

+

+#define IDM_OPTIONS              900

+#define IDM_BENCHMARK            901

+#define IDM_BENCHMARK2           902

+

+#define IDM_HELP_CONTENTS        960

+#define IDM_ABOUT                961

+

+#define IDS_OPTIONS                     2100

+

+#define IDS_N_SELECTED_ITEMS            3002

+

+#define IDS_FILE_EXIST                  3008

+#define IDS_WANT_UPDATE_MODIFIED_FILE   3009

+#define IDS_CANNOT_UPDATE_FILE          3010

+#define IDS_CANNOT_START_EDITOR         3011

+#define IDS_VIRUS                       3012

+#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER  3013

+#define IDS_SELECT_ONE_FILE             3014

+#define IDS_SELECT_FILES                3015

+#define IDS_TOO_MANY_ITEMS              3016

+

+#define IDS_COPY                        6000

+#define IDS_MOVE                        6001

+#define IDS_COPY_TO                     6002

+#define IDS_MOVE_TO                     6003

+#define IDS_COPYING                     6004

+#define IDS_MOVING                      6005

+#define IDS_RENAMING                    6006

+

+#define IDS_OPERATION_IS_NOT_SUPPORTED  6008

+#define IDS_ERROR_RENAMING              6009

+#define IDS_CONFIRM_FILE_COPY           6010

+#define IDS_WANT_TO_COPY_FILES          6011

+

+#define IDS_CONFIRM_FILE_DELETE         6100

+#define IDS_CONFIRM_FOLDER_DELETE       6101

+#define IDS_CONFIRM_ITEMS_DELETE        6102

+#define IDS_WANT_TO_DELETE_FILE         6103

+#define IDS_WANT_TO_DELETE_FOLDER       6104

+#define IDS_WANT_TO_DELETE_ITEMS        6105

+#define IDS_DELETING                    6106

+#define IDS_ERROR_DELETING              6107

+#define IDS_ERROR_LONG_PATH_TO_RECYCLE  6108

+

+#define IDS_CREATE_FOLDER               6300

+#define IDS_CREATE_FILE                 6301

+#define IDS_CREATE_FOLDER_NAME          6302

+#define IDS_CREATE_FILE_NAME            6303

+#define IDS_CREATE_FOLDER_DEFAULT_NAME  6304

+#define IDS_CREATE_FILE_DEFAULT_NAME    6305

+#define IDS_CREATE_FOLDER_ERROR         6306

+#define IDS_CREATE_FILE_ERROR           6307

+

+#define IDS_COMMENT                     6400

+#define IDS_COMMENT2                    6401

+#define IDS_SELECT                      6402

+#define IDS_DESELECT                    6403

+#define IDS_SELECT_MASK                 6404

+

+#define IDS_PROPERTIES                  6600

+#define IDS_FOLDERS_HISTORY             6601

+

+#define IDS_COMPUTER                    7100

+#define IDS_NETWORK                     7101

+#define IDS_DOCUMENTS                   7102

+#define IDS_SYSTEM                      7103

+

+#define IDS_ADD                         7200

+#define IDS_EXTRACT                     7201

+#define IDS_TEST                        7202

+#define IDS_BUTTON_COPY                 7203

+#define IDS_BUTTON_MOVE                 7204

+#define IDS_BUTTON_DELETE               7205

+#define IDS_BUTTON_INFO                 7206

+

+#define IDS_SPLITTING                   7303

+#define IDS_SPLIT_CONFIRM_TITLE         7304

+#define IDS_SPLIT_CONFIRM_MESSAGE       7305

+#define IDS_SPLIT_VOL_MUST_BE_SMALLER   7306

+

+#define IDS_COMBINE                     7400

+#define IDS_COMBINE_TO                  7401

+#define IDS_COMBINING                   7402

+#define IDS_COMBINE_SELECT_ONE_FILE     7403

+#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404

+#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405

diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h
new file mode 100644
index 0000000..025f316
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resourceGui.h
@@ -0,0 +1,15 @@
+#define IDI_ICON  1

+

+#define IDS_MESSAGE_NO_ERRORS           3001

+

+#define IDS_PROGRESS_TESTING            3302

+#define IDS_OPENNING                    3303

+#define IDS_SCANNING                    3304

+

+#define IDS_CHECKSUM_CALCULATING        7500

+#define IDS_CHECKSUM_INFORMATION        7501

+#define IDS_CHECKSUM_CRC_DATA           7502

+#define IDS_CHECKSUM_CRC_DATA_NAMES     7503

+#define IDS_CHECKSUM_CRC_STREAMS_NAMES  7504

+

+#define IDS_INCORRECT_VOLUME_SIZE       7307

diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc
new file mode 100644
index 0000000..5fb2b3a
--- /dev/null
+++ b/CPP/7zip/UI/GUI/Extract.rc
@@ -0,0 +1,52 @@
+#include "ExtractRes.h"

+

+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

+

+STRINGTABLE DISCARDABLE

+BEGIN

+  IDS_MEM_ERROR  "The system cannot allocate the required amount of memory"

+  IDS_CANNOT_CREATE_FOLDER  "Cannot create folder '{0}'"

+  IDS_UPDATE_NOT_SUPPORTED  "Update operations are not supported for this archive."

+  IDS_CANT_OPEN_ARCHIVE  "Can not open file '{0}' as archive"

+  IDS_CANT_OPEN_ENCRYPTED_ARCHIVE  "Can not open encrypted archive '{0}'. Wrong password?"

+  IDS_UNSUPPORTED_ARCHIVE_TYPE  "Unsupported archive type"

+

+  IDS_PROGRESS_EXTRACTING "Extracting"

+

+  IDS_EXTRACT_SET_FOLDER  "Specify a location for extracted files."

+

+  IDS_EXTRACT_PATHS_FULL    "Full pathnames"

+  IDS_EXTRACT_PATHS_NO      "No pathnames"

+  IDS_EXTRACT_PATHS_ABS     "Absolute pathnames"

+  IDS_PATH_MODE_RELAT       "Relative pathnames"

+

+  IDS_EXTRACT_OVERWRITE_ASK             "Ask before overwrite"

+  IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT  "Overwrite without prompt"

+  IDS_EXTRACT_OVERWRITE_SKIP_EXISTING   "Skip existing files"

+  IDS_EXTRACT_OVERWRITE_RENAME          "Auto rename"

+  IDS_EXTRACT_OVERWRITE_RENAME_EXISTING "Auto rename existing files"

+

+  IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD   "Unsupported compression method for '{0}'."

+  IDS_EXTRACT_MESSAGE_DATA_ERROR           "Data error in '{0}'. File is broken"

+  IDS_EXTRACT_MESSAGE_CRC_ERROR            "CRC failed in '{0}'. File is broken."

+  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_ENCRYPTED            "Encrypted file"

+

+  IDS_EXTRACT_MSG_UNSUPPORTED_METHOD   "Unsupported compression method"

+  IDS_EXTRACT_MSG_DATA_ERROR           "Data error"

+  IDS_EXTRACT_MSG_CRC_ERROR            "CRC failed"

+  IDS_EXTRACT_MSG_UNAVAILABLE_DATA     "Unavailable data"

+  IDS_EXTRACT_MSG_UEXPECTED_END        "Unexpected end of data";

+  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_OPEN_MSG_UNAVAILABLE_START  "Unavailable start of archive"

+  IDS_OPEN_MSG_UNCONFIRMED_START  "Unconfirmed start of archive"

+  // IDS_OPEN_MSG_ERROR_FLAGS + 5  "Unexpected end of archive"

+  // IDS_OPEN_MSG_ERROR_FLAGS + 6  "There are data after the end of archive"

+  IDS_OPEN_MSG_UNSUPPORTED_FEATURE  "Unsupported feature"

+END

diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
new file mode 100644
index 0000000..bb0a655
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -0,0 +1,418 @@
+// ExtractDialog.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/Wildcard.h"

+

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/ResourceString.h"

+

+#ifndef NO_REGISTRY

+#include "../FileManager/HelpUtils.h"

+#endif

+

+

+#include "../FileManager/BrowseDialog.h"

+#include "../FileManager/LangUtils.h"

+#include "../FileManager/resourceGui.h"

+

+#include "ExtractDialog.h"

+#include "ExtractDialogRes.h"

+#include "ExtractRes.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+

+extern HINSTANCE g_hInstance;

+

+static const UInt32 kPathMode_IDs[] =

+{

+  IDS_EXTRACT_PATHS_FULL,

+  IDS_EXTRACT_PATHS_NO,

+  IDS_EXTRACT_PATHS_ABS

+};

+

+static const UInt32 kOverwriteMode_IDs[] =

+{

+  IDS_EXTRACT_OVERWRITE_ASK,

+  IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT,

+  IDS_EXTRACT_OVERWRITE_SKIP_EXISTING,

+  IDS_EXTRACT_OVERWRITE_RENAME,

+  IDS_EXTRACT_OVERWRITE_RENAME_EXISTING

+};

+

+#ifndef _SFX

+

+static const

+  // NExtract::NPathMode::EEnum

+  int

+  kPathModeButtonsVals[] =

+{

+  NExtract::NPathMode::kFullPaths,

+  NExtract::NPathMode::kNoPaths,

+  NExtract::NPathMode::kAbsPaths

+};

+

+static const

+  int

+  // NExtract::NOverwriteMode::EEnum

+  kOverwriteButtonsVals[] =

+{

+  NExtract::NOverwriteMode::kAsk,

+  NExtract::NOverwriteMode::kOverwrite,

+  NExtract::NOverwriteMode::kSkip,

+  NExtract::NOverwriteMode::kRename,

+  NExtract::NOverwriteMode::kRenameExisting

+};

+

+#endif

+

+#ifdef LANG

+

+static const UInt32 kLangIDs[] =

+{

+  IDT_EXTRACT_EXTRACT_TO,

+  IDT_EXTRACT_PATH_MODE,

+  IDT_EXTRACT_OVERWRITE_MODE,

+  // IDX_EXTRACT_ALT_STREAMS,

+  IDX_EXTRACT_NT_SECUR,

+  IDX_EXTRACT_ELIM_DUP,

+  IDG_PASSWORD,

+  IDX_PASSWORD_SHOW

+};

+#endif

+

+// static const int kWildcardsButtonIndex = 2;

+

+#ifndef NO_REGISTRY

+static const unsigned kHistorySize = 16;

+#endif

+

+#ifndef _SFX

+

+// it's used in CompressDialog also

+void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal)

+{

+  int curSel = 0;

+  for (unsigned i = 0; i < numItems; i++)

+  {

+    UString s = LangString(langIDs[i]);

+    s.RemoveChar(L'&');

+    int index = (int)combo.AddString(s);

+    combo.SetItemData(index, i);

+    if (values[i] == curVal)

+      curSel = i;

+  }

+  combo.SetCurSel(curSel);

+}

+

+// it's used in CompressDialog also

+bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2)

+{

+  if (b1.Def) return b1.Val;

+  if (b2.Def) return b2.Val;

+  return b1.Val;

+}

+

+void CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2)

+{

+  CheckButton(id, GetBoolsVal(b1, b2));

+}

+

+void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2)

+{

+  bool val = IsButtonCheckedBool(id);

+  bool oldVal = GetBoolsVal(b1, b2);

+  if (val != oldVal)

+    b1.Def = b2.Def = true;

+  b1.Val = b2.Val = val;

+}

+

+#endif

+

+bool CExtractDialog::OnInit()

+{

+  #ifdef LANG

+  {

+    UString s;

+    LangString_OnlyFromLangFile(IDD_EXTRACT, s);

+    if (s.IsEmpty())

+      GetText(s);

+    if (!ArcPath.IsEmpty())

+    {

+      s += L" : ";

+      s += ArcPath;

+    }

+    SetText(s);

+    // LangSetWindowText(*this, IDD_EXTRACT);

+    LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));

+  }

+  #endif

+  

+  #ifndef _SFX

+  _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD));

+  _passwordControl.SetText(Password);

+  _passwordControl.SetPasswordChar(TEXT('*'));

+  _pathName.Attach(GetItem(IDE_EXTRACT_NAME));

+  #endif

+

+  #ifdef NO_REGISTRY

+  

+  PathMode = NExtract::NPathMode::kFullPaths;

+  OverwriteMode = NExtract::NOverwriteMode::kAsk;

+  

+  #else

+  

+  _info.Load();

+

+  if (_info.PathMode == NExtract::NPathMode::kCurPaths)

+    _info.PathMode = NExtract::NPathMode::kFullPaths;

+

+  if (!PathMode_Force && _info.PathMode_Force)

+    PathMode = _info.PathMode;

+  if (!OverwriteMode_Force && _info.OverwriteMode_Force)

+    OverwriteMode = _info.OverwriteMode;

+

+  // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);

+  CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR,    NtSecurity, _info.NtSecurity);

+  CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP,    ElimDup,    _info.ElimDup);

+  

+  CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val);

+  UpdatePasswordControl();

+

+  #endif

+

+  _path.Attach(GetItem(IDC_EXTRACT_PATH));

+

+  UString pathPrefix = DirPath;

+

+  #ifndef _SFX

+  

+  if (_info.SplitDest.Val)

+  {

+    CheckButton(IDX_EXTRACT_NAME_ENABLE, true);

+    UString pathName;

+    SplitPathToParts_Smart(DirPath, pathPrefix, pathName);

+    if (pathPrefix.IsEmpty())

+      pathPrefix = pathName;

+    else

+      _pathName.SetText(pathName);

+  }

+  else

+    ShowItem_Bool(IDE_EXTRACT_NAME, false);

+

+  #endif

+

+  _path.SetText(pathPrefix);

+

+  #ifndef NO_REGISTRY

+  for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++)

+    _path.AddString(_info.Paths[i]);

+  #endif

+

+  /*

+  if (_info.Paths.Size() > 0)

+    _path.SetCurSel(0);

+  else

+    _path.SetCurSel(-1);

+  */

+

+  #ifndef _SFX

+

+  _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE));

+  _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE));

+

+  AddComboItems(_pathMode, kPathMode_IDs, ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode);

+  AddComboItems(_overwriteMode, kOverwriteMode_IDs, ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode);

+

+  #endif

+

+  HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));

+  SetIcon(ICON_BIG, icon);

+ 

+  // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES);

+  // filesWindow.Enable(_enableFilesButton);

+

+  NormalizePosition();

+

+  return CModalDialog::OnInit();

+}

+

+#ifndef _SFX

+void CExtractDialog::UpdatePasswordControl()

+{

+  _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*'));

+  UString password;

+  _passwordControl.GetText(password);

+  _passwordControl.SetText(password);

+}

+#endif

+

+bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch(buttonID)

+  {

+    case IDB_EXTRACT_SET_PATH:

+      OnButtonSetPath();

+      return true;

+    #ifndef _SFX

+    case IDX_EXTRACT_NAME_ENABLE:

+      ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE));

+      return true;

+    case IDX_PASSWORD_SHOW:

+    {

+      UpdatePasswordControl();

+      return true;

+    }

+    #endif

+  }

+  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);

+}

+

+void CExtractDialog::OnButtonSetPath()

+{

+  UString currentPath;

+  _path.GetText(currentPath);

+  UString title = LangString(IDS_EXTRACT_SET_FOLDER);

+  UString resultPath;

+  if (!MyBrowseForFolder(*this, title, currentPath, resultPath))

+    return;

+  #ifndef NO_REGISTRY

+  _path.SetCurSel(-1);

+  #endif

+  _path.SetText(resultPath);

+}

+

+void AddUniqueString(UStringVector &list, const UString &s)

+{

+  FOR_VECTOR (i, list)

+    if (s.IsEqualToNoCase(list[i]))

+      return;

+  list.Add(s);

+}

+

+void CExtractDialog::OnOK()

+{

+  #ifndef _SFX

+  int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()];

+  if (PathMode != NExtract::NPathMode::kCurPaths ||

+      pathMode2 != NExtract::NPathMode::kFullPaths)

+    PathMode = (NExtract::NPathMode::EEnum)pathMode2;

+

+  OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()];

+

+  // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode();

+

+  _passwordControl.GetText(Password);

+

+  #endif

+

+  #ifndef NO_REGISTRY

+

+  // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);

+  GetButton_Bools(IDX_EXTRACT_NT_SECUR,    NtSecurity, _info.NtSecurity);

+  GetButton_Bools(IDX_EXTRACT_ELIM_DUP,    ElimDup,    _info.ElimDup);

+

+  bool showPassword = IsShowPasswordChecked();

+  if (showPassword != _info.ShowPassword.Val)

+  {

+    _info.ShowPassword.Def = true;

+    _info.ShowPassword.Val = showPassword;

+  }

+

+  if (_info.PathMode != pathMode2)

+  {

+    _info.PathMode_Force = true;

+    _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2;

+    /*

+    // we allow kAbsPaths in registry.

+    if (_info.PathMode == NExtract::NPathMode::kAbsPaths)

+      _info.PathMode = NExtract::NPathMode::kFullPaths;

+    */

+  }

+

+  if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode)

+    _info.OverwriteMode_Force = true;

+  _info.OverwriteMode = OverwriteMode;

+

+

+  #else

+  

+  ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);

+

+  #endif

+  

+  UString s;

+  

+  #ifdef NO_REGISTRY

+  

+  _path.GetText(s);

+  

+  #else

+

+  int currentItem = _path.GetCurSel();

+  if (currentItem == CB_ERR)

+  {

+    _path.GetText(s);

+    if (_path.GetCount() >= kHistorySize)

+      currentItem = _path.GetCount() - 1;

+  }

+  else

+    _path.GetLBText(currentItem, s);

+  

+  #endif

+

+  s.Trim();

+  NName::NormalizeDirPathPrefix(s);

+  

+  #ifndef _SFX

+  

+  bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE);

+  if (splitDest)

+  {

+    UString pathName;

+    _pathName.GetText(pathName);

+    pathName.Trim();

+    s += pathName;

+    NName::NormalizeDirPathPrefix(s);

+  }

+  if (splitDest != _info.SplitDest.Val)

+  {

+    _info.SplitDest.Def = true;

+    _info.SplitDest.Val = splitDest;

+  }

+

+  #endif

+

+  DirPath = s;

+  

+  #ifndef NO_REGISTRY

+  _info.Paths.Clear();

+  #ifndef _SFX

+  AddUniqueString(_info.Paths, s);

+  #endif

+  for (int i = 0; i < _path.GetCount(); i++)

+    if (i != currentItem)

+    {

+      UString sTemp;

+      _path.GetLBText(i, sTemp);

+      sTemp.Trim();

+      AddUniqueString(_info.Paths, sTemp);

+    }

+  _info.Save();

+  #endif

+  

+  CModalDialog::OnOK();

+}

+

+#ifndef NO_REGISTRY

+static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm";

+void CExtractDialog::OnHelp()

+{

+  ShowHelpWindow(NULL, kHelpTopic);

+  CModalDialog::OnHelp();

+}

+#endif

diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h
new file mode 100644
index 0000000..308c786
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialog.h
@@ -0,0 +1,113 @@
+// ExtractDialog.h

+

+#ifndef __EXTRACT_DIALOG_H

+#define __EXTRACT_DIALOG_H

+

+#include "ExtractDialogRes.h"

+

+#include "../../../Windows/Control/ComboBox.h"

+#include "../../../Windows/Control/Edit.h"

+

+#include "../Common/ExtractMode.h"

+

+#include "../FileManager/DialogSize.h"

+

+#ifndef NO_REGISTRY

+#include "../Common/ZipRegistry.h"

+#endif

+

+namespace NExtractionDialog

+{

+  /*

+  namespace NFilesMode

+  {

+    enum EEnum

+    {

+      kSelected,

+      kAll,

+      kSpecified

+    };

+  }

+  */

+}

+

+class CExtractDialog: public NWindows::NControl::CModalDialog

+{

+  #ifdef NO_REGISTRY

+  NWindows::NControl::CDialogChildControl _path;

+  #else

+  NWindows::NControl::CComboBox _path;

+  #endif

+

+  #ifndef _SFX

+  NWindows::NControl::CEdit _pathName;

+  NWindows::NControl::CEdit _passwordControl;

+  NWindows::NControl::CComboBox _pathMode;

+  NWindows::NControl::CComboBox _overwriteMode;

+  #endif

+

+  #ifndef _SFX

+  // int GetFilesMode() const;

+  void UpdatePasswordControl();

+  #endif

+  

+  void OnButtonSetPath();

+

+  void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2);

+  void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2);

+  virtual bool OnInit();

+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  virtual void OnOK();

+  

+  #ifndef NO_REGISTRY

+

+  virtual void OnHelp();

+

+  NExtract::CInfo _info;

+  

+  #endif

+  

+  bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); }

+public:

+  // bool _enableSelectedFilesButton;

+  // bool _enableFilesButton;

+  // NExtractionDialog::NFilesMode::EEnum FilesMode;

+

+  UString DirPath;

+  UString ArcPath;

+

+  #ifndef _SFX

+  UString Password;

+  #endif

+  bool PathMode_Force;

+  bool OverwriteMode_Force;

+  NExtract::NPathMode::EEnum PathMode;

+  NExtract::NOverwriteMode::EEnum OverwriteMode;

+

+  #ifndef _SFX

+  // CBoolPair AltStreams;

+  CBoolPair NtSecurity;

+  #endif

+

+  CBoolPair ElimDup;

+

+  INT_PTR Create(HWND aWndParent = 0)

+  {

+    #ifdef _SFX

+    BIG_DIALOG_SIZE(240, 64);

+    #else

+    BIG_DIALOG_SIZE(300, 160);

+    #endif

+    return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent);

+  }

+

+  CExtractDialog():

+    PathMode_Force(false),

+    OverwriteMode_Force(false)

+  {

+    ElimDup.Val = true;

+  }

+

+};

+

+#endif

diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc
new file mode 100644
index 0000000..f5d6528
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialog.rc
@@ -0,0 +1,98 @@
+#include "ExtractDialogRes.h"

+#include "../../GuiCommon.rc"

+

+#define xc 336

+#define yc 168

+

+#undef g1xs

+#undef g2x

+#undef g2x2

+#undef g2xs

+#undef g2xs2

+

+#define g1xs 160

+

+#define gSpace 20

+#define g2x (m + g1xs + gSpace)

+#define g2x2 (g2x + m)

+#define g2xs (xc - g1xs - gSpace)

+#define g2xs2 (g2xs - m - m)

+

+#undef GROUP_Y_SIZE

+#ifdef UNDER_CE

+#define GROUP_Y_SIZE 8

+#else

+#define GROUP_Y_SIZE 56

+#endif

+

+IDD_EXTRACT  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Extract"

+BEGIN

+  LTEXT     "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8

+  COMBOBOX  IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT

+  PUSHBUTTON  "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP

+

+  CONTROL   "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10

+  EDITTEXT  IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL

+

+  LTEXT     "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8

+  COMBOBOX  IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO

+

+  CONTROL   "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX,

+            m, m + 84, g1xs, 10

+

+  LTEXT     "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8

+  COMBOBOX  IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO

+

+

+  GROUPBOX  "Password", IDG_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE

+  EDITTEXT  IDE_EXTRACT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL

+  CONTROL   "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10

+

+//  CONTROL   "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX,

+//            g2x, m + 104, g2xs, 10

+  CONTROL   "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX,

+            g2x, m + 104, g2xs, 10

+  

+  DEFPUSHBUTTON  "OK",     IDOK,     bx3, by, bxs, bys, WS_GROUP

+  PUSHBUTTON     "Cancel", IDCANCEL, bx2, by, bxs, bys

+  PUSHBUTTON     "Help",   IDHELP,   bx1, by, bxs, bys

+END

+

+

+#ifdef UNDER_CE

+

+#undef m

+#define m 4

+

+#undef xc

+#undef yc

+

+#define xc 152

+#define yc 128

+

+#undef g1xs

+

+#define g1xs 64

+

+IDD_EXTRACT_2  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT

+CAPTION "Extract"

+BEGIN

+  LTEXT     "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8

+  COMBOBOX  IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT

+  PUSHBUTTON  "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP

+

+  LTEXT     "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8

+  COMBOBOX  IDC_EXTRACT_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO

+

+  LTEXT     "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8

+  COMBOBOX  IDC_EXTRACT_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO

+

+  LTEXT     "Password", IDG_PASSWORD, m, m + 76, g1xs, 8

+  EDITTEXT  IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL

+  CONTROL   "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10

+  

+  OK_CANCEL

+END

+

+#endif

diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h
new file mode 100644
index 0000000..61737e4
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h
@@ -0,0 +1,24 @@
+#define IDD_EXTRACT     3400

+#define IDD_EXTRACT_2  13400

+

+#define IDC_EXTRACT_PATH             100

+#define IDB_EXTRACT_SET_PATH         101

+#define IDC_EXTRACT_PATH_MODE        102

+#define IDC_EXTRACT_OVERWRITE_MODE   103

+

+#define IDE_EXTRACT_PASSWORD         120

+

+#define IDE_EXTRACT_NAME             130

+#define IDX_EXTRACT_NAME_ENABLE      131

+

+

+#define IDT_EXTRACT_EXTRACT_TO      3401

+#define IDT_EXTRACT_PATH_MODE       3410

+#define IDT_EXTRACT_OVERWRITE_MODE  3420

+

+#define IDX_EXTRACT_ELIM_DUP        3430

+#define IDX_EXTRACT_NT_SECUR        3431

+// #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
new file mode 100644
index 0000000..ff78648
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -0,0 +1,270 @@
+// ExtractGUI.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+#include "../../../Common/StringConvert.h"

+

+#include "../../../Windows/FileDir.h"

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/FileName.h"

+#include "../../../Windows/Thread.h"

+

+#include "../FileManager/ExtractCallback.h"

+#include "../FileManager/FormatUtils.h"

+#include "../FileManager/LangUtils.h"

+#include "../FileManager/resourceGui.h"

+#include "../FileManager/OverwriteDialogRes.h"

+

+#include "../Common/ArchiveExtractCallback.h"

+#include "../Common/PropIDUtils.h"

+

+#include "../Explorer/MyMessages.h"

+

+#include "resource2.h"

+#include "ExtractRes.h"

+

+#include "ExtractDialog.h"

+#include "ExtractGUI.h"

+#include "HashGUI.h"

+

+#include "../FileManager/PropertyNameRes.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDir;

+

+static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";

+

+#ifndef _SFX

+

+static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)

+{

+  wchar_t sz[32];

+  s += LangString(resourceID);

+  if (addColon)

+    s += L':';

+  s += L' ';

+  ConvertUInt64ToString(value, sz);

+  s += sz;

+  s += L'\n';

+}

+

+static void AddSizePair(UString &s, UINT resourceID, UInt64 value)

+{

+  wchar_t sz[32];

+  s += LangString(resourceID);

+  s += L": ";

+  ConvertUInt64ToString(value, sz);

+  s += MyFormatNew(IDS_FILE_SIZE, sz);

+  // s += sz;

+  if (value >= (1 << 20))

+  {

+    ConvertUInt64ToString(value >> 20, sz);

+    s += L" (";

+    s += sz;

+    s += L" MB)";

+  }

+  s += L'\n';

+}

+

+#endif

+

+class CThreadExtracting: public CProgressThreadVirt

+{

+  HRESULT ProcessVirt();

+public:

+  CCodecs *codecs;

+  CExtractCallbackImp *ExtractCallbackSpec;

+  const CObjectVector<COpenType> *FormatIndices;

+  const CIntVector *ExcludedFormatIndices;

+

+  UStringVector *ArchivePaths;

+  UStringVector *ArchivePathsFull;

+  const NWildcard::CCensorNode *WildcardCensor;

+  const CExtractOptions *Options;

+  #ifndef _SFX

+  CHashBundle *HashBundle;

+  #endif

+  CMyComPtr<IExtractCallbackUI> ExtractCallback;

+  UString Title;

+};

+

+HRESULT CThreadExtracting::ProcessVirt()

+{

+  CDecompressStat Stat;

+  #ifndef _SFX

+  if (HashBundle)

+    HashBundle->Init();

+  #endif

+

+  HRESULT res = Extract(codecs,

+      *FormatIndices, *ExcludedFormatIndices,

+      *ArchivePaths, *ArchivePathsFull,

+      *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback,

+      #ifndef _SFX

+        HashBundle,

+      #endif

+      FinalMessage.ErrorMessage.Message, Stat);

+  #ifndef _SFX

+  if (res == S_OK && Options->TestMode && ExtractCallbackSpec->IsOK())

+  {

+    UString s;

+    

+    AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);

+    AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);

+

+    if (!HashBundle)

+    {

+      if (Stat.NumFolders != 0)

+        AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);

+      AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);

+      AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);

+      if (Stat.NumAltStreams != 0)

+      {

+        s += L'\n';

+        AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);

+        AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);

+      }

+    }

+    

+    if (HashBundle)

+    {

+      s += L'\n';

+      AddHashBundleRes(s, *HashBundle, UString());

+    }

+    

+    s += L'\n';

+    s += LangString(IDS_MESSAGE_NO_ERRORS);

+    

+    FinalMessage.OkMessage.Title = Title;

+    FinalMessage.OkMessage.Message = s;

+  }

+  #endif

+  return res;

+}

+

+HRESULT ExtractGUI(

+    CCodecs *codecs,

+    const CObjectVector<COpenType> &formatIndices,

+    const CIntVector &excludedFormatIndices,

+    UStringVector &archivePaths,

+    UStringVector &archivePathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    CExtractOptions &options,

+    #ifndef _SFX

+    CHashBundle *hb,

+    #endif

+    bool showDialog,

+    bool &messageWasDisplayed,

+    CExtractCallbackImp *extractCallback,

+    HWND hwndParent)

+{

+  messageWasDisplayed = false;

+

+  CThreadExtracting extracter;

+  extracter.codecs = codecs;

+  extracter.FormatIndices = &formatIndices;

+  extracter.ExcludedFormatIndices = &excludedFormatIndices;

+

+  if (!options.TestMode)

+  {

+    FString outputDir = options.OutputDir;

+    #ifndef UNDER_CE

+    if (outputDir.IsEmpty())

+      GetCurrentDir(outputDir);

+    #endif

+    if (showDialog)

+    {

+      CExtractDialog dialog;

+      FString outputDirFull;

+      if (!MyGetFullPathName(outputDir, outputDirFull))

+      {

+        ShowErrorMessage(kIncorrectOutDir);

+        messageWasDisplayed = true;

+        return E_FAIL;

+      }

+      NName::NormalizeDirPathPrefix(outputDirFull);

+

+      dialog.DirPath = fs2us(outputDirFull);

+

+      dialog.OverwriteMode = options.OverwriteMode;

+      dialog.OverwriteMode_Force = options.OverwriteMode_Force;

+      dialog.PathMode = options.PathMode;

+      dialog.PathMode_Force = options.PathMode_Force;

+      dialog.ElimDup = options.ElimDup;

+

+      if (archivePathsFull.Size() == 1)

+        dialog.ArcPath = archivePathsFull[0];

+

+      #ifndef _SFX

+      // dialog.AltStreams = options.NtOptions.AltStreams;

+      dialog.NtSecurity = options.NtOptions.NtSecurity;

+      if (extractCallback->PasswordIsDefined)

+        dialog.Password = extractCallback->Password;

+      #endif

+

+      if (dialog.Create(hwndParent) != IDOK)

+        return E_ABORT;

+

+      outputDir = us2fs(dialog.DirPath);

+

+      options.OverwriteMode = dialog.OverwriteMode;

+      options.PathMode = dialog.PathMode;

+      options.ElimDup = dialog.ElimDup;

+      

+      #ifndef _SFX

+      // options.NtOptions.AltStreams = dialog.AltStreams;

+      options.NtOptions.NtSecurity = dialog.NtSecurity;

+      extractCallback->Password = dialog.Password;

+      extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();

+      #endif

+    }

+    if (!MyGetFullPathName(outputDir, options.OutputDir))

+    {

+      ShowErrorMessage(kIncorrectOutDir);

+      messageWasDisplayed = true;

+      return E_FAIL;

+    }

+    NName::NormalizeDirPathPrefix(options.OutputDir);

+    

+    /*

+    if(!CreateComplexDirectory(options.OutputDir))

+    {

+      UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));

+      UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,

+      #ifdef LANG

+      0x02000603,

+      #endif

+      options.OutputDir);

+      MyMessageBox(s2 + UString(L'\n') + s);

+      return E_FAIL;

+    }

+    */

+  }

+  

+  UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING);

+

+  extracter.Title = title;

+  extracter.ExtractCallbackSpec = extractCallback;

+  extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;

+  extracter.ExtractCallback = extractCallback;

+  extracter.ExtractCallbackSpec->Init();

+

+  extracter.ProgressDialog.CompressingMode = false;

+

+  extracter.ArchivePaths = &archivePaths;

+  extracter.ArchivePathsFull = &archivePathsFull;

+  extracter.WildcardCensor = &wildcardCensor;

+  extracter.Options = &options;

+  #ifndef _SFX

+  extracter.HashBundle = hb;

+  #endif

+

+  extracter.ProgressDialog.IconID = IDI_ICON;

+

+  RINOK(extracter.Create(title, hwndParent));

+  messageWasDisplayed = extracter.ThreadFinishedOK &

+      extracter.ProgressDialog.MessagesDisplayed;

+  return extracter.Result;

+}

diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h
new file mode 100644
index 0000000..466e524
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractGUI.h
@@ -0,0 +1,38 @@
+// GUI/ExtractGUI.h

+

+#ifndef __EXTRACT_GUI_H

+#define __EXTRACT_GUI_H

+

+#include "../Common/Extract.h"

+

+#include "../FileManager/ExtractCallback.h"

+

+/*

+  RESULT can be S_OK, even if there are errors!!!

+  if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI().

+

+  RESULT = E_ABORT - user break.

+  RESULT != E_ABORT:

+  {

+   messageWasDisplayed = true  - message was displayed already.

+   messageWasDisplayed = false - there was some internal error, so you must show error message.

+  }

+*/

+

+HRESULT ExtractGUI(

+    CCodecs *codecs,

+    const CObjectVector<COpenType> &formatIndices,

+    const CIntVector &excludedFormatIndices,

+    UStringVector &archivePaths,

+    UStringVector &archivePathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    CExtractOptions &options,

+    #ifndef _SFX

+    CHashBundle *hb,

+    #endif

+    bool showDialog,

+    bool &messageWasDisplayed,

+    CExtractCallbackImp *extractCallback,

+    HWND hwndParent = NULL);

+

+#endif

diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h
new file mode 100644
index 0000000..407ad19
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractRes.h
@@ -0,0 +1,44 @@
+#define IDS_MEM_ERROR                   3000

+

+#define IDS_CANNOT_CREATE_FOLDER        3003

+#define IDS_UPDATE_NOT_SUPPORTED        3004

+#define IDS_CANT_OPEN_ARCHIVE           3005

+#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006

+#define IDS_UNSUPPORTED_ARCHIVE_TYPE    3007

+

+#define IDS_PROGRESS_EXTRACTING         3300

+

+#define IDS_EXTRACT_SET_FOLDER          3402

+

+#define IDS_EXTRACT_PATHS_FULL          3411

+#define IDS_EXTRACT_PATHS_NO            3412

+#define IDS_EXTRACT_PATHS_ABS           3413

+#define IDS_PATH_MODE_RELAT             3414

+

+#define IDS_EXTRACT_OVERWRITE_ASK             3421

+#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT  3422

+#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING   3423

+#define IDS_EXTRACT_OVERWRITE_RENAME          3424

+#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425

+

+#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD    3700

+#define IDS_EXTRACT_MESSAGE_DATA_ERROR            3701

+#define IDS_EXTRACT_MESSAGE_CRC_ERROR             3702

+#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_ENCRYPTED            3711

+

+#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD   3721

+#define IDS_EXTRACT_MSG_DATA_ERROR           3722

+#define IDS_EXTRACT_MSG_CRC_ERROR            3723

+#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA     3724

+#define IDS_EXTRACT_MSG_UEXPECTED_END        3725

+#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_OPEN_MSG_UNAVAILABLE_START       3763

+#define IDS_OPEN_MSG_UNCONFIRMED_START       3764

+#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE     3768

diff --git a/CPP/7zip/UI/GUI/HashGUI.h b/CPP/7zip/UI/GUI/HashGUI.h
new file mode 100644
index 0000000..4fb0666
--- /dev/null
+++ b/CPP/7zip/UI/GUI/HashGUI.h
@@ -0,0 +1,16 @@
+// HashGUI.h

+

+#ifndef __HASH_GUI_H

+#define __HASH_GUI_H

+

+#include "../Common/HashCalc.h"

+

+HRESULT HashCalcGUI(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const NWildcard::CCensor &censor,

+    const CHashOptions &options,

+    bool &messageWasDisplayed);

+

+void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName);

+

+#endif

diff --git a/CPP/7zip/UI/GUI/resource2.h b/CPP/7zip/UI/GUI/resource2.h
new file mode 100644
index 0000000..152e71f
--- /dev/null
+++ b/CPP/7zip/UI/GUI/resource2.h
@@ -0,0 +1,2 @@
+#define IDS_PROGRESS_COMPRESSING  3301

+#define IDS_ARCHIVES_COLON        3907

diff --git a/CPP/Build.mak b/CPP/Build.mak
old mode 100755
new mode 100644
index 81ac79d..70c9c48
--- a/CPP/Build.mak
+++ b/CPP/Build.mak
@@ -1,11 +1,10 @@
 LIBS = $(LIBS) oleaut32.lib ole32.lib

 

-!IFDEF CPU

-!IFNDEF NO_BUFFEROVERFLOWU

-LIBS = $(LIBS) bufferoverflowU.lib

-!ENDIF

+!IFNDEF MY_NO_UNICODE

+CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE

 !ENDIF

 

+# CFLAGS = $(CFLAGS) -FAsc -Fa$O/Asm/

 

 !IFNDEF O

 !IFDEF CPU

@@ -43,7 +42,7 @@
 COMPL_ASM = $(MY_ML) -c -Fo$O/ $**

 !ENDIF

 

-CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gy -GR-

+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR-

 

 !IFDEF MY_STATIC_LINK

 !IFNDEF MY_SINGLE_THREAD

@@ -54,9 +53,12 @@
 !ENDIF

 

 !IFDEF NEW_COMPILER

-CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope

+CFLAGS = $(CFLAGS) -GS- -Zc:forScope

+!IFNDEF UNDER_CE

+CFLAGS = $(CFLAGS) -MP2

+!ENDIF

 !ELSE

-CFLAGS = $(CFLAGS) -W3

+CFLAGS = $(CFLAGS)

 !ENDIF

 

 CFLAGS_O1 = $(CFLAGS) -O1

@@ -64,10 +66,21 @@
 

 LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF

 

+!IFNDEF UNDER_CE

+LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE

+!ENDIF

+

 !IFDEF DEF_FILE

 LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)

 !ENDIF

 

+MY_SUB_SYS_VER=6.0

+!IFDEF MY_CONSOLE

+# LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER)

+!ELSE

+# LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER)

+!ENDIF

+

 PROGPATH = $O\$(PROG)

 

 COMPL_O1   = $(CC) $(CFLAGS_O1) $**

@@ -75,15 +88,27 @@
 COMPL_PCH  = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $**

 COMPL      = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $**

 

+COMPLB    = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $<

+# COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $<

+COMPLB_O2 = $(CC) $(CFLAGS_O2) $<

+

+CCOMPL_PCH  = $(CC) $(CFLAGS_O2) -Yc"Precomp.h" -Fp$O/a.pch $**

+CCOMPL_USE  = $(CC) $(CFLAGS_O2) -Yu"Precomp.h" -Fp$O/a.pch $**

+CCOMPL      = $(CC) $(CFLAGS_O2) $**

+CCOMPLB     = $(CC) $(CFLAGS_O2) $<

+

+

 all: $(PROGPATH)

 

 clean:

-	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch

+	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O\*.asm

 

 $O:

 	if not exist "$O" mkdir "$O"

+$O/Asm:

+	if not exist "$O/Asm" mkdir "$O/Asm"

 

-$(PROGPATH): $O $(OBJS) $(DEF_FILE)

+$(PROGPATH): $O $O/Asm $(OBJS) $(DEF_FILE)

 	link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)

 

 !IFNDEF NO_DEFAULT_RES

diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h
old mode 100755
new mode 100644
diff --git a/CPP/Common/Buffer.h b/CPP/Common/Buffer.h
deleted file mode 100755
index defe943..0000000
--- a/CPP/Common/Buffer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Common/Buffer.h

-

-#ifndef __COMMON_BUFFER_H

-#define __COMMON_BUFFER_H

-

-#include "Defs.h"

-

-template <class T> class CBuffer

-{

-protected:

-  size_t _capacity;

-  T *_items;

-public:

-  void Free()

-  {

-    delete []_items;

-    _items = 0;

-    _capacity = 0;

-  }

-  CBuffer(): _capacity(0), _items(0) {};

-  CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }

-  CBuffer(size_t size): _items(0), _capacity(0) {  SetCapacity(size); }

-  virtual ~CBuffer() { delete []_items; }

-  operator T *() { return _items; };

-  operator const T *() const { return _items; };

-  size_t GetCapacity() const { return  _capacity; }

-  void SetCapacity(size_t newCapacity)

-  {

-    if (newCapacity == _capacity)

-      return;

-    T *newBuffer;

-    if (newCapacity > 0)

-    {

-      newBuffer = new T[newCapacity];

-      if (_capacity > 0)

-        memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T));

-    }

-    else

-      newBuffer = 0;

-    delete []_items;

-    _items = newBuffer;

-    _capacity = newCapacity;

-  }

-  CBuffer& operator=(const CBuffer &buffer)

-  {

-    Free();

-    if (buffer._capacity > 0)

-    {

-      SetCapacity(buffer._capacity);

-      memmove(_items, buffer._items, buffer._capacity * sizeof(T));

-    }

-    return *this;

-  }

-};

-

-template <class T>

-bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)

-{

-  if (b1.GetCapacity() != b2.GetCapacity())

-    return false;

-  for (size_t i = 0; i < b1.GetCapacity(); i++)

-    if (b1[i] != b2[i])

-      return false;

-  return true;

-}

-

-template <class T>

-bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)

-{

-  return !(b1 == b2);

-}

-

-typedef CBuffer<char> CCharBuffer;

-typedef CBuffer<wchar_t> CWCharBuffer;

-typedef CBuffer<unsigned char> CByteBuffer;

-

-#endif

diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp
old mode 100755
new mode 100644
diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp
old mode 100755
new mode 100644
index 0e5647f..d68a427
--- a/CPP/Common/C_FileIO.cpp
+++ b/CPP/Common/C_FileIO.cpp
@@ -1,9 +1,13 @@
-// Common/C_FileIO.h

+// Common/C_FileIO.cpp

 

 #include "C_FileIO.h"

 

 #include <fcntl.h>

+#ifdef _WIN32

+#include <io.h>

+#else

 #include <unistd.h>

+#endif

 

 namespace NC {

 namespace NFile {

diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h
old mode 100755
new mode 100644
index 3f8cbca..4c400b4
--- a/CPP/Common/C_FileIO.h
+++ b/CPP/Common/C_FileIO.h
@@ -6,9 +6,15 @@
 #include <stdio.h>

 #include <sys/types.h>

 

-#include "Types.h"

+#include "MyTypes.h"

 #include "MyWindows.h"

 

+#ifdef _WIN32

+#ifdef _MSC_VER

+typedef size_t ssize_t;

+#endif

+#endif

+

 namespace NC {

 namespace NFile {

 namespace NIO {

diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
old mode 100755
new mode 100644
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
old mode 100755
new mode 100644
index 028f4f8..01269c8
--- a/CPP/Common/CommandLineParser.cpp
+++ b/CPP/Common/CommandLineParser.cpp
@@ -4,6 +4,20 @@
 

 #include "CommandLineParser.h"

 

+static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a)

+{

+  for (;;)

+  {

+    char c = *a;

+    if (c == 0)

+      return true;

+    if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))

+      return false;

+    a++;

+    u++;

+  }

+}

+

 namespace NCommandLineParser {

 

 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)

@@ -11,13 +25,13 @@
   dest1.Empty();

   dest2.Empty();

   bool quoteMode = false;

-  int i;

-  for (i = 0; i < src.Length(); i++)

+  unsigned i;

+  for (i = 0; i < src.Len(); i++)

   {

     wchar_t c = src[i];

-    if (c == L' ' && !quoteMode)

+    if ((c == L' ' || c == L'\t') && !quoteMode)

     {

-      dest2 = src.Mid(i + 1);

+      dest2 = src.Ptr(i + 1);

       return i != 0;

     }

     if (c == L'\"')

@@ -45,21 +59,18 @@
 }

 

 

-static const wchar_t kSwitchID1 = '-';

-// static const wchar_t kSwitchID2 = '/';

+static const char *kStopSwitchParsing = "--";

 

-static const wchar_t kSwitchMinus = '-';

-static const wchar_t *kStopSwitchParsing = L"--";

-

-static bool IsItSwitchChar(wchar_t c)

+static bool inline IsItSwitchChar(wchar_t c)

 {

-  return (c == kSwitchID1 /*|| c == kSwitchID2 */);

+  return (c == '-');

 }

 

-CParser::CParser(int numSwitches):

-  _numSwitches(numSwitches)

+CParser::CParser(unsigned numSwitches):

+  _numSwitches(numSwitches),

+  _switches(0)

 {

-  _switches = new CSwitchResult[_numSwitches];

+  _switches = new CSwitchResult[numSwitches];

 }

 

 CParser::~CParser()

@@ -67,163 +78,121 @@
   delete []_switches;

 }

 

-void CParser::ParseStrings(const CSwitchForm *switchForms,

-  const UStringVector &commandStrings)

-{

-  int numCommandStrings = commandStrings.Size();

-  bool stopSwitch = false;

-  for (int i = 0; i < numCommandStrings; i++)

-  {

-    const UString &s = commandStrings[i];

-    if (stopSwitch)

-      NonSwitchStrings.Add(s);

-    else

-      if (s == kStopSwitchParsing)

-        stopSwitch = true;

-      else

-        if (!ParseString(s, switchForms))

-          NonSwitchStrings.Add(s);

-  }

-}

 

-// if string contains switch then function updates switch structures

-// out: (string is a switch)

+// if (s) contains switch then function updates switch structures

+// out: true, if (s) is a switch

 bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)

 {

-  int len = s.Length();

-  if (len == 0)

+  if (s.IsEmpty() || !IsItSwitchChar(s[0]))

     return false;

-  int pos = 0;

-  if (!IsItSwitchChar(s[pos]))

-    return false;

-  while (pos < len)

-  {

-    if (IsItSwitchChar(s[pos]))

-      pos++;

-    const int kNoLen = -1;

-    int matchedSwitchIndex = 0; // GCC Warning

-    int maxLen = kNoLen;

-    for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)

-    {

-      int switchLen = MyStringLen(switchForms[switchIndex].IDString);

-      if (switchLen <= maxLen || pos + switchLen > len)

-        continue;

 

-      UString temp = s + pos;

-      temp = temp.Left(switchLen);

-      if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)

-      // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)

-      {

-        matchedSwitchIndex = switchIndex;

-        maxLen = switchLen;

-      }

-    }

-    if (maxLen == kNoLen)

-      throw "maxLen == kNoLen";

-    CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];

-    const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];

-    if ((!switchForm.Multi) && matchedSwitch.ThereIs)

-      throw "switch must be single";

-    matchedSwitch.ThereIs = true;

-    pos += maxLen;

-    int tailSize = len - pos;

-    NSwitchType::EEnum type = switchForm.Type;

-    switch(type)

+  unsigned pos = 1;

+  unsigned switchIndex = 0;

+  int maxLen = -1;

+  

+  for (unsigned i = 0; i < _numSwitches; i++)

+  {

+    const char *key = switchForms[i].Key;

+    unsigned switchLen = MyStringLen(key);

+    if ((int)switchLen <= maxLen || pos + switchLen > s.Len())

+      continue;

+    if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key))

     {

-      case NSwitchType::kPostMinus:

-        {

-          if (tailSize == 0)

-            matchedSwitch.WithMinus = false;

-          else

-          {

-            matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);

-            if (matchedSwitch.WithMinus)

-              pos++;

-          }

-          break;

-        }

-      case NSwitchType::kPostChar:

-        {

-          if (tailSize < switchForm.MinLen)

-            throw "switch is not full";

-          UString set = switchForm.PostCharSet;

-          const int kEmptyCharValue = -1;

-          if (tailSize == 0)

-            matchedSwitch.PostCharIndex = kEmptyCharValue;

-          else

-          {

-            int index = set.Find(s[pos]);

-            if (index < 0)

-              matchedSwitch.PostCharIndex =  kEmptyCharValue;

-            else

-            {

-              matchedSwitch.PostCharIndex = index;

-              pos++;

-            }

-          }

-          break;

-        }

-      case NSwitchType::kLimitedPostString:

-      case NSwitchType::kUnLimitedPostString:

-        {

-          int minLen = switchForm.MinLen;

-          if (tailSize < minLen)

-            throw "switch is not full";

-          if (type == NSwitchType::kUnLimitedPostString)

-          {

-            matchedSwitch.PostStrings.Add(s.Mid(pos));

-            return true;

-          }

-          int maxLen = switchForm.MaxLen;

-          UString stringSwitch = s.Mid(pos, minLen);

-          pos += minLen;

-          for (int i = minLen; i < maxLen && pos < len; i++, pos++)

-          {

-            wchar_t c = s[pos];

-            if (IsItSwitchChar(c))

-              break;

-            stringSwitch += c;

-          }

-          matchedSwitch.PostStrings.Add(stringSwitch);

-          break;

-        }

-      case NSwitchType::kSimple:

-          break;

+      switchIndex = i;

+      maxLen = switchLen;

     }

   }

+

+  if (maxLen < 0)

+  {

+    ErrorMessage = "Unknown switch:";

+    return false;

+  }

+

+  pos += maxLen;

+  

+  CSwitchResult &sw = _switches[switchIndex];

+  const CSwitchForm &form = switchForms[switchIndex];

+  

+  if (!form.Multi && sw.ThereIs)

+  {

+    ErrorMessage = "Multiple instances for switch:";

+    return false;

+  }

+

+  sw.ThereIs = true;

+

+  int rem = s.Len() - pos;

+  if (rem < form.MinLen)

+  {

+    ErrorMessage = "Too short switch:";

+    return false;

+  }

+  

+  sw.WithMinus = false;

+  sw.PostCharIndex = -1;

+  

+  switch (form.Type)

+  {

+    case NSwitchType::kMinus:

+      if (rem != 0)

+      {

+        sw.WithMinus = (s[pos] == '-');

+        if (sw.WithMinus)

+          pos++;

+      }

+      break;

+      

+    case NSwitchType::kChar:

+      if (rem != 0)

+      {

+        wchar_t c = s[pos];

+        if (c <= 0x7F)

+        {

+          sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);

+          if (sw.PostCharIndex >= 0)

+            pos++;

+        }

+      }

+      break;

+      

+    case NSwitchType::kString:

+      sw.PostStrings.Add((const wchar_t *)s + pos);

+      return true;

+  }

+  if (pos != s.Len())

+  {

+    ErrorMessage = "Too long switch:";

+    return false;

+  }

   return true;

 }

 

-const CSwitchResult& CParser::operator[](size_t index) const

+bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings)

 {

-  return _switches[index];

-}

-

-/////////////////////////////////

-// Command parsing procedures

-

-int ParseCommand(int numCommandForms, const CCommandForm *commandForms,

-    const UString &commandString, UString &postString)

-{

-  for (int i = 0; i < numCommandForms; i++)

+  ErrorLine.Empty();

+  bool stopSwitch = false;

+  FOR_VECTOR (i, commandStrings)

   {

-    const UString id = commandForms[i].IDString;

-    if (commandForms[i].PostStringMode)

+    const UString &s = commandStrings[i];

+    if (!stopSwitch)

     {

-      if (commandString.Find(id) == 0)

+      if (s.IsEqualTo(kStopSwitchParsing))

       {

-        postString = commandString.Mid(id.Length());

-        return i;

+        stopSwitch = true;

+        continue;

+      }

+      if (!s.IsEmpty() && IsItSwitchChar(s[0]))

+      {

+        if (ParseString(s, switchForms))

+          continue;

+        ErrorLine = s;

+        return false;

       }

     }

-    else

-      if (commandString == id)

-      {

-        postString.Empty();

-        return i;

-      }

+    NonSwitchStrings.Add(s);

   }

-  return -1;

+  return true;

 }

-   

+

 }

diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h
old mode 100755
new mode 100644
index ec079e3..446619c
--- a/CPP/Common/CommandLineParser.h
+++ b/CPP/Common/CommandLineParser.h
@@ -10,63 +10,54 @@
 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);

 void SplitCommandLine(const UString &s, UStringVector &parts);

 

-namespace NSwitchType {

+namespace NSwitchType

+{

   enum EEnum

   {

     kSimple,

-    kPostMinus,

-    kLimitedPostString,

-    kUnLimitedPostString,

-    kPostChar

+    kMinus,

+    kString,

+    kChar

   };

 }

 

 struct CSwitchForm

 {

-  const wchar_t *IDString;

-  NSwitchType::EEnum Type;

+  const char *Key;

+  Byte Type;

   bool Multi;

-  int MinLen;

-  int MaxLen;

-  const wchar_t *PostCharSet;

+  Byte MinLen;

+  // int MaxLen;

+  const char *PostCharSet;

 };

 

 struct CSwitchResult

 {

   bool ThereIs;

   bool WithMinus;

-  UStringVector PostStrings;

   int PostCharIndex;

+  UStringVector PostStrings;

+  

   CSwitchResult(): ThereIs(false) {};

 };

   

 class CParser

 {

-  int _numSwitches;

+  unsigned _numSwitches;

   CSwitchResult *_switches;

+

   bool ParseString(const UString &s, const CSwitchForm *switchForms);

 public:

   UStringVector NonSwitchStrings;

-  CParser(int numSwitches);

+  AString ErrorMessage;

+  UString ErrorLine;

+  

+  CParser(unsigned numSwitches);

   ~CParser();

-  void ParseStrings(const CSwitchForm *switchForms,

-    const UStringVector &commandStrings);

-  const CSwitchResult& operator[](size_t index) const;

+  bool ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings);

+  const CSwitchResult& operator[](size_t index) const { return _switches[index]; }

 };

 

-/////////////////////////////////

-// Command parsing procedures

-

-struct CCommandForm

-{

-  const wchar_t *IDString;

-  bool PostStringMode;

-};

-

-// Returns: Index of form and postString; -1, if there is no match

-int ParseCommand(int numCommandForms, const CCommandForm *commandForms,

-    const UString &commandString, UString &postString);

-

 }

 

 #endif

diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h
new file mode 100644
index 0000000..1f99077
--- /dev/null
+++ b/CPP/Common/Common.h
@@ -0,0 +1,13 @@
+// Common.h

+

+#ifndef __COMMON_COMMON_H

+#define __COMMON_COMMON_H

+

+#include "../../C/Compiler.h"

+

+#include "MyWindows.h"

+#include "NewHandler.h"

+

+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[1]))

+

+#endif

diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
new file mode 100644
index 0000000..cfa1996
--- /dev/null
+++ b/CPP/Common/CrcReg.cpp
@@ -0,0 +1,111 @@
+// CrcReg.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/7zCrc.h"

+#include "../../C/CpuArch.h"

+

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

+

+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_C_END

+

+class CCrcHasher:

+  public IHasher,

+  public ICompressSetCoderProperties,

+  public CMyUnknownImp

+{

+  UInt32 _crc;

+  CRC_FUNC _updateFunc;

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

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

+  {

+    #ifndef MY_CPU_BE

+    _updateFunc = CrcUpdateT4;

+    #endif

+  }

+  else if (tSize == 8)

+  {

+    #ifdef MY_CPU_X86_OR_AMD64

+      _updateFunc = CrcUpdateT8;

+    #else

+      return false;

+    #endif

+  }

+  return true;

+}

+

+STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs,

+    const PROPVARIANT *coderProps, UInt32 numProps)

+{

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = coderProps[i];

+    if (propIDs[i] == NCoderPropID::kDefaultProp)

+    {

+      if (prop.vt != VT_UI4)

+        return E_INVALIDARG;

+      if (!SetFunctions(prop.ulVal))

+        return E_NOTIMPL;

+    }

+  }

+  return S_OK;

+}

+

+static IHasher *CreateHasher() { return new CCrcHasher(); }

+

+static CHasherInfo g_HasherInfo = { CreateHasher, 0x1, L"CRC32", 4 };

+

+REGISTER_HASHER(Crc32)

diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
old mode 100755
new mode 100644
diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
old mode 100755
new mode 100644
index 2bd80ac..92abf99
--- a/CPP/Common/DynamicBuffer.h
+++ b/CPP/Common/DynamicBuffer.h
@@ -3,48 +3,56 @@
 #ifndef __COMMON_DYNAMIC_BUFFER_H

 #define __COMMON_DYNAMIC_BUFFER_H

 

-#include "Buffer.h"

-

-template <class T> class CDynamicBuffer: public CBuffer<T>

+template <class T> class CDynamicBuffer

 {

-  void GrowLength(size_t size)

+  T *_items;

+  size_t _size;

+  size_t _pos;

+

+  CDynamicBuffer(const CDynamicBuffer &buffer);

+  void operator=(const CDynamicBuffer &buffer);

+

+  void Grow(size_t size)

   {

-    size_t delta;

-    if (this->_capacity > 64)

-      delta = this->_capacity / 4;

-    else if (this->_capacity > 8)

-      delta = 16;

-    else

-      delta = 4;

-    delta = MyMax(delta, size);

-    size_t newCap = this->_capacity + delta;

+    size_t delta = _size >= 64 ? _size : 64;

+    if (delta < size)

+      delta = size;

+    size_t newCap = _size + delta;

     if (newCap < delta)

-      newCap = this->_capacity + size;

-    SetCapacity(newCap);

-  }

-public:

-  CDynamicBuffer(): CBuffer<T>() {};

-  CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {};

-  CDynamicBuffer(size_t size): CBuffer<T>(size) {};

-  CDynamicBuffer& operator=(const CDynamicBuffer &buffer)

-  {

-    this->Free();

-    if (buffer._capacity > 0)

     {

-      SetCapacity(buffer._capacity);

-      memmove(this->_items, buffer._items, buffer._capacity * sizeof(T));

+      newCap = _size + size;

+      if (newCap < size)

+        throw 20120116;

     }

-    return *this;

+

+    T *newBuffer = new T[newCap];

+    memcpy(newBuffer, _items, _pos * sizeof(T));

+    delete []_items;

+    _items = newBuffer;

+    _size = newCap;

   }

-  void EnsureCapacity(size_t capacity)

+

+public:

+  CDynamicBuffer(): _items(0), _size(0), _pos(0) {}

+  // operator T *() { return _items; };

+  operator const T *() const { return _items; };

+  ~CDynamicBuffer() { delete []_items; }

+

+  T *GetCurPtrAndGrow(size_t addSize)

   {

-    if (this->_capacity < capacity)

-      GrowLength(capacity - this->_capacity);

+    size_t rem = _size - _pos;

+    if (rem < addSize)

+      Grow(addSize - rem);

+    T *res = _items + _pos;

+    _pos += addSize;

+    return res;

   }

+

+  const size_t GetPos() const { return _pos; }

+

+  // void Empty() { _pos = 0; }

 };

 

-typedef CDynamicBuffer<char> CCharDynamicBuffer;

-typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer;

 typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;

 

 #endif

diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
old mode 100755
new mode 100644
index 312e9f0..d035115
--- a/CPP/Common/IntToString.cpp
+++ b/CPP/Common/IntToString.cpp
@@ -4,74 +4,143 @@
 

 #include "IntToString.h"

 

-void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)

+#define CONVERT_INT_TO_STR(charType, tempSize) \

+  unsigned char temp[tempSize]; unsigned i = 0; \

+  while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \

+  *s++ = (charType)('0' + (unsigned)val); \

+  while (i != 0) { i--; *s++ = temp[i]; } \

+  *s = 0;

+

+void ConvertUInt32ToString(UInt32 val, char *s) throw()

 {

-  if (base < 2 || base > 36)

+  CONVERT_INT_TO_STR(char, 16);

+}

+

+void ConvertUInt64ToString(UInt64 val, char *s) throw()

+{

+  if (val <= (UInt32)0xFFFFFFFF)

   {

-    *s = '\0';

+    ConvertUInt32ToString((UInt32)val, s);

     return;

   }

-  char temp[72];

-  int pos = 0;

-  do

-  {

-    int delta = (int)(value % base);

-    temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10)));

-    value /= base;

-  }

-  while (value != 0);

-  do

-    *s++ = temp[--pos];

-  while (pos > 0);

-  *s = '\0';

+  CONVERT_INT_TO_STR(char, 24);

 }

 

-void ConvertUInt64ToString(UInt64 value, wchar_t *s)

+void ConvertUInt64ToOct(UInt64 val, char *s) throw()

 {

-  wchar_t temp[32];

-  int pos = 0;

+  UInt64 v = val;

+  unsigned i;

+  for (i = 1;; i++)

+  {

+    v >>= 3;

+    if (v == 0)

+      break;

+  }

+  s[i] = 0;

   do

   {

-    temp[pos++] = (wchar_t)(L'0' + (int)(value % 10));

-    value /= 10;

+    unsigned t = (unsigned)(val & 0x7);

+    val >>= 3;

+    s[--i] = (char)('0' + t);

   }

-  while (value != 0);

-  do

-    *s++ = temp[--pos];

-  while (pos > 0);

-  *s = L'\0';

+  while (i);

 }

 

-void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); }

-void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); }

-

-void ConvertInt64ToString(Int64 value, char *s)

+void ConvertUInt32ToHex(UInt32 val, char *s) throw()

 {

-  if (value < 0)

+  UInt32 v = val;

+  unsigned i;

+  for (i = 1;; i++)

+  {

+    v >>= 4;

+    if (v == 0)

+      break;

+  }

+  s[i] = 0;

+  do

+  {

+    unsigned t = (unsigned)((val & 0xF));

+    val >>= 4;

+    s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+  }

+  while (i);

+}

+

+void ConvertUInt64ToHex(UInt64 val, char *s) throw()

+{

+  UInt64 v = val;

+  unsigned i;

+  for (i = 1;; i++)

+  {

+    v >>= 4;

+    if (v == 0)

+      break;

+  }

+  s[i] = 0;

+  do

+  {

+    unsigned t = (unsigned)((val & 0xF));

+    val >>= 4;

+    s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+  }

+  while (i);

+}

+

+void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()

+{

+  s[8] = 0;

+  for (int i = 7; i >= 0; i--)

+  {

+    unsigned t = val & 0xF;

+    val >>= 4;

+    s[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));

+  }

+}

+

+/*

+void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s)

+{

+  s[8] = 0;

+  for (int i = 7; i >= 0; i--)

+  {

+    unsigned t = val & 0xF;

+    val >>= 4;

+    s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));

+  }

+}

+*/

+

+void ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()

+{

+  CONVERT_INT_TO_STR(wchar_t, 16);

+}

+

+void ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()

+{

+  if (val <= (UInt32)0xFFFFFFFF)

+  {

+    ConvertUInt32ToString((UInt32)val, s);

+    return;

+  }

+  CONVERT_INT_TO_STR(wchar_t, 24);

+}

+

+void ConvertInt64ToString(Int64 val, char *s) throw()

+{

+  if (val < 0)

   {

     *s++ = '-';

-    value = -value;

+    val = -val;

   }

-  ConvertUInt64ToString(value, s);

+  ConvertUInt64ToString(val, s);

 }

 

-void ConvertInt64ToString(Int64 value, wchar_t *s)

+void ConvertInt64ToString(Int64 val, wchar_t *s) throw()

 {

-  if (value < 0)

+  if (val < 0)

   {

     *s++ = L'-';

-    value = -value;

+    val = -val;

   }

-  ConvertUInt64ToString(value, s);

-}

-

-void ConvertUInt32ToHexWithZeros(UInt32 value, char *s)

-{

-  for (int i = 0; i < 8; i++)

-  {

-    int t = value & 0xF;

-    value >>= 4;

-    s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

-  }

-  s[8] = '\0';

+  ConvertUInt64ToString(val, s);

 }

diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
old mode 100755
new mode 100644
index c57fd6a..7750934
--- a/CPP/Common/IntToString.h
+++ b/CPP/Common/IntToString.h
@@ -3,17 +3,22 @@
 #ifndef __COMMON_INT_TO_STRING_H

 #define __COMMON_INT_TO_STRING_H

 

-#include <stddef.h>

-#include "Types.h"

+#include "MyTypes.h"

 

-void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10);

-void ConvertUInt64ToString(UInt64 value, wchar_t *s);

-void ConvertInt64ToString(Int64 value, char *s);

-void ConvertInt64ToString(Int64 value, wchar_t *s);

+void ConvertUInt32ToString(UInt32 value, char *s) throw();

+void ConvertUInt64ToString(UInt64 value, char *s) throw();

 

-void ConvertUInt32ToString(UInt32 value, char *s);

-void ConvertUInt32ToString(UInt32 value, wchar_t *s);

+void ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();

+void ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();

 

-void ConvertUInt32ToHexWithZeros(UInt32 value, char *s);

+void ConvertUInt64ToOct(UInt64 value, char *s) throw();

+

+void ConvertUInt32ToHex(UInt32 value, char *s) throw();

+void ConvertUInt64ToHex(UInt64 value, char *s) throw();

+void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();

+// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();

+

+void ConvertInt64ToString(Int64 value, char *s) throw();

+void ConvertInt64ToString(Int64 value, wchar_t *s) throw();

 

 #endif

diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
new file mode 100644
index 0000000..9850e19
--- /dev/null
+++ b/CPP/Common/Lang.h
@@ -0,0 +1,23 @@
+// Common/Lang.h

+

+#ifndef __COMMON_LANG_H

+#define __COMMON_LANG_H

+

+#include "MyString.h"

+

+class CLang

+{

+  wchar_t *_text;

+  CRecordVector<UInt32> _ids;

+  CRecordVector<UInt32> _offsets;

+

+  bool OpenFromString(const AString &s);

+public:

+  CLang(): _text(0) {}

+  ~CLang() { Clear(); };

+  bool Open(CFSTR fileName, const wchar_t *id);

+  void Clear() throw();

+  const wchar_t *Get(UInt32 id) const throw();

+};

+

+#endif

diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
old mode 100755
new mode 100644
index ff61b02..b0e80b1
--- a/CPP/Common/ListFileUtils.cpp
+++ b/CPP/Common/ListFileUtils.cpp
@@ -2,74 +2,116 @@
 

 #include "StdAfx.h"

 

-#include "MyWindows.h"

+#include "../../C/CpuArch.h"

+

 #include "../Windows/FileIO.h"

 

 #include "ListFileUtils.h"

+#include "MyBuffer.h"

 #include "StringConvert.h"

 #include "UTFConvert.h"

 

-static const char kQuoteChar     = '\"';

-static void RemoveQuote(UString &s)

+static const char kQuoteChar = '\"';

+

+static void AddName(UStringVector &strings, UString &s)

 {

-  if (s.Length() >= 2)

-    if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar)

-      s = s.Mid(1, s.Length() - 2);

+  s.Trim();

+  if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar)

+  {

+    s.DeleteBack();

+    s.Delete(0);

+  }

+  if (!s.IsEmpty())

+    strings.Add(s);

 }

 

-bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage)

+bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage)

 {

   NWindows::NFile::NIO::CInFile file;

   if (!file.Open(fileName))

     return false;

-  UInt64 length;

-  if (!file.GetLength(length))

+  UInt64 fileSize;

+  if (!file.GetLength(fileSize))

     return false;

-  if (length > ((UInt32)1 << 31))

+  if (fileSize >= ((UInt32)1 << 31) - 32)

     return false;

-  AString s;

-  char *p = s.GetBuffer((int)length + 1);

-  UInt32 processed;

-  if (!file.Read(p, (UInt32)length, processed))

-    return false;

-  p[(UInt32)length] = 0;

-  s.ReleaseBuffer();

-  file.Close();

-

   UString u;

-  #ifdef CP_UTF8

-  if (codePage == CP_UTF8)

+  if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE)

   {

-    if (!ConvertUTF8ToUnicode(s, u))

+    if ((fileSize & 1) != 0)

       return false;

+    CByteArr buf((size_t)fileSize);

+    UInt32 processed;

+    if (!file.Read(buf, (UInt32)fileSize, processed))

+      return false;

+    if (processed != fileSize)

+      return false;

+    file.Close();

+    unsigned num = (unsigned)fileSize / 2;

+    wchar_t *p = u.GetBuffer(num);

+    if (codePage == MY__CP_UTF16)

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

+      {

+        wchar_t c = GetUi16(buf + i * 2);

+        if (c == 0)

+          return false;

+        p[i] = c;

+      }

+    else

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

+      {

+        wchar_t c = (wchar_t)GetBe16(buf + i * 2);

+        if (c == 0)

+          return false;

+        p[i] = c;

+      }

+    u.ReleaseBuffer(num);

   }

   else

-  #endif

-    u = MultiByteToUnicodeString(s, codePage);

-  if (!u.IsEmpty())

   {

-    if (u[0] == 0xFEFF)

-      u.Delete(0);

-  }

-

-  UString t;

-  for (int i = 0; i < u.Length(); i++)

-  {

-    wchar_t c = u[i];

-    if (c == L'\n' || c == 0xD)

+    AString s;

+    char *p = s.GetBuffer((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();

+    if (s.Len() != processed)

+      return false;

+    

+    // #ifdef CP_UTF8

+    if (codePage == CP_UTF8)

     {

-      t.Trim();

-      RemoveQuote(t);

-      if (!t.IsEmpty())

-        resultStrings.Add(t);

-      t.Empty();

+      if (!ConvertUTF8ToUnicode(s, u))

+        return false;

     }

     else

-      t += c;

+    // #endif

+      MultiByteToUnicodeString2(u, s, codePage);

   }

-  t.Trim();

-  RemoveQuote(t);

-  if (!t.IsEmpty())

-    resultStrings.Add(t);

+

+  const wchar_t kGoodBOM = 0xFEFF;

+  const wchar_t kBadBOM  = 0xFFFE;

+  

+  UString s;

+  unsigned i = 0;

+  for (; i < u.Len() && u[i] == kGoodBOM; i++);

+  for (; i < u.Len(); i++)

+  {

+    wchar_t c = u[i];

+    if (c == kGoodBOM || c == kBadBOM)

+      return false;

+    if (c == L'\n' || c == 0xD)

+    {

+      AddName(strings, s);

+      s.Empty();

+    }

+    else

+      s += c;

+  }

+  AddName(strings, s);

   return true;

 }

diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h
old mode 100755
new mode 100644
index 64f2199..ec32d8e
--- a/CPP/Common/ListFileUtils.h
+++ b/CPP/Common/ListFileUtils.h
@@ -1,11 +1,14 @@
 // Common/ListFileUtils.h

 

-#ifndef __COMMON_LISTFILEUTILS_H

-#define __COMMON_LISTFILEUTILS_H

+#ifndef __COMMON_LIST_FILE_UTILS_H

+#define __COMMON_LIST_FILE_UTILS_H

 

 #include "MyString.h"

-#include "Types.h"

+#include "MyTypes.h"

 

-bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);

+#define MY__CP_UTF16   1200

+#define MY__CP_UTF16BE 1201

+

+bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);

 

 #endif

diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
new file mode 100644
index 0000000..dabdea6
--- /dev/null
+++ b/CPP/Common/MyBuffer.h
@@ -0,0 +1,237 @@
+// Common/MyBuffer.h

+

+#ifndef __COMMON_MY_BUFFER_H

+#define __COMMON_MY_BUFFER_H

+

+#include "Defs.h"

+

+template <class T> class CBuffer

+{

+  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()

+  {

+    if (_items)

+    {

+      delete []_items;

+      _items = 0;

+    }

+    _size = 0;

+  }

+  

+  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() { delete []_items; }

+

+  operator       T *()       { return _items; };

+  operator const T *() const { return _items; };

+  size_t Size() const { return _size; }

+

+  void Alloc(size_t size)

+  {

+    if (size != _size)

+    {

+      Free();

+      if (size != 0)

+      {

+        _items = new T[size];

+        _size = size;

+      }

+    }

+  }

+

+  void AllocAtLeast(size_t size)

+  {

+    if (size > _size)

+    {

+      Free();

+      _items = new T[size];

+      _size = size;

+    }

+  }

+

+  void CopyFrom(const T *data, size_t size)

+  {

+    Alloc(size);

+    memcpy(_items, data, size * sizeof(T));

+  }

+

+  void ChangeSize_KeepData(size_t newSize, size_t keepSize)

+  {

+    if (newSize == _size)

+      return;

+    T *newBuffer = NULL;

+    if (newSize > 0)

+    {

+      newBuffer = new T[newSize];

+      if (_size > 0)

+        memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T));

+    }

+    delete []_items;

+    _items = newBuffer;

+    _size = newSize;

+  }

+

+  CBuffer& operator=(const CBuffer &buffer)

+  {

+    Free();

+    CopyToEmpty(buffer);

+    return *this;

+  }

+};

+

+template <class T>

+bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)

+{

+  size_t size1 = b1.Size();

+  if (size1 != b2.Size())

+    return false;

+  return memcmp(b1, b2, size1 * sizeof(T)) == 0;

+}

+

+template <class T>

+bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)

+{

+  size_t size1 = b1.Size();

+  if (size1 == b2.Size())

+    return false;

+  return memcmp(b1, b2, size1 * sizeof(T)) != 0;

+}

+

+

+typedef CBuffer<char> CCharBuffer;

+typedef CBuffer<wchar_t> CWCharBuffer;

+typedef CBuffer<unsigned char> CByteBuffer;

+

+

+template <class T> class CObjArray

+{

+protected:

+  T *_items;

+private:

+  // we disable constructors

+  CObjArray(const CObjArray &buffer);

+  void operator=(const CObjArray &buffer);

+public:

+  void Free()

+  {

+    delete []_items;

+    _items = 0;

+  }

+  CObjArray(size_t size): _items(0) { if (size != 0) _items = new T[size]; }

+  CObjArray(): _items(0) {};

+  ~CObjArray() { delete []_items; }

+  

+  operator       T *()       { return _items; };

+  operator const T *() const { return _items; };

+  

+  void Alloc(size_t newSize)

+  {

+    delete []_items;

+    _items = 0;

+    _items = new T[newSize];

+  }

+};

+

+typedef CObjArray<unsigned char> CByteArr;

+typedef CObjArray<bool> CBoolArr;

+typedef CObjArray<int> CIntArr;

+

+// #define CRecArray CObjArray

+

+template <class T> class CObjArray2

+{

+// protected:

+  T *_items;

+  unsigned _size;

+

+  CObjArray2(const CObjArray2 &buffer);

+  void operator=(const CObjArray2 &buffer);

+public:

+  

+  void Free()

+  {

+    delete []_items;

+    _items = 0;

+    _size = 0;

+  }

+  CObjArray2(): _items(0), _size(0) {};

+  /*

+  CObjArray2(const CObjArray2 &buffer): _items(0), _size(0)

+  {

+    size_t newSize = buffer._size;

+    if (newSize > 0)

+    {

+      T *newBuffer = new T[newSize];;

+      _items = newBuffer;

+      _size = newSize;

+      const T *src = buffer;

+      for (size_t i = 0; i < newSize; i++)

+        newBuffer[i] = src[i];

+    }

+  }

+  */

+  /*

+  CObjArray2(size_t size): _items(0), _size(0)

+  {

+    if (size != 0)

+    {

+      _items = new T[size];

+      _size = size;

+    }

+  }

+  */

+

+  ~CObjArray2() { delete []_items; }

+  

+  operator       T *()       { return _items; };

+  operator const T *() const { return _items; };

+  

+  unsigned Size() const { return (unsigned)_size; }

+  bool IsEmpty() const { return _size == 0; }

+

+  // SetSize doesn't keep old items. It allocates new array if size is not equal

+  void SetSize(unsigned size)

+  {

+    if (size == _size)

+      return;

+    T *newBuffer = NULL;

+    if (size > 0)

+      newBuffer = new T[size];

+    delete []_items;

+    _items = newBuffer;

+    _size = size;

+  }

+

+  /*

+  CObjArray2& operator=(const CObjArray2 &buffer)

+  {

+    Free();

+    size_t newSize = buffer._size;

+    if (newSize > 0)

+    {

+      T *newBuffer = new T[newSize];;

+      _items = newBuffer;

+      _size = newSize;

+      const T *src = buffer;

+      for (size_t i = 0; i < newSize; i++)

+        newBuffer[i] = src[i];

+    }

+    return *this;

+  }

+  */

+};

+

+#endif

diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
old mode 100755
new mode 100644
index d04fa4c..614a083
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -1,9 +1,10 @@
 // MyCom.h

 

-#ifndef __MYCOM_H

-#define __MYCOM_H

+#ifndef __MY_COM_H

+#define __MY_COM_H

 

 #include "MyWindows.h"

+#include "NewHandler.h"

 

 #ifndef RINOK

 #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }

@@ -14,14 +15,9 @@
 {

   T* _p;

 public:

-  // typedef T _PtrClass;

-  CMyComPtr() { _p = NULL;}

-  CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }

-  CMyComPtr(const CMyComPtr<T>& lp)

-  {

-    if ((_p = lp._p) != NULL)

-      _p->AddRef();

-  }

+  CMyComPtr(): _p(NULL) {}

+  CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }

+  CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }

   ~CMyComPtr() { if (_p) _p->Release(); }

   void Release() { if (_p) { _p->Release(); _p = NULL; } }

   operator T*() const {  return (T*)_p;  }

@@ -30,7 +26,7 @@
   T* operator->() const { return _p; }

   T* operator=(T* p)

   {

-    if (p != 0)

+    if (p)

       p->AddRef();

     if (_p)

       _p->Release();

@@ -40,7 +36,6 @@
   T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }

   bool operator!() const { return (_p == NULL); }

   // bool operator==(T* pT) const {  return _p == pT; }

-  // Compare two objects for equivalence

   void Attach(T* p2)

   {

     Release();

@@ -70,7 +65,7 @@
   }

   */

   template <class Q>

-  HRESULT QueryInterface(REFGUID iid, Q** pp) const

+  HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()

   {

     return _p->QueryInterface(iid, (void**)pp);

   }

@@ -81,13 +76,14 @@
 inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)

 {

   *bstr = ::SysAllocString(src);

-  return (*bstr != 0) ? S_OK : E_OUTOFMEMORY;

+  return (*bstr != NULL) ? S_OK : E_OUTOFMEMORY;

 }

 

 class CMyComBSTR

 {

-public:

   BSTR m_str;

+public:

+  

   CMyComBSTR(): m_str(NULL) {}

   CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }

   // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }

@@ -119,7 +115,7 @@
     m_str = ::SysAllocString(src);

     return *this;

   }

-  unsigned int Length() const { return ::SysStringLen(m_str); }

+  // unsigned Len() const { return ::SysStringLen(m_str); }

   operator BSTR() const { return m_str; }

   BSTR* operator&() { return &m_str; }

   BSTR MyCopy() const

@@ -143,7 +139,7 @@
     ::SysFreeString(m_str);

     m_str = NULL;

   }

-  bool operator!() const {  return (m_str == NULL); }

+  bool operator!() const { return (m_str == NULL); }

 };

 

 //////////////////////////////////////////////////////////

@@ -156,22 +152,22 @@
 };

 

 #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \

-    (REFGUID iid, void **outObject) {

+(REFGUID iid, void **outObject) throw() { *outObject = NULL;

 

-#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \

-    { *outObject = (void *)(i *)this; AddRef(); return S_OK; }

+#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \

+    { *outObject = (void *)(i *)this; }

 

 #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \

-    { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }

+    { *outObject = (void *)(IUnknown *)(i *)this; }

 

 #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \

     MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \

     MY_QUERYINTERFACE_ENTRY(i)

 

-#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }

+#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; AddRef(); return S_OK; }

 

 #define MY_ADDREF_RELEASE \

-STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \

+STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \

 STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \

   return __m_RefCount; delete this; return 0; }

 

@@ -222,4 +218,25 @@
   MY_QUERYINTERFACE_ENTRY(i5) \

   )

 

+#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  MY_QUERYINTERFACE_ENTRY(i3) \

+  MY_QUERYINTERFACE_ENTRY(i4) \

+  MY_QUERYINTERFACE_ENTRY(i5) \

+  MY_QUERYINTERFACE_ENTRY(i6) \

+  )

+

+#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  MY_QUERYINTERFACE_ENTRY(i3) \

+  MY_QUERYINTERFACE_ENTRY(i4) \

+  MY_QUERYINTERFACE_ENTRY(i5) \

+  MY_QUERYINTERFACE_ENTRY(i6) \

+  MY_QUERYINTERFACE_ENTRY(i7) \

+  )

+

 #endif

diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h
old mode 100755
new mode 100644
diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
old mode 100755
new mode 100644
index da73d0a..e0359e2
--- a/CPP/Common/MyGuidDef.h
+++ b/CPP/Common/MyGuidDef.h
@@ -3,7 +3,7 @@
 #ifndef GUID_DEFINED

 #define GUID_DEFINED

 

-#include "Types.h"

+#include "MyTypes.h"

 

 typedef struct {

   UInt32 Data1;

diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h
old mode 100755
new mode 100644
index 98d1705..79fea19
--- a/CPP/Common/MyInitGuid.h
+++ b/CPP/Common/MyInitGuid.h
@@ -3,20 +3,43 @@
 #ifndef __COMMON_MY_INITGUID_H

 #define __COMMON_MY_INITGUID_H

 

+/*

+This file must be included only to one C++ file in project before

+declarations of COM interfaces with DEFINE_GUID macro.

+

+Each GUID must be initialized exactly once in project.

+There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h):

+  - if INITGUID is not defined:  DEFINE_GUID declares an external reference to the symbol name.

+  - if INITGUID is     defined:  DEFINE_GUID initializes the symbol name to the value of the GUID.

+

+Also we need IID_IUnknown that is initialized in some file for linking:

+  MSVC:  by default the linker uses some lib file that contains IID_IUnknown

+  MinGW: add -luuid switch for linker

+  WinCE: we define IID_IUnknown in this file

+  Other: we define IID_IUnknown in this file

+*/

+

 #ifdef _WIN32

+

 #ifdef UNDER_CE

 #include <basetyps.h>

 #endif

+

 #include <initguid.h>

+

 #ifdef UNDER_CE

 DEFINE_GUID(IID_IUnknown,

 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

 #endif

+

 #else

+

 #define INITGUID

 #include "MyGuidDef.h"

 DEFINE_GUID(IID_IUnknown,

 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

+

 #endif

 

+

 #endif

diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
old mode 100755
new mode 100644
index 1a25c9e..747a181
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -2,32 +2,104 @@
 

 #include "StdAfx.h"

 

-#ifndef _WIN32

+#ifdef _WIN32

+#include <windows.h>

+#include <wchar.h>

+#else

 #include <ctype.h>

 #endif

 

-#ifndef _UNICODE

+#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)

 #include "StringConvert.h"

 #endif

 

 #include "MyString.h"

 

+#define MY_STRING_NEW(_T_, _size_) new _T_[_size_]

+// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))

+

+/*

+inline const char* MyStringGetNextCharPointer(const char *p) throw()

+{

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  return CharNextA(p);

+  #else

+  return p + 1;

+  #endif

+}

+*/

+

+int FindCharPosInString(const char *s, char c) throw()

+{

+  for (const char *p = s;; p++)

+  {

+    if (*p == c)

+      return (int)(p - s);

+    if (*p == 0)

+      return -1;

+    // MyStringGetNextCharPointer(p);

+  }

+}

+

+int FindCharPosInString(const wchar_t *s, wchar_t c) throw()

+{

+  for (const wchar_t *p = s;; p++)

+  {

+    if (*p == c)

+      return (int)(p - s);

+    if (*p == 0)

+      return -1;

+  }

+}

+

+/*

+void MyStringUpper_Ascii(wchar_t *s)

+{

+  for (;;)

+  {

+    wchar_t c = *s;

+    if (c == 0)

+      return;

+    *s++ = MyCharUpper_Ascii(c);

+  }

+}

+*/

+

+void MyStringLower_Ascii(wchar_t *s) throw()

+{

+  for (;;)

+  {

+    wchar_t c = *s;

+    if (c == 0)

+      return;

+    *s++ = MyCharLower_Ascii(c);

+  }

+}

 

 #ifdef _WIN32

 

-#ifndef _UNICODE

+#ifdef _UNICODE

 

-wchar_t MyCharUpper(wchar_t c)

+// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }

+// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }

+// for WinCE - FString - char

+// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }

+

+#else

+

+// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }

+// char * MyStringUpper(char *s) { return CharUpperA(s); }

+// char * MyStringLower(char *s) { return CharLowerA(s); }

+

+wchar_t MyCharUpper_WIN(wchar_t c) throw()

 {

-  if (c == 0)

-    return 0;

-  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c);

+  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);

   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

-    return (wchar_t)(unsigned int)(UINT_PTR)res;

-  const int kBufferSize = 4;

-  char s[kBufferSize + 1];

-  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);

-  if (numChars == 0 || numChars > kBufferSize)

+    return (wchar_t)(unsigned)(UINT_PTR)res;

+  const int kBufSize = 4;

+  char s[kBufSize + 1];

+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);

+  if (numChars == 0 || numChars > kBufSize)

     return c;

   s[numChars] = 0;

   ::CharUpperA(s);

@@ -35,24 +107,25 @@
   return c;

 }

 

-wchar_t MyCharLower(wchar_t c)

+/*

+wchar_t MyCharLower_WIN(wchar_t c)

 {

-  if (c == 0)

-    return 0;

-  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c);

+  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);

   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

-    return (wchar_t)(unsigned int)(UINT_PTR)res;

-  const int kBufferSize = 4;

-  char s[kBufferSize + 1];

-  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);

-  if (numChars == 0 || numChars > kBufferSize)

+    return (wchar_t)(unsigned)(UINT_PTR)res;

+  const int kBufSize = 4;

+  char s[kBufSize + 1];

+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);

+  if (numChars == 0 || numChars > kBufSize)

     return c;

   s[numChars] = 0;

   ::CharLowerA(s);

   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);

   return c;

 }

+*/

 

+/*

 wchar_t * MyStringUpper(wchar_t *s)

 {

   if (s == 0)

@@ -62,9 +135,12 @@
     return res;

   AString a = UnicodeStringToMultiByte(s);

   a.MakeUpper();

-  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

+  MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

+  return s;

 }

+*/

 

+/*

 wchar_t * MyStringLower(wchar_t *s)

 {

   if (s == 0)

@@ -74,108 +150,130 @@
     return res;

   AString a = UnicodeStringToMultiByte(s);

   a.MakeLower();

-  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

-}

-

-#endif

-

-/*

-inline int ConvertCompareResult(int r) { return r - 2; }

-

-int MyStringCollate(const wchar_t *s1, const wchar_t *s2)

-{

-  int res = CompareStringW(

-        LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);

-  #ifdef _UNICODE

-  return ConvertCompareResult(res);

-  #else

-  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

-    return ConvertCompareResult(res);

-  return MyStringCollate(UnicodeStringToMultiByte(s1),

-        UnicodeStringToMultiByte(s2));

-  #endif

-}

-

-#ifndef UNDER_CE

-int MyStringCollate(const char *s1, const char *s2)

-{

-  return ConvertCompareResult(CompareStringA(

-    LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));

-}

-

-int MyStringCollateNoCase(const char *s1, const char *s2)

-{

-  return ConvertCompareResult(CompareStringA(

-    LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));

-}

-#endif

-

-int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)

-{

-  int res = CompareStringW(

-        LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);

-  #ifdef _UNICODE

-  return ConvertCompareResult(res);

-  #else

-  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

-    return ConvertCompareResult(res);

-  return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),

-      UnicodeStringToMultiByte(s2));

-  #endif

-}

-*/

-

-#else

-

-wchar_t MyCharUpper(wchar_t c)

-{

-  return toupper(c);

-}

-

-/*

-int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)

-{

-  for (;;)

-  {

-    wchar_t c1 = *s1++;

-    wchar_t c2 = *s2++;

-    wchar_t u1 = MyCharUpper(c1);

-    wchar_t u2 = MyCharUpper(c2);

-

-    if (u1 < u2) return -1;

-    if (u1 > u2) return 1;

-    if (u1 == 0) return 0;

-  }

+  MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

+  return s;

 }

 */

 

 #endif

 

-int MyStringCompare(const char *s1, const char *s2)

+#endif

+

+bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()

 {

   for (;;)

   {

-    unsigned char c1 = (unsigned char)*s1++;

-    unsigned char c2 = (unsigned char)*s2++;

-    if (c1 < c2) return -1;

-    if (c1 > c2) return 1;

-    if (c1 == 0) return 0;

+    unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;

+    unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;

   }

 }

 

-int MyStringCompare(const wchar_t *s1, const wchar_t *s2)

+bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()

 {

   for (;;)

   {

     wchar_t c1 = *s1++;

     wchar_t c2 = *s2++;

-    if (c1 < c2) return -1;

-    if (c1 > c2) return 1;

-    if (c1 == 0) return 0;

+    if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;

+    if (c1 == 0) return true;

   }

 }

 

-int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)

+// ---------- ASCII ----------

+

+bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()

+{

+  const char *s1 = _chars;

+  for (;;)

+  {

+    char c2 = *s++;

+    if (c2 == 0)

+      return true;

+    char c1 = *s1++;

+    if (MyCharLower_Ascii(c1) !=

+        MyCharLower_Ascii(c2))

+      return false;

+  }

+}

+

+bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()

+{

+  const wchar_t *s1 = _chars;

+  for (;;)

+  {

+    char c2 = *s++;

+    if (c2 == 0)

+      return true;

+    wchar_t c1 = *s1++;

+    if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))

+      return false;

+  }

+}

+

+bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()

+{

+  for (;;)

+  {

+    unsigned char c = *a;

+    if (c != *u)

+      return false;

+    if (c == 0)

+      return true;

+    a++;

+    u++;

+  }

+}

+

+bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()

+{

+  for (;;)

+  {

+    char c1 = *s1++;

+    char c2 = *s2++;

+    if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))

+      return false;

+    if (c1 == 0)

+      return true;

+  }

+}

+

+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()

+{

+  for (;;)

+  {

+    wchar_t c1 = *s1++;

+    wchar_t c2 = *s2++;

+    if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))

+      return false;

+    if (c1 == 0)

+      return true;

+  }

+}

+

+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()

+{

+  for (;;)

+  {

+    wchar_t c1 = *s1++;

+    char c2 = *s2++;

+    if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))

+      return false;

+    if (c1 == 0)

+      return true;

+  }

+}

+

+bool IsString1PrefixedByString2(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) return false;

+  }

+}

+

+// NTFS order: uses upper case

+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()

 {

   for (;;)

   {

@@ -192,9 +290,926 @@
   }

 }

 

+int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw()

+{

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

+  {

+    wchar_t c1 = *s1++;

+    wchar_t c2 = *s2++;

+    if (c1 != c2)

+    {

+      wchar_t u1 = MyCharUpper(c1);

+      wchar_t u2 = MyCharUpper(c2);

+      if (u1 < u2) return -1;

+      if (u1 > u2) return 1;

+    }

+    if (c1 == 0) return 0;

+  }

+  return 0;

+}

+

+

+// ---------- AString ----------

+

+void AString::InsertSpace(unsigned &index, unsigned size)

+{

+  Grow(size);

+  MoveItems(index + size, index);

+}

+

+void AString::ReAlloc(unsigned newLimit)

+{

+  if (newLimit < _len || newLimit >= 0x20000000) 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::SetStartLen(unsigned len)

+{

+  _chars = 0;

+  _chars = MY_STRING_NEW(char, len + 1);

+  _len = len;

+  _limit = len;

+}

+

+void AString::Grow_1()

+{

+  unsigned next = _len;

+  next += next / 2;

+  next += 16;

+  next &= ~(unsigned)15;

+  ReAlloc(next - 1);

+}

+

+void AString::Grow(unsigned n)

+{

+  unsigned freeSize = _limit - _len;

+  if (n <= freeSize)

+    return;

+  

+  unsigned next = _len + n;

+  next += next / 2;

+  next += 16;

+  next &= ~(unsigned)15;

+  ReAlloc(next - 1);

+}

+

+/*

+AString::AString(unsigned num, const char *s)

+{

+  unsigned len = MyStringLen(s);

+  if (num > len)

+    num = len;

+  SetStartLen(num);

+  memcpy(_chars, s, num);

+  _chars[num] = 0;

+}

+*/

+

+AString::AString(unsigned num, const AString &s)

+{

+  if (num > s._len)

+    num = s._len;

+  SetStartLen(num);

+  memcpy(_chars, s._chars, num);

+  _chars[num] = 0;

+}

+

+AString::AString(const AString &s, char c)

+{

+  SetStartLen(s.Len() + 1);

+  char *chars = _chars;

+  unsigned len = s.Len();

+  memcpy(chars, s, len);

+  chars[len] = c;

+  chars[len + 1] = 0;

+}

+

+AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)

+{

+  SetStartLen(num1 + num2);

+  char *chars = _chars;

+  memcpy(chars, s1, num1);

+  memcpy(chars + num1, s2, num2 + 1);

+}

+

+AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }

+AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }

+AString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }

+

+AString::AString()

+{

+  _chars = 0;

+  _chars = MY_STRING_NEW(char, 4);

+  _len = 0;

+  _limit = 4 - 1;

+  _chars[0] = 0;

+}

+

+AString::AString(char c)

+{

+  SetStartLen(1);

+  _chars[0] = c;

+  _chars[1] = 0;

+}

+

+AString::AString(const char *s)

+{

+  SetStartLen(MyStringLen(s));

+  MyStringCopy(_chars, s);

+}

+

+AString::AString(const AString &s)

+{

+  SetStartLen(s._len);

+  MyStringCopy(_chars, s._chars);

+}

+

+AString &AString::operator=(char c)

+{

+  if (1 > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, 1 + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = 1;

+  }

+  _len = 1;

+  _chars[0] = c;

+  _chars[1] = 0;

+  return *this;

+}

+

+AString &AString::operator=(const char *s)

+{

+  unsigned len = MyStringLen(s);

+  if (len > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  MyStringCopy(_chars, s);

+  return *this;

+}

+

+AString &AString::operator=(const AString &s)

+{

+  if (&s == this)

+    return *this;

+  unsigned len = s._len;

+  if (len > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  MyStringCopy(_chars, s._chars);

+  return *this;

+}

+

+AString &AString::operator+=(const char *s)

+{

+  unsigned len = MyStringLen(s);

+  Grow(len);

+  MyStringCopy(_chars + _len, s);

+  _len += len;

+  return *this;

+}

+

+AString &AString::operator+=(const AString &s)

+{

+  Grow(s._len);

+  MyStringCopy(_chars + _len, s._chars);

+  _len += s._len;

+  return *this;

+}

+

+void AString::SetFrom(const char *s, unsigned len) // no check

+{

+  if (len > _limit)

+  {

+    char *newBuf = MY_STRING_NEW(char, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  memcpy(_chars, s, len);

+  _chars[len] = 0;

+  _len = len;

+}

+

+int AString::Find(const AString &s, unsigned startIndex) const throw()

+{

+  if (s.IsEmpty())

+    return startIndex;

+  for (; startIndex < _len; startIndex++)

+  {

+    unsigned j;

+    for (j = 0; j < s._len && startIndex + j < _len; j++)

+      if (_chars[startIndex + j] != s._chars[j])

+        break;

+    if (j == s._len)

+      return (int)startIndex;

+  }

+  return -1;

+}

+

+int AString::ReverseFind(char c) const throw()

+{

+  if (_len == 0)

+    return -1;

+  const char *p = _chars + _len - 1;

+  for (;;)

+  {

+    if (*p == c)

+      return (int)(p - _chars);

+    if (p == _chars)

+      return -1;

+    p--; // p = GetPrevCharPointer(_chars, p);

+  }

+}

+

+void AString::TrimLeft() throw()

+{

+  const char *p = _chars;

+  for (;; p++)

+  {

+    char c = *p;

+    if (c != ' ' && c != '\n' && c != '\t')

+      break;

+  }

+  unsigned pos = (unsigned)(p - _chars);

+  if (pos != 0)

+  {

+    MoveItems(0, pos);

+    _len -= pos;

+  }

+}

+

+void AString::TrimRight() throw()

+{

+  const char *p = _chars;

+  int i;

+  for (i = _len - 1; i >= 0; i--)

+  {

+    char c = p[i];

+    if (c != ' ' && c != '\n' && c != '\t')

+      break;

+  }

+  i++;

+  if ((unsigned)i != _len)

+  {

+    _chars[i] = 0;

+    _len = i;

+  }

+}

+

+void AString::InsertAtFront(char c)

+{

+  if (_limit == _len)

+    Grow_1();

+  MoveItems(1, 0);

+  _chars[0] = c;

+  _len++;

+}

+

+/*

+void AString::Insert(unsigned index, char c)

+{

+  InsertSpace(index, 1);

+  _chars[index] = c;

+  _len++;

+}

+*/

+

+void AString::Insert(unsigned index, const char *s)

+{

+  unsigned num = MyStringLen(s);

+  if (num != 0)

+  {

+    InsertSpace(index, num);

+    memcpy(_chars + index, s, num);

+    _len += num;

+  }

+}

+

+void AString::Insert(unsigned index, const AString &s)

+{

+  unsigned num = s.Len();

+  if (num != 0)

+  {

+    InsertSpace(index, num);

+    memcpy(_chars + index, s, num);

+    _len += num;

+  }

+}

+

+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 c = src[(unsigned)pos];

+    if (c != ch)

+      *dest++ = c;

+  }

+  *dest = 0;

+  _len = (unsigned)(dest - _chars);

+}

+

+// !!!!!!!!!!!!!!! test it if newChar = '\0'

+void AString::Replace(char oldChar, char newChar) throw()

+{

+  if (oldChar == newChar)

+    return; // 0;

+  // unsigned number = 0;

+  int pos = 0;

+  while ((unsigned)pos < _len)

+  {

+    pos = Find(oldChar, pos);

+    if (pos < 0)

+      break;

+    _chars[pos] = newChar;

+    pos++;

+    // number++;

+  }

+  return; //  number;

+}

+

+void AString::Replace(const AString &oldString, const AString &newString)

+{

+  if (oldString.IsEmpty())

+    return; // 0;

+  if (oldString == newString)

+    return; // 0;

+  unsigned oldLen = oldString.Len();

+  unsigned newLen = newString.Len();

+  // unsigned number = 0;

+  int pos = 0;

+  while ((unsigned)pos < _len)

+  {

+    pos = Find(oldString, pos);

+    if (pos < 0)

+      break;

+    Delete(pos, oldLen);

+    Insert(pos, newString);

+    pos += newLen;

+    // number++;

+  }

+  // return number;

+}

+

+void AString::Delete(unsigned index) throw()

+{

+  MoveItems(index, index + 1);

+  _len--;

+}

+

+void AString::Delete(unsigned index, unsigned count) throw()

+{

+  if (index + count > _len)

+    count = _len - index;

+  if (count > 0)

+  {

+    MoveItems(index, index + count);

+    _len -= count;

+  }

+}

+

+void AString::DeleteFrontal(unsigned num) throw()

+{

+  if (num != 0)

+  {

+    MoveItems(0, num);

+    _len -= num;

+  }

+}

+

+/*

+AString operator+(const AString &s1, const AString &s2)

+{

+  AString result(s1);

+  result += s2;

+  return result;

+}

+

+AString operator+(const AString &s, const char *chars)

+{

+  AString result(s);

+  result += chars;

+  return result;

+}

+

+AString operator+(const char *chars, const AString &s)

+{

+  AString result(chars);

+  result += s;

+  return result;

+}

+

+AString operator+(const AString &s, char c)

+{

+  AString result(s);

+  result += c;

+  return result;

+}

+*/

+

+/*

+AString operator+(char c, const AString &s)

+{

+  AString result(c);

+  result += s;

+  return result;

+}

+*/

+

+

+

+

+// ---------- UString ----------

+

+void UString::InsertSpace(unsigned index, unsigned size)

+{

+  Grow(size);

+  MoveItems(index + size, index);

+}

+

+void UString::ReAlloc(unsigned newLimit)

+{

+  if (newLimit < _len || newLimit >= 0x20000000) 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::SetStartLen(unsigned len)

+{

+  _chars = 0;

+  _chars = MY_STRING_NEW(wchar_t, len + 1);

+  _len = len;

+  _limit = len;

+}

+

+void UString::Grow_1()

+{

+  unsigned next = _len;

+  next += next / 2;

+  next += 16;

+  next &= ~(unsigned)15;

+  ReAlloc(next - 1);

+}

+

+void UString::Grow(unsigned n)

+{

+  unsigned freeSize = _limit - _len;

+  if (n <= freeSize)

+    return;

+  

+  unsigned next = _len + n;

+  next += next / 2;

+  next += 16;

+  next &= ~(unsigned)15;

+  ReAlloc(next - 1);

+}

+

+

+UString::UString(unsigned num, const wchar_t *s)

+{

+  unsigned len = MyStringLen(s);

+  if (num > len)

+    num = len;

+  SetStartLen(num);

+  wmemcpy(_chars, s, num);

+  _chars[num] = 0;

+}

+

+

+UString::UString(unsigned num, const UString &s)

+{

+  if (num > s._len)

+    num = s._len;

+  SetStartLen(num);

+  wmemcpy(_chars, s._chars, num);

+  _chars[num] = 0;

+}

+

+UString::UString(const UString &s, wchar_t c)

+{

+  SetStartLen(s.Len() + 1);

+  wchar_t *chars = _chars;

+  unsigned len = s.Len();

+  wmemcpy(chars, s, len);

+  chars[len] = c;

+  chars[len + 1] = 0;

+}

+

+UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)

+{

+  SetStartLen(num1 + num2);

+  wchar_t *chars = _chars;

+  wmemcpy(chars, s1, num1);

+  wmemcpy(chars + num1, s2, num2 + 1);

+}

+

+UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }

+UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }

+UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }

+

+UString::UString()

+{

+  _chars = 0;

+  _chars = MY_STRING_NEW(wchar_t, 4);

+  _len = 0;

+  _limit = 4 - 1;

+  _chars[0] = 0;

+}

+

+UString::UString(wchar_t c)

+{

+  SetStartLen(1);

+  _chars[0] = c;

+  _chars[1] = 0;

+}

+

+UString::UString(const wchar_t *s)

+{

+  SetStartLen(MyStringLen(s));

+  MyStringCopy(_chars, s);

+}

+

+UString::UString(const UString &s)

+{

+  SetStartLen(s._len);

+  MyStringCopy(_chars, s._chars);

+}

+

+UString &UString::operator=(wchar_t c)

+{

+  if (1 > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = 1;

+  }

+  _len = 1;

+  _chars[0] = c;

+  _chars[1] = 0;

+  return *this;

+}

+

+UString &UString::operator=(const wchar_t *s)

+{

+  unsigned len = MyStringLen(s);

+  if (len > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  MyStringCopy(_chars, s);

+  return *this;

+}

+

+UString &UString::operator=(const UString &s)

+{

+  if (&s == this)

+    return *this;

+  unsigned len = s._len;

+  if (len > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  _len = len;

+  MyStringCopy(_chars, s._chars);

+  return *this;

+}

+

+UString &UString::operator+=(const wchar_t *s)

+{

+  unsigned len = MyStringLen(s);

+  Grow(len);

+  MyStringCopy(_chars + _len, s);

+  _len += len;

+  return *this;

+}

+

+UString &UString::operator+=(const UString &s)

+{

+  Grow(s._len);

+  MyStringCopy(_chars + _len, s._chars);

+  _len += s._len;

+  return *this;

+}

+

+void UString::SetFrom(const wchar_t *s, unsigned len) // no check

+{

+  if (len > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  wmemcpy(_chars, s, len);

+  _chars[len] = 0;

+  _len = len;

+}

+

+void UString::SetFromAscii(const char *s)

+{

+  unsigned len = MyStringLen(s);

+  if (len > _limit)

+  {

+    wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);

+    MY_STRING_DELETE(_chars);

+    _chars = newBuf;

+    _limit = len;

+  }

+  wchar_t *chars = _chars;

+  for (unsigned i = 0; i < len; i++)

+    chars[i] = s[i];

+  chars[len] = 0;

+  _len = len;

+}

+

+void UString::AddAsciiStr(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[len] = 0;

+  _len += len;

+}

+

+

+

+int UString::Find(const UString &s, unsigned startIndex) const throw()

+{

+  if (s.IsEmpty())

+    return startIndex;

+  for (; startIndex < _len; startIndex++)

+  {

+    unsigned j;

+    for (j = 0; j < s._len && startIndex + j < _len; j++)

+      if (_chars[startIndex + j] != s._chars[j])

+        break;

+    if (j == s._len)

+      return (int)startIndex;

+  }

+  return -1;

+}

+

+int UString::ReverseFind(wchar_t c) const throw()

+{

+  if (_len == 0)

+    return -1;

+  const wchar_t *p = _chars + _len - 1;

+  for (;;)

+  {

+    if (*p == c)

+      return (int)(p - _chars);

+    if (p == _chars)

+      return -1;

+    p--;

+  }

+}

+

+void UString::TrimLeft() throw()

+{

+  const wchar_t *p = _chars;

+  for (;; p++)

+  {

+    wchar_t c = *p;

+    if (c != ' ' && c != '\n' && c != '\t')

+      break;

+  }

+  unsigned pos = (unsigned)(p - _chars);

+  if (pos != 0)

+  {

+    MoveItems(0, pos);

+    _len -= pos;

+  }

+}

+

+void UString::TrimRight() throw()

+{

+  const wchar_t *p = _chars;

+  int i;

+  for (i = _len - 1; i >= 0; i--)

+  {

+    wchar_t c = p[i];

+    if (c != ' ' && c != '\n' && c != '\t')

+      break;

+  }

+  i++;

+  if ((unsigned)i != _len)

+  {

+    _chars[i] = 0;

+    _len = i;

+  }

+}

+

+void UString::InsertAtFront(wchar_t c)

+{

+  if (_limit == _len)

+    Grow_1();

+  MoveItems(1, 0);

+  _chars[0] = c;

+  _len++;

+}

+

+/*

+void UString::Insert(unsigned index, wchar_t c)

+{

+  InsertSpace(index, 1);

+  _chars[index] = c;

+  _len++;

+}

+*/

+

+void UString::Insert(unsigned index, const wchar_t *s)

+{

+  unsigned num = MyStringLen(s);

+  if (num != 0)

+  {

+    InsertSpace(index, num);

+    wmemcpy(_chars + index, s, num);

+    _len += num;

+  }

+}

+

+void UString::Insert(unsigned index, const UString &s)

+{

+  unsigned num = s.Len();

+  if (num != 0)

+  {

+    InsertSpace(index, num);

+    wmemcpy(_chars + index, s, num);

+    _len += num;

+  }

+}

+

+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 c = src[(unsigned)pos];

+    if (c != ch)

+      *dest++ = c;

+  }

+  *dest = 0;

+  _len = (unsigned)(dest - _chars);

+}

+

+// !!!!!!!!!!!!!!! test it if newChar = '\0'

+void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()

+{

+  if (oldChar == newChar)

+    return; // 0;

+  // unsigned number = 0;

+  int pos = 0;

+  while ((unsigned)pos < _len)

+  {

+    pos = Find(oldChar, pos);

+    if (pos < 0)

+      break;

+    _chars[pos] = newChar;

+    pos++;

+    // number++;

+  }

+  return; //  number;

+}

+

+void UString::Replace(const UString &oldString, const UString &newString)

+{

+  if (oldString.IsEmpty())

+    return; // 0;

+  if (oldString == newString)

+    return; // 0;

+  unsigned oldLen = oldString.Len();

+  unsigned newLen = newString.Len();

+  // unsigned number = 0;

+  int pos = 0;

+  while ((unsigned)pos < _len)

+  {

+    pos = Find(oldString, pos);

+    if (pos < 0)

+      break;

+    Delete(pos, oldLen);

+    Insert(pos, newString);

+    pos += newLen;

+    // number++;

+  }

+  // return number;

+}

+

+void UString::Delete(unsigned index) throw()

+{

+  MoveItems(index, index + 1);

+  _len--;

+}

+

+void UString::Delete(unsigned index, unsigned count) throw()

+{

+  if (index + count > _len)

+    count = _len - index;

+  if (count > 0)

+  {

+    MoveItems(index, index + count);

+    _len -= count;

+  }

+}

+

+void UString::DeleteFrontal(unsigned num) throw()

+{

+  if (num != 0)

+  {

+    MoveItems(0, num);

+    _len -= num;

+  }

+}

+

+

+// ----------------------------------------

+

 /*

 int MyStringCompareNoCase(const char *s1, const char *s2)

 {

   return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));

 }

 */

+

+static inline UINT GetCurrentCodePage()

+{

+  #if defined(UNDER_CE) || !defined(_WIN32)

+  return CP_ACP;

+  #else

+  return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;

+  #endif

+}

+

+#ifdef USE_UNICODE_FSTRING

+

+#ifndef _UNICODE

+

+AString fs2fas(CFSTR s)

+{

+  return UnicodeStringToMultiByte(s, GetCurrentCodePage());

+}

+

+FString fas2fs(const AString &s)

+{

+  return MultiByteToUnicodeString(s, GetCurrentCodePage());

+}

+

+#endif

+

+#else

+

+UString fs2us(const FString &s)

+{

+  return MultiByteToUnicodeString((AString)s, GetCurrentCodePage());

+}

+

+FString us2fs(const wchar_t *s)

+{

+  return UnicodeStringToMultiByte(s, GetCurrentCodePage());

+}

+

+#endif

diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
old mode 100755
new mode 100644
index ede2573..018acce
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -5,611 +5,468 @@
 

 #include <string.h>

 

+#ifndef _WIN32

+#include <wctype.h>

+#include <wchar.h>

+#endif

+

+#include "MyTypes.h"

 #include "MyVector.h"

 

-template <class T>

-inline int MyStringLen(const T *s)

+inline unsigned MyStringLen(const char *s)

 {

-  int i;

-  for (i = 0; s[i] != '\0'; i++);

+  unsigned i;

+  for (i = 0; s[i] != 0; i++);

   return i;

 }

 

-template <class T>

-inline T * MyStringCopy(T *dest, const T *src)

+inline void MyStringCopy(char *dest, const char *src)

 {

-  T *destStart = dest;

   while ((*dest++ = *src++) != 0);

-  return destStart;

 }

 

-inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)

-  { return (p + 1); }

-inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)

-  { return (p + 1); }

-inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)

-  { return (p - 1); }

-inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)

-  { return (p - 1); }

+inline char *MyStpCpy(char *dest, const char *src)

+{

+  for (;;)

+  {

+    char c = *src;

+    *dest = c;

+    if (c == 0)

+      return dest;

+    src++;

+    dest++;

+  }

+}

+

+inline unsigned MyStringLen(const wchar_t *s)

+{

+  unsigned i;

+  for (i = 0; s[i] != 0; i++);

+  return i;

+}

+

+inline void MyStringCopy(wchar_t *dest, const wchar_t *src)

+{

+  while ((*dest++ = *src++) != 0);

+}

+

+int FindCharPosInString(const char *s, char c) throw();

+int FindCharPosInString(const wchar_t *s, wchar_t c) throw();

 

 #ifdef _WIN32

+  #ifndef _UNICODE

+    #define STRING_UNICODE_THROW

+  #endif

+#endif

 

-inline const char* MyStringGetNextCharPointer(const char *p)

+#ifndef STRING_UNICODE_THROW

+  #define STRING_UNICODE_THROW throw()

+#endif

+

+/*

+inline char MyCharUpper_Ascii(char c)

 {

-  #ifdef UNDER_CE

-  return p + 1;

+  if (c >= 'a' && c <= 'z')

+    return (char)(c - 0x20);

+  return c;

+}

+inline wchar_t MyCharUpper_Ascii(wchar_t c)

+{

+  if (c >= 'a' && c <= 'z')

+    return (wchar_t)(c - 0x20);

+  return c;

+}

+*/

+

+inline char MyCharLower_Ascii(char c)

+{

+  if (c >= 'A' && c <= 'Z')

+    return (char)(c + 0x20);

+  return c;

+}

+

+inline wchar_t MyCharLower_Ascii(wchar_t c)

+{

+  if (c >= 'A' && c <= 'Z')

+    return (wchar_t)(c + 0x20);

+  return c;

+}

+

+wchar_t MyCharUpper_WIN(wchar_t c) throw();

+

+inline wchar_t MyCharUpper(wchar_t c) throw()

+{

+  if (c < 'a') return c;

+  if (c <= 'z') return (wchar_t)(c - 0x20);

+  if (c <= 0x7F) return c;

+  #ifdef _WIN32

+    #ifdef _UNICODE

+      return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);

+    #else

+      return (wchar_t)MyCharUpper_WIN(c);

+    #endif

   #else

-  return CharNextA(p);

+    return (wchar_t)towupper(c);

   #endif

 }

 

-inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)

-  { return CharPrevA(base, p); }

-

-inline char MyCharUpper(char c)

-  { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }

-#ifdef _UNICODE

-inline wchar_t MyCharUpper(wchar_t c)

-  { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }

-#else

-wchar_t MyCharUpper(wchar_t c);

-#endif

-

-#ifdef _UNICODE

-inline wchar_t MyCharLower(wchar_t c)

-  { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }

-#else

-wchar_t MyCharLower(wchar_t c);

-#endif

-

-inline char MyCharLower(char c)

-#ifdef UNDER_CE

-  { return (char)MyCharLower((wchar_t)c); }

-#else

-  { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }

-#endif

-

-inline char * MyStringUpper(char *s) { return CharUpperA(s); }

-#ifdef _UNICODE

-inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }

-#else

-wchar_t * MyStringUpper(wchar_t *s);

-#endif

-

-inline char * MyStringLower(char *s) { return CharLowerA(s); }

-#ifdef _UNICODE

-inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }

-#else

-wchar_t * MyStringLower(wchar_t *s);

-#endif

-

-#else // Standard-C

-wchar_t MyCharUpper(wchar_t c);

-#endif

-

-//////////////////////////////////////

-// Compare

-

 /*

-#ifndef UNDER_CE

-int MyStringCollate(const char *s1, const char *s2);

-int MyStringCollateNoCase(const char *s1, const char *s2);

-#endif

-int MyStringCollate(const wchar_t *s1, const wchar_t *s2);

-int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);

+wchar_t MyCharLower_WIN(wchar_t c) throw();

+

+inline wchar_t MyCharLower(wchar_t c) throw()

+{

+  if (c < 'A') return c;

+  if (c <= 'Z') return (wchar_t)(c + 0x20);

+  if (c <= 0x7F) return c;

+  #ifdef _WIN32

+    #ifdef _UNICODE

+      return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);

+    #else

+      return (wchar_t)MyCharLower_WIN(c);

+    #endif

+  #else

+    return (wchar_t)tolower(c);

+  #endif

+}

 */

 

-int MyStringCompare(const char *s1, const char  *s2);

-int MyStringCompare(const wchar_t *s1, const wchar_t *s2);

+// char *MyStringUpper(char *s) throw();

+// char *MyStringLower(char *s) throw();

 

-// int MyStringCompareNoCase(const char *s1, const char  *s2);

-int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);

+// void MyStringUpper_Ascii(wchar_t *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;

 

-template <class T>

-class CStringBase

+bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();

+

+bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();

+bool IsString1PrefixedByString2(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();

+

+// ---------- ASCII ----------

+// char values in ASCII strings must be less then 128

+bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();

+bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();

+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();

+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();

+

+#define MY_STRING_DELETE(_p_) delete []_p_;

+// #define MY_STRING_DELETE(_p_) my_delete(_p_);

+

+class AString

 {

-  void TrimLeftWithCharSet(const CStringBase &charSet)

-  {

-    const T *p = _chars;

-    while (charSet.Find(*p) >= 0 && (*p != 0))

-      p = GetNextCharPointer(p);

-    Delete(0, (int)(p - _chars));

-  }

-  void TrimRightWithCharSet(const CStringBase &charSet)

-  {

-    const T *p = _chars;

-    const T *pLast = NULL;

-    while (*p != 0)

-    {

-      if (charSet.Find(*p) >= 0)

-      {

-        if (pLast == NULL)

-          pLast = p;

-      }

-      else

-        pLast = NULL;

-      p = GetNextCharPointer(p);

-    }

-    if (pLast != NULL)

-    {

-      int i = (int)(pLast - _chars);

-      Delete(i, _length - i);

-    }

+  char *_chars;

+  unsigned _len;

+  unsigned _limit;

 

-  }

-  void MoveItems(int destIndex, int srcIndex)

+  void MoveItems(unsigned dest, unsigned src)

   {

-    memmove(_chars + destIndex, _chars + srcIndex,

-        sizeof(T) * (_length - srcIndex + 1));

+    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));

   }

   

-  void InsertSpace(int &index, int size)

-  {

-    CorrectIndex(index);

-    GrowLength(size);

-    MoveItems(index + size, index);

-  }

-

-  static const T *GetNextCharPointer(const T *p)

-    { return MyStringGetNextCharPointer(p); }

-  static const T *GetPrevCharPointer(const T *base, const T *p)

-    { return MyStringGetPrevCharPointer(base, p); }

-protected:

-  T *_chars;

-  int _length;

-  int _capacity;

+  void InsertSpace(unsigned &index, unsigned size);

   

-  void SetCapacity(int newCapacity)

-  {

-    int realCapacity = newCapacity + 1;

-    if (realCapacity == _capacity)

-      return;

-    /*

-    const int kMaxStringSize = 0x20000000;

-    if (newCapacity > kMaxStringSize || newCapacity < _length)

-      throw 1052337;

-    */

-    T *newBuffer = new T[realCapacity];

-    if (_capacity > 0)

-    {

-      for (int i = 0; i < _length; i++)

-        newBuffer[i] = _chars[i];

-      delete []_chars;

-    }

-    _chars = newBuffer;

-    _chars[_length] = 0;

-    _capacity = realCapacity;

-  }

+  void ReAlloc(unsigned newLimit);

+  void SetStartLen(unsigned len);

+  void Grow_1();

+  void Grow(unsigned n);

 

-  void GrowLength(int n)

-  {

-    int freeSize = _capacity - _length - 1;

-    if (n <= freeSize)

-      return;

-    int delta;

-    if (_capacity > 64)

-      delta = _capacity / 2;

-    else if (_capacity > 8)

-      delta = 16;

-    else

-      delta = 4;

-    if (freeSize + delta < n)

-      delta = n - freeSize;

-    SetCapacity(_capacity + delta);

-  }

+  // AString(unsigned num, const char *s);

+  AString(unsigned num, const AString &s);

+  AString(const AString &s, char c); // it's for String + char

+  AString(const char *s1, unsigned num1, const char *s2, unsigned num2);

 

-  void CorrectIndex(int &index) const

-  {

-    if (index > _length)

-      index = _length;

-  }

+  friend AString operator+(const AString &s, char c) { return AString(s, c); } ;

+  // friend AString operator+(char c, const AString &s); // is not supported

+

+  friend AString operator+(const AString &s1, const AString &s2);

+  friend AString operator+(const AString &s1, const char    *s2);

+  friend AString operator+(const char    *s1, const AString &s2);

 

 public:

-  CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }

-  CStringBase(T c):  _chars(0), _length(0), _capacity(0)

-  {

-    SetCapacity(1);

-    _chars[0] = c;

-    _chars[1] = 0;

-    _length = 1;

-  }

-  CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)

-  {

-    int length = MyStringLen(chars);

-    SetCapacity(length);

-    MyStringCopy(_chars, chars); // can be optimized by memove()

-    _length = length;

-  }

-  CStringBase(const CStringBase &s):  _chars(0), _length(0), _capacity(0)

-  {

-    SetCapacity(s._length);

-    MyStringCopy(_chars, s._chars);

-    _length = s._length;

-  }

-  ~CStringBase() {  delete []_chars; }

+  AString();

+  AString(char c);

+  AString(const char *s);

+  AString(const AString &s);

+  ~AString() { MY_STRING_DELETE(_chars); }

 

-  operator const T*() const { return _chars;}

+  unsigned Len() const { return _len; }

+  bool IsEmpty() const { return _len == 0; }

+  void Empty() { _len = 0; _chars[0] = 0; }

 

-  T Back() const { return _chars[_length - 1]; }

+  operator const char *() const { return _chars; }

+  const char *Ptr() const { return _chars; }

+  const char *Ptr(unsigned pos) const { return _chars + pos; }

+  const char *RightPtr(unsigned num) const { return _chars + _len - num; }

+  char Back() const { return _chars[_len - 1]; }

+

+  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.

-  T* GetBuffer(int minBufLength)

+  char *GetBuffer(unsigned minBufLen)

   {

-    if (minBufLength >= _capacity)

-      SetCapacity(minBufLength);

+    if (minBufLen > _limit)

+      ReAlloc(minBufLen);

     return _chars;

   }

   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }

-  void ReleaseBuffer(int newLength)

-  {

-    /*

-    if (newLength >= _capacity)

-      throw 282217;

-    */

-    _chars[newLength] = 0;

-    _length = newLength;

-  }

+  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

 

-  CStringBase& operator=(T c)

+  AString &operator=(char c);

+  AString &operator=(const char *s);

+  AString &operator=(const AString &s);

+

+  AString &operator+=(char c)

   {

-    Empty();

-    SetCapacity(1);

-    _chars[0] = c;

-    _chars[1] = 0;

-    _length = 1;

+    if (_limit == _len)

+      Grow_1();

+    unsigned len = _len;

+    char *chars = _chars;

+    chars[len++] = c;

+    chars[len] = 0;

+    _len = len;

     return *this;

   }

-  CStringBase& operator=(const T *chars)

-  {

-    Empty();

-    int length = MyStringLen(chars);

-    SetCapacity(length);

-    MyStringCopy(_chars, chars);

-    _length = length;

-    return *this;

-  }

-  CStringBase& operator=(const CStringBase& s)

-  {

-    if (&s == this)

-      return *this;

-    Empty();

-    SetCapacity(s._length);

-    MyStringCopy(_chars, s._chars);

-    _length = s._length;

-    return *this;

-  }

-  

-  CStringBase& operator+=(T c)

-  {

-    GrowLength(1);

-    _chars[_length] = c;

-    _chars[++_length] = 0;

-    return *this;

-  }

-  CStringBase& operator+=(const T *s)

-  {

-    int len = MyStringLen(s);

-    GrowLength(len);

-    MyStringCopy(_chars + _length, s);

-    _length += len;

-    return *this;

-  }

-  CStringBase& operator+=(const CStringBase &s)

-  {

-    GrowLength(s._length);

-    MyStringCopy(_chars + _length, s._chars);

-    _length += s._length;

-    return *this;

-  }

-  void Empty()

-  {

-    _length = 0;

-    _chars[0] = 0;

-  }

-  int Length() const { return _length; }

-  bool IsEmpty() const { return (_length == 0); }

 

-  CStringBase Mid(int startIndex) const

-    { return Mid(startIndex, _length - startIndex); }

-  CStringBase Mid(int startIndex, int count) const

-  {

-    if (startIndex + count > _length)

-      count = _length - startIndex;

-    

-    if (startIndex == 0 && startIndex + count == _length)

-      return *this;

-    

-    CStringBase<T> result;

-    result.SetCapacity(count);

-    // MyStringNCopy(result._chars, _chars + startIndex, count);

-    for (int i = 0; i < count; i++)

-      result._chars[i] = _chars[startIndex + i];

-    result._chars[count] = 0;

-    result._length = count;

-    return result;

-  }

-  CStringBase Left(int count) const

-    { return Mid(0, count); }

-  CStringBase Right(int count) const

-  {

-    if (count > _length)

-      count = _length;

-    return Mid(_length - count, count);

-  }

+  AString &operator+=(const char *s);

+  AString &operator+=(const AString &s);

 

-  void MakeUpper()

-    { MyStringUpper(_chars); }

-  void MakeLower()

-    { MyStringLower(_chars); }

+  void SetFrom(const char *s, unsigned len); // no check

+  // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }

+  AString Left(unsigned count) const { return AString(count, *this); }

 

-  int Compare(const CStringBase& s) const

-    { return MyStringCompare(_chars, s._chars); }

+  // void MakeUpper() { MyStringUpper(_chars); }

+  // void MakeLower() { MyStringLower(_chars); }

 

-  int Compare(const T *s) const

-    { return MyStringCompare(_chars, s); }

 

-  int CompareNoCase(const CStringBase& s) const

-    { return MyStringCompareNoCase(_chars, s._chars); }

+  // 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); }

+  // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }

+  bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }

+  bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();

+ 

+  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 CompareNoCase(const T *s) const

-    { return MyStringCompareNoCase(_chars, s); }

-

-  /*

-  int Collate(const CStringBase& s) const

-    { return MyStringCollate(_chars, s._chars); }

-  int CollateNoCase(const CStringBase& s) const

-    { return MyStringCollateNoCase(_chars, s._chars); }

-  */

-

-  int Find(T c) const { return Find(c, 0); }

-  int Find(T c, int startIndex) const

-  {

-    const T *p = _chars + startIndex;

-    for (;;)

-    {

-      if (*p == c)

-        return (int)(p - _chars);

-      if (*p == 0)

-        return -1;

-      p = GetNextCharPointer(p);

-    }

-  }

-  int Find(const CStringBase &s) const { return Find(s, 0); }

-  int Find(const CStringBase &s, int startIndex) const

-  {

-    if (s.IsEmpty())

-      return startIndex;

-    for (; startIndex < _length; startIndex++)

-    {

-      int j;

-      for (j = 0; j < s._length && startIndex + j < _length; j++)

-        if (_chars[startIndex+j] != s._chars[j])

-          break;

-      if (j == s._length)

-        return startIndex;

-    }

-    return -1;

-  }

-  int ReverseFind(T c) const

-  {

-    if (_length == 0)

-      return -1;

-    const T *p = _chars + _length - 1;

-    for (;;)

-    {

-      if (*p == c)

-        return (int)(p - _chars);

-      if (p == _chars)

-        return -1;

-      p = GetPrevCharPointer(_chars, p);

-    }

-  }

-  int FindOneOf(const CStringBase &s) const

-  {

-    for (int i = 0; i < _length; i++)

-      if (s.Find(_chars[i]) >= 0)

-        return i;

-      return -1;

-  }

-

-  void TrimLeft(T c)

-  {

-    const T *p = _chars;

-    while (c == *p)

-      p = GetNextCharPointer(p);

-    Delete(0, p - _chars);

-  }

-  private:

-  CStringBase GetTrimDefaultCharSet()

-  {

-    CStringBase<T> charSet;

-    charSet += (T)' ';

-    charSet += (T)'\n';

-    charSet += (T)'\t';

-    return charSet;

-  }

-  public:

-

-  void TrimLeft()

-  {

-    TrimLeftWithCharSet(GetTrimDefaultCharSet());

-  }

-  void TrimRight()

-  {

-    TrimRightWithCharSet(GetTrimDefaultCharSet());

-  }

-  void TrimRight(T c)

-  {

-    const T *p = _chars;

-    const T *pLast = NULL;

-    while (*p != 0)

-    {

-      if (*p == c)

-      {

-        if (pLast == NULL)

-          pLast = p;

-      }

-      else

-        pLast = NULL;

-      p = GetNextCharPointer(p);

-    }

-    if (pLast != NULL)

-    {

-      int i = pLast - _chars;

-      Delete(i, _length - i);

-    }

-  }

+  void TrimLeft() throw();

+  void TrimRight() throw();

   void Trim()

   {

     TrimRight();

     TrimLeft();

   }

 

-  int Insert(int index, T c)

-  {

-    InsertSpace(index, 1);

-    _chars[index] = c;

-    _length++;

-    return _length;

-  }

-  int Insert(int index, const CStringBase &s)

-  {

-    CorrectIndex(index);

-    if (s.IsEmpty())

-      return _length;

-    int numInsertChars = s.Length();

-    InsertSpace(index, numInsertChars);

-    for (int i = 0; i < numInsertChars; i++)

-      _chars[index + i] = s[i];

-    _length += numInsertChars;

-    return _length;

-  }

+  void InsertAtFront(char c);

+  // void Insert(unsigned index, char c);

+  void Insert(unsigned index, const char *s);

+  void Insert(unsigned index, const AString &s);

 

-  // !!!!!!!!!!!!!!! test it if newChar = '\0'

-  int Replace(T oldChar, T newChar)

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

+  void DeleteBack() { _chars[--_len] = 0; }

+  void DeleteFrom(unsigned index)

   {

-    if (oldChar == newChar)

-      return 0;

-    int number  = 0;

-    int pos  = 0;

-    while (pos < Length())

+    if (index < _len)

     {

-      pos = Find(oldChar, pos);

-      if (pos < 0)

-        break;

-      _chars[pos] = newChar;

-      pos++;

-      number++;

+      _len = index;

+      _chars[index] = 0;

     }

-    return number;

   }

-  int Replace(const CStringBase &oldString, const CStringBase &newString)

-  {

-    if (oldString.IsEmpty())

-      return 0;

-    if (oldString == newString)

-      return 0;

-    int oldStringLength = oldString.Length();

-    int newStringLength = newString.Length();

-    int number  = 0;

-    int pos  = 0;

-    while (pos < _length)

-    {

-      pos = Find(oldString, pos);

-      if (pos < 0)

-        break;

-      Delete(pos, oldStringLength);

-      Insert(pos, newString);

-      pos += newStringLength;

-      number++;

-    }

-    return number;

-  }

-  int Delete(int index, int count = 1)

-  {

-    if (index + count > _length)

-      count = _length - index;

-    if (count > 0)

-    {

-      MoveItems(index, index + count);

-      _length -= count;

-    }

-    return _length;

-  }

-  void DeleteBack() { Delete(_length - 1); }

 };

 

-template <class T>

-CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)

+bool operator<(const AString &s1, const AString &s2);

+bool operator>(const AString &s1, const AString &s2);

+

+/*

+bool operator==(const AString &s1, const AString &s2);

+bool operator==(const AString &s1, const char    *s2);

+bool operator==(const char    *s1, const AString &s2);

+

+bool operator!=(const AString &s1, const AString &s2);

+bool operator!=(const AString &s1, const char    *s2);

+bool operator!=(const char    *s1, const AString &s2);

+*/

+

+inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }

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

+

+inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }

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

+

+

+

+class UString

 {

-  CStringBase<T> result(s1);

-  result += s2;

-  return result;

-}

+  wchar_t *_chars;

+  unsigned _len;

+  unsigned _limit;

 

-template <class T>

-CStringBase<T> operator+(const CStringBase<T>& s, T c)

-{

-  CStringBase<T> result(s);

-  result += c;

-  return result;

-}

+  void MoveItems(unsigned dest, unsigned src)

+  {

+    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));

+  }

+  

+  void InsertSpace(unsigned index, unsigned size);

+  

+  void ReAlloc(unsigned newLimit);

+  void SetStartLen(unsigned len);

+  void Grow_1();

+  void Grow(unsigned n);

 

-template <class T>

-CStringBase<T> operator+(T c, const CStringBase<T>& s)

-{

-  CStringBase<T> result(c);

-  result += s;

-  return result;

-}

+  UString(unsigned num, const wchar_t *s); // for Mid

+  UString(unsigned num, const UString &s); // for Left

+  UString(const UString &s, wchar_t c); // it's for String + char

+  UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);

 

-template <class T>

-CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)

-{

-  CStringBase<T> result(s);

-  result += chars;

-  return result;

-}

+  friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ;

+  // friend UString operator+(wchar_t c, const UString &s); // is not supported

 

-template <class T>

-CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)

-{

-  CStringBase<T> result(chars);

-  result += s;

-  return result;

-}

+  friend UString operator+(const UString &s1, const UString &s2);

+  friend UString operator+(const UString &s1, const wchar_t *s2);

+  friend UString operator+(const wchar_t *s1, const UString &s2);

 

-template <class T>

-bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)

-  { return (s1.Compare(s2) == 0); }

+public:

+  UString();

+  UString(wchar_t c);

+  UString(const wchar_t *s);

+  UString(const UString &s);

+  ~UString() { MY_STRING_DELETE(_chars); }

 

-template <class T>

-bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)

-  { return (s1.Compare(s2) < 0); }

+  unsigned Len() const { return _len; }

+  bool IsEmpty() const { return _len == 0; }

+  void Empty() { _len = 0; _chars[0] = 0; }

 

-template <class T>

-bool operator==(const T *s1, const CStringBase<T>& s2)

-  { return (s2.Compare(s1) == 0); }

+  operator const wchar_t *() const { return _chars; }

+  const wchar_t *Ptr() const { return _chars; }

+  const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }

+  const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }

+  wchar_t Back() const { return _chars[_len - 1]; }

 

-template <class T>

-bool operator==(const CStringBase<T>& s1, const T *s2)

-  { return (s1.Compare(s2) == 0); }

+  void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }

 

-template <class T>

-bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)

-  { return (s1.Compare(s2) != 0); }

+  // The minimum size of the character buffer in characters.

+  // This value does not include space for a null terminator.

+  wchar_t *GetBuffer(unsigned minBufLen)

+  {

+    if (minBufLen > _limit)

+      ReAlloc(minBufLen);

+    return _chars;

+  }

+  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }

+  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }

 

-template <class T>

-bool operator!=(const T *s1, const CStringBase<T>& s2)

-  { return (s2.Compare(s1) != 0); }

+  UString &operator=(wchar_t c);

+  UString &operator=(const wchar_t *s);

+  UString &operator=(const UString &s);

 

-template <class T>

-bool operator!=(const CStringBase<T>& s1, const T *s2)

-  { return (s1.Compare(s2) != 0); }

+  UString &operator+=(wchar_t c)

+  {

+    if (_limit == _len)

+      Grow_1();

+    unsigned len = _len;

+    wchar_t *chars = _chars;

+    chars[len++] = c;

+    chars[len] = 0;

+    _len = len;

+    return *this;

+  }

 

-typedef CStringBase<char> AString;

-typedef CStringBase<wchar_t> UString;

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

+

+  UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }

+  UString Left(unsigned count) const { return UString(count, *this); }

+

+  // void MakeUpper() { MyStringUpper(_chars); }

+  // void MakeUpper() { MyStringUpper_Ascii(_chars); }

+  // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }

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

+  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_Ascii_NoCase(const char *s) const throw();

+

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

+

+  void TrimLeft() throw();

+  void TrimRight() throw();

+  void Trim()

+  {

+    TrimRight();

+    TrimLeft();

+  }

+

+  void InsertAtFront(wchar_t c);

+  // void Insert(unsigned index, wchar_t c);

+  void Insert(unsigned index, const wchar_t *s);

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

+  void DeleteBack() { _chars[--_len] = 0; }

+  void DeleteFrom(unsigned index)

+  {

+    if (index < _len)

+    {

+      _len = index;

+      _chars[index] = 0;

+    }

+  }

+};

+

+bool operator<(const UString &s1, const UString &s2);

+bool operator>(const UString &s1, const UString &s2);

+

+inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }

+inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }

+inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }

+

+inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }

+inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }

+inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }

+

 

 typedef CObjectVector<AString> AStringVector;

 typedef CObjectVector<UString> UStringVector;

@@ -622,4 +479,47 @@
 

 typedef CObjectVector<CSysString> CSysStringVector;

 

+

+// ---------- FString ----------

+

+#ifdef _WIN32

+  #define USE_UNICODE_FSTRING

+#endif

+

+#ifdef USE_UNICODE_FSTRING

+

+  #define __FTEXT(quote) L##quote

+

+  typedef wchar_t FChar;

+  typedef UString FString;

+

+  #define fs2us(_x_) (_x_)

+  #define us2fs(_x_) (_x_)

+  FString fas2fs(const AString &s);

+  AString fs2fas(const FChar *s);

+

+#else

+

+  #define __FTEXT(quote) quote

+

+  typedef char FChar;

+  typedef AString FString;

+

+  UString fs2us(const FString &s);

+  FString us2fs(const wchar_t *s);

+  #define fas2fs(_x_) (_x_)

+  #define fs2fas(_x_) (_x_)

+

+#endif

+

+#define FTEXT(quote) __FTEXT(quote)

+

+#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)

+#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)

+#define FCHAR_ANY_MASK FTEXT('*')

+#define FSTRING_ANY_MASK FTEXT("*")

+typedef const FChar *CFSTR;

+

+typedef CObjectVector<FString> FStringVector;

+

 #endif

diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
new file mode 100644
index 0000000..f49739c
--- /dev/null
+++ b/CPP/Common/MyTypes.h
@@ -0,0 +1,30 @@
+// Common/MyTypes.h

+

+#ifndef __COMMON_MY_TYPES_H

+#define __COMMON_MY_TYPES_H

+

+#include "../../C/7zTypes.h"

+

+typedef int HRes;

+

+struct CBoolPair

+{

+  bool Val;

+  bool Def;

+

+  CBoolPair(): Val(false), Def(false) {}

+  

+  void Init()

+  {

+    Val = false;

+    Def = false;

+  }

+

+  void SetTrueTrue()

+  {

+    Val = true;

+    Def = true;

+  }

+};

+

+#endif

diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
old mode 100755
new mode 100644
diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp
old mode 100755
new mode 100644
index 054d0aa..9a6d1d5
--- a/CPP/Common/MyVector.cpp
+++ b/CPP/Common/MyVector.cpp
@@ -1,87 +1,3 @@
 // Common/MyVector.cpp

 

 #include "StdAfx.h"

-

-#include <string.h>

-

-#include "MyVector.h"

-

-CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); }

-

-void CBaseRecordVector::ClearAndFree()

-{

-  Clear();

-  delete []((unsigned char *)_items);

-  _capacity = 0;

-  _size = 0;

-  _items = 0;

-}

-

-void CBaseRecordVector::Clear() { DeleteFrom(0); }

-void CBaseRecordVector::DeleteBack() { Delete(_size - 1); }

-void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); }

-

-void CBaseRecordVector::ReserveOnePosition()

-{

-  if (_size != _capacity)

-    return;

-  unsigned delta = 1;

-  if (_capacity >= 64)

-    delta = (unsigned)_capacity / 4;

-  else if (_capacity >= 8)

-    delta = 8;

-  Reserve(_capacity + (int)delta);

-}

-

-void CBaseRecordVector::Reserve(int newCapacity)

-{

-  // if (newCapacity <= _capacity)

-  if (newCapacity == _capacity)

-    return;

-  if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1)))

-    throw 1052353;

-  size_t newSize = (size_t)(unsigned)newCapacity * _itemSize;

-  if (newSize / _itemSize != (size_t)(unsigned)newCapacity)

-    throw 1052354;

-  unsigned char *p = NULL;

-  if (newSize > 0)

-  {

-    p = new unsigned char[newSize];

-    if (p == 0)

-      throw 1052355;

-    int numRecordsToMove = (_size < newCapacity ? _size : newCapacity);

-    memcpy(p, _items, _itemSize * numRecordsToMove);

-  }

-  delete [](unsigned char *)_items;

-  _items = p;

-  _capacity = newCapacity;

-}

-

-void CBaseRecordVector::ReserveDown()

-{

-  Reserve(_size);

-}

-

-void CBaseRecordVector::MoveItems(int destIndex, int srcIndex)

-{

-  memmove(((unsigned char *)_items) + destIndex * _itemSize,

-    ((unsigned char  *)_items) + srcIndex * _itemSize,

-    _itemSize * (_size - srcIndex));

-}

-

-void CBaseRecordVector::InsertOneItem(int index)

-{

-  ReserveOnePosition();

-  MoveItems(index + 1, index);

-  _size++;

-}

-

-void CBaseRecordVector::Delete(int index, int num)

-{

-  TestIndexAndCorrectNum(index, num);

-  if (num > 0)

-  {

-    MoveItems(index, index + num);

-    _size -= num;

-  }

-}

diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
old mode 100755
new mode 100644
index 24740dc..521aa23
--- a/CPP/Common/MyVector.h
+++ b/CPP/Common/MyVector.h
@@ -1,92 +1,247 @@
-// Common/Vector.h

+// Common/MyVector.h

 

-#ifndef __COMMON_VECTOR_H

-#define __COMMON_VECTOR_H

-

-#include "Defs.h"

-

-class CBaseRecordVector

-{

-  void MoveItems(int destIndex, int srcIndex);

-protected:

-  int _capacity;

-  int _size;

-  void *_items;

-  size_t _itemSize;

-  

-  void ReserveOnePosition();

-  void InsertOneItem(int index);

-  void TestIndexAndCorrectNum(int index, int &num) const

-    { if (index + num > _size) num = _size - index; }

-public:

-  CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}

-  virtual ~CBaseRecordVector();

-  void ClearAndFree();

-  int Size() const { return _size; }

-  bool IsEmpty() const { return (_size == 0); }

-  void Reserve(int newCapacity);

-  void ReserveDown();

-  virtual void Delete(int index, int num = 1);

-  void Clear();

-  void DeleteFrom(int index);

-  void DeleteBack();

-};

+#ifndef __COMMON_MY_VECTOR_H

+#define __COMMON_MY_VECTOR_H

 

 template <class T>

-class CRecordVector: public CBaseRecordVector

+class CRecordVector

 {

+  T *_items;

+  unsigned _size;

+  unsigned _capacity;

+  

+  void MoveItems(unsigned destIndex, unsigned srcIndex)

+  {

+    memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * (size_t)sizeof(T));

+  }

+

+  void ReserveOnePosition()

+  {

+    if (_size == _capacity)

+    {

+      unsigned newCapacity = _capacity + (_capacity >> 2) + 1;

+      T *p = new T[newCapacity];

+      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      delete []_items;

+      _items = p;

+      _capacity = newCapacity;

+    }

+  }

+

 public:

-  CRecordVector(): CBaseRecordVector(sizeof(T)){};

-  CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; }

-  CRecordVector& operator=(const CRecordVector &v)

+

+  CRecordVector(): _items(0), _size(0), _capacity(0) {}

+  

+  CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0)

+  {

+    unsigned size = v.Size();

+    if (size != 0)

+    {

+      _items = new T[size];

+      _size = size;

+      _capacity = size;

+      memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));

+    }

+  }

+  

+  unsigned Size() const { return _size; }

+  bool IsEmpty() const { return _size == 0; }

+  

+  void ConstructReserve(unsigned size)

+  {

+    if (size != 0)

+    {

+      _items = new T[size];

+      _capacity = size;

+    }

+  }

+

+  void Reserve(unsigned newCapacity)

+  {

+    if (newCapacity > _capacity)

+    {

+      T *p = new T[newCapacity];

+      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      delete []_items;

+      _items = p;

+      _capacity = newCapacity;

+    }

+  }

+

+  void ClearAndReserve(unsigned newCapacity)

   {

     Clear();

-    return (*this += v);

+    if (newCapacity > _capacity)

+    {

+      delete []_items;

+      _items = NULL;

+      _capacity = 0;

+      _items = new T[newCapacity];

+      _capacity = newCapacity;

+    }

   }

-  CRecordVector& operator+=(const CRecordVector &v)

+

+  void ClearAndSetSize(unsigned newSize)

   {

-    int size = v.Size();

-    Reserve(Size() + size);

-    for (int i = 0; i < size; i++)

-      Add(v[i]);

+    ClearAndReserve(newSize);

+    _size = newSize;

+  }

+

+  void ChangeSize_KeepData(unsigned newSize)

+  {

+    if (newSize > _capacity)

+    {

+      T *p = new T[newSize];

+      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+      delete []_items;

+      _items = p;

+      _capacity = newSize;

+    }

+    _size = newSize;

+  }

+

+  void ReserveDown()

+  {

+    if (_size == _capacity)

+      return;

+    T *p = NULL;

+    if (_size != 0)

+    {

+      p = new T[_size];

+      memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));

+    }

+    delete []_items;

+    _items = p;

+    _capacity = _size;

+  }

+  

+  ~CRecordVector() { delete []_items; }

+  

+  void ClearAndFree()

+  {

+    delete []_items;

+    _items = NULL;

+    _size = 0;

+    _capacity = 0;

+  }

+  

+  void Clear() { _size = 0; }

+

+  void DeleteBack() { _size--; }

+  

+  void DeleteFrom(unsigned index)

+  {

+    // if (index <= _size)

+      _size = index;

+  }

+  

+  void DeleteFrontal(unsigned num)

+  {

+    if (num != 0)

+    {

+      MoveItems(0, num);

+      _size -= num;

+    }

+  }

+

+  void Delete(unsigned index)

+  {

+    MoveItems(index, index + 1);

+    _size -= 1;

+  }

+

+  /*

+  void Delete(unsigned index, unsigned num)

+  {

+    if (num > 0)

+    {

+      MoveItems(index, index + num);

+      _size -= num;

+    }

+  }

+  */

+

+  CRecordVector& operator=(const CRecordVector &v)

+  {

+    unsigned size = v.Size();

+    if (size > _capacity)

+    {

+      delete []_items;

+      _capacity = 0;

+      _size = 0;

+      _items = NULL;

+      _items = new T[size];

+      _capacity = size;

+    }

+    _size = size;

+    memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));

     return *this;

   }

-  int Add(T item)

+

+  CRecordVector& operator+=(const CRecordVector &v)

+  {

+    unsigned size = v.Size();

+    Reserve(_size + size);

+    memcpy(_items + _size, v._items, (size_t)size * (size_t)sizeof(T));

+    _size += size;

+    return *this;

+  }

+  

+  unsigned Add(const T item)

   {

     ReserveOnePosition();

-    ((T *)_items)[_size] = item;

+    _items[_size] = item;

     return _size++;

   }

-  void Insert(int index, T item)

-  {

-    InsertOneItem(index);

-    ((T *)_items)[index] = item;

-  }

-  // T* GetPointer() const { return (T*)_items; }

-  // operator const T *() const { return _items; };

-  const T& operator[](int index) const { return ((T *)_items)[index]; }

-  T& operator[](int index) { return ((T *)_items)[index]; }

-  const T& Front() const { return operator[](0); }

-  T& Front() { return operator[](0); }

-  const T& Back() const { return operator[](_size - 1); }

-  T& Back() { return operator[](_size - 1); }

 

-  void Swap(int i, int j)

+  void AddInReserved(const T item)

   {

-    T temp = operator[](i);

-    operator[](i) = operator[](j);

-    operator[](j) = temp;

+    _items[_size++] = item;

   }

 

-  int FindInSorted(const T& item, int left, int right) const

+  void Insert(unsigned index, const T item)

+  {

+    ReserveOnePosition();

+    MoveItems(index + 1, index);

+    _items[index] = item;

+    _size++;

+  }

+

+  void MoveToFront(unsigned index)

+  {

+    if (index != 0)

+    {

+      T temp = _items[index];

+      memmove(_items + 1, _items, (size_t)index * (size_t)sizeof(T));

+      _items[0] = temp;

+    }

+  }

+

+  const T& operator[](unsigned index) const { return _items[index]; }

+        T& operator[](unsigned index)       { return _items[index]; }

+  const T& Front() const { return _items[0]; }

+        T& Front()       { return _items[0]; }

+  const T& Back() const  { return _items[_size - 1]; }

+        T& Back()        { return _items[_size - 1]; }

+

+  /*

+  void Swap(unsigned i, unsigned j)

+  {

+    T temp = _items[i];

+    _items[i] = _items[j];

+    _items[j] = temp;

+  }

+  */

+

+  int FindInSorted(const T item, unsigned left, unsigned right) const

   {

     while (left != right)

     {

-      int mid = (left + right) / 2;

-      const T& midValue = (*this)[mid];

-      if (item == midValue)

+      unsigned mid = (left + right) / 2;

+      const T midVal = (*this)[mid];

+      if (item == midVal)

         return mid;

-      if (item < midValue)

+      if (item < midVal)

         right = mid;

       else

         left = mid + 1;

@@ -94,16 +249,16 @@
     return -1;

   }

 

-  int FindInSorted(const T& item) const

+  int FindInSorted2(const T &item, unsigned left, unsigned right) const

   {

-    int left = 0, right = Size();

     while (left != right)

     {

-      int mid = (left + right) / 2;

-      const T& midValue = (*this)[mid];

-      if (item == midValue)

+      unsigned mid = (left + right) / 2;

+      const T& midVal = (*this)[mid];

+      int comp = item.Compare(midVal);

+      if (comp == 0)

         return mid;

-      if (item < midValue)

+      if (comp < 0)

         right = mid;

       else

         left = mid + 1;

@@ -111,16 +266,26 @@
     return -1;

   }

 

-  int AddToUniqueSorted(const T& item)

+  int FindInSorted(const T item) const

   {

-    int left = 0, right = Size();

+    return FindInSorted(item, 0, _size);

+  }

+

+  int FindInSorted2(const T &item) const

+  {

+    return FindInSorted2(item, 0, _size);

+  }

+

+  unsigned AddToUniqueSorted(const T item)

+  {

+    unsigned left = 0, right = _size;

     while (left != right)

     {

-      int mid = (left + right) / 2;

-      const T& midValue = (*this)[mid];

-      if (item == midValue)

+      unsigned mid = (left + right) / 2;

+      const T midVal = (*this)[mid];

+      if (item == midVal)

         return mid;

-      if (item < midValue)

+      if (item < midVal)

         right = mid;

       else

         left = mid + 1;

@@ -129,12 +294,31 @@
     return right;

   }

 

-  static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param)

+  unsigned AddToUniqueSorted2(const T &item)

+  {

+    unsigned left = 0, right = _size;

+    while (left != right)

+    {

+      unsigned mid = (left + right) / 2;

+      const T& midVal = (*this)[mid];

+      int comp = item.Compare(midVal);

+      if (comp == 0)

+        return mid;

+      if (comp < 0)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    Insert(right, item);

+    return right;

+  }

+

+  static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)

   {

     T temp = p[k];

     for (;;)

     {

-      int s = (k << 1);

+      unsigned s = (k << 1);

       if (s > size)

         break;

       if (s < size && compare(p + s + 1, p + s, param) > 0)

@@ -149,12 +333,12 @@
 

   void Sort(int (*compare)(const T*, const T*, void *), void *param)

   {

-    int size = _size;

+    unsigned size = _size;

     if (size <= 1)

       return;

     T* p = (&Front()) - 1;

     {

-      int i = size / 2;

+      unsigned i = size >> 1;

       do

         SortRefDown(p, i, size, compare, param);

       while (--i != 0);

@@ -168,6 +352,46 @@
     }

     while (size > 1);

   }

+

+  static void SortRefDown2(T* p, unsigned k, unsigned size)

+  {

+    T temp = p[k];

+    for (;;)

+    {

+      unsigned s = (k << 1);

+      if (s > size)

+        break;

+      if (s < size && p[s + 1].Compare(p[s]) > 0)

+        s++;

+      if (temp.Compare(p[s]) >= 0)

+        break;

+      p[k] = p[s];

+      k = s;

+    }

+    p[k] = temp;

+  }

+

+  void Sort2()

+  {

+    unsigned size = _size;

+    if (size <= 1)

+      return;

+    T* p = (&Front()) - 1;

+    {

+      unsigned i = size >> 1;

+      do

+        SortRefDown2(p, i, size);

+      while (--i != 0);

+    }

+    do

+    {

+      T temp = p[size];

+      p[size--] = p[1];

+      p[1] = temp;

+      SortRefDown2(p, 1, size);

+    }

+    while (size > 1);

+  }

 };

 

 typedef CRecordVector<int> CIntVector;

@@ -177,76 +401,174 @@
 typedef CRecordVector<void *> CPointerVector;

 

 template <class T>

-class CObjectVector: public CPointerVector

+class CObjectVector

 {

+  CPointerVector _v;

 public:

+  unsigned Size() const { return _v.Size(); }

+  bool IsEmpty() const { return _v.IsEmpty(); }

+  void ReserveDown() { _v.ReserveDown(); }

+  // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); }

+  void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); }

+

   CObjectVector() {};

-  ~CObjectVector() { Clear(); };

-  CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; }

+  CObjectVector(const CObjectVector &v)

+  {

+    unsigned size = v.Size();

+    _v.ConstructReserve(size);

+    for (unsigned i = 0; i < size; i++)

+      _v.AddInReserved(new T(v[i]));

+  }

   CObjectVector& operator=(const CObjectVector &v)

   {

     Clear();

-    return (*this += v);

-  }

-  CObjectVector& operator+=(const CObjectVector &v)

-  {

-    int size = v.Size();

-    Reserve(Size() + size);

-    for (int i = 0; i < size; i++)

-      Add(v[i]);

+    unsigned size = v.Size();

+    _v.Reserve(size);

+    for (unsigned i = 0; i < size; i++)

+      _v.AddInReserved(new T(v[i]));

     return *this;

   }

-  const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }

-  T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }

-  T& Front() { return operator[](0); }

-  const T& Front() const { return operator[](0); }

-  T& Back() { return operator[](_size - 1); }

-  const T& Back() const { return operator[](_size - 1); }

-  int Add(const T& item) { return CPointerVector::Add(new T(item)); }

-  void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); }

-  virtual void Delete(int index, int num = 1)

+

+  CObjectVector& operator+=(const CObjectVector &v)

   {

-    TestIndexAndCorrectNum(index, num);

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

-      delete (T *)(((void **)_items)[index + i]);

-    CPointerVector::Delete(index, num);

+    unsigned size = v.Size();

+    _v.Reserve(Size() + size);

+    for (unsigned i = 0; i < size; i++)

+      _v.AddInReserved(new T(v[i]));

+    return *this;

   }

+  

+  const T& operator[](unsigned index) const { return *((T *)_v[index]); }

+        T& operator[](unsigned index)       { return *((T *)_v[index]); }

+  const T& Front() const { return operator[](0); }

+        T& Front()       { return operator[](0); }

+  const T& Back() const  { return operator[](_v.Size() - 1); }

+        T& Back()        { return operator[](_v.Size() - 1); }

+  

+  void MoveToFront(unsigned index) { _v.MoveToFront(index); }

+

+  unsigned Add(const T& item) { return _v.Add(new T(item)); }

+  

+  void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); }

+  

+  T& AddNew()

+  {

+    T *p = new T;

+    _v.Add(p);

+    return *p;

+  }

+  

+  T& AddNewInReserved()

+  {

+    T *p = new T;

+    _v.AddInReserved(p);

+    return *p;

+  }

+  

+  void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); }

+  

+  T& InsertNew(unsigned index)

+  {

+    T *p = new T;

+    _v.Insert(index, p);

+    return *p;

+  }

+

+  ~CObjectVector()

+  {

+    for (unsigned i = _v.Size(); i != 0;)

+      delete (T *)_v[--i];

+  }

+  

+  void ClearAndFree()

+  {

+    Clear();

+    _v.ClearAndFree();

+  }

+  

+  void Clear()

+  {

+    for (unsigned i = _v.Size(); i != 0;)

+      delete (T *)_v[--i];

+    _v.Clear();

+  }

+  

+  void DeleteFrom(unsigned index)

+  {

+    unsigned size = _v.Size();

+    for (unsigned i = index; i < size; i++)

+      delete (T *)_v[i];

+    _v.DeleteFrom(index);

+  }

+

+  void DeleteFrontal(unsigned num)

+  {

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

+      delete (T *)_v[i];

+    _v.DeleteFrontal(num);

+  }

+

+  void DeleteBack()

+  {

+    delete (T *)_v[_v.Size() - 1];

+    _v.DeleteBack();

+  }

+

+  void Delete(unsigned index)

+  {

+    delete (T *)_v[index];

+    _v.Delete(index);

+  }

+

+  /*

+  void Delete(unsigned index, unsigned num)

+  {

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

+      delete (T *)_v[index + i];

+    _v.Delete(index, num);

+  }

+  */

+

+  /*

   int Find(const T& item) const

   {

-    for (int i = 0; i < Size(); i++)

+    unsigned size = Size();

+    for (unsigned i = 0; i < size; i++)

       if (item == (*this)[i])

         return i;

     return -1;

   }

+  */

+  

   int FindInSorted(const T& item) const

   {

-    int left = 0, right = Size();

+    unsigned left = 0, right = Size();

     while (left != right)

     {

-      int mid = (left + right) / 2;

-      const T& midValue = (*this)[mid];

-      if (item == midValue)

+      unsigned mid = (left + right) / 2;

+      const T& midVal = (*this)[mid];

+      int comp = item.Compare(midVal);

+      if (comp == 0)

         return mid;

-      if (item < midValue)

+      if (comp < 0)

         right = mid;

       else

         left = mid + 1;

     }

     return -1;

   }

-  int AddToSorted(const T& item)

+

+  unsigned AddToUniqueSorted(const T& item)

   {

-    int left = 0, right = Size();

+    unsigned left = 0, right = Size();

     while (left != right)

     {

-      int mid = (left + right) / 2;

-      const T& midValue = (*this)[mid];

-      if (item == midValue)

-      {

-        right = mid + 1;

-        break;

-      }

-      if (item < midValue)

+      unsigned mid = (left + right) / 2;

+      const T& midVal = (*this)[mid];

+      int comp = item.Compare(midVal);

+      if (comp == 0)

+        return mid;

+      if (comp < 0)

         right = mid;

       else

         left = mid + 1;

@@ -255,12 +577,39 @@
     return right;

   }

 

+  /*

+  unsigned AddToSorted(const T& item)

+  {

+    unsigned left = 0, right = Size();

+    while (left != right)

+    {

+      unsigned mid = (left + right) / 2;

+      const T& midVal = (*this)[mid];

+      int comp = item.Compare(midVal);

+      if (comp == 0)

+      {

+        right = mid + 1;

+        break;

+      }

+      if (comp < 0)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    Insert(right, item);

+    return right;

+  }

+  */

+

   void Sort(int (*compare)(void *const *, void *const *, void *), void *param)

-    { CPointerVector::Sort(compare, param); }

+    { _v.Sort(compare, param); }

 

   static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)

-    { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }

-  void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }

+    { return (*(*((const T **)a1))).Compare(*(*((const T **)a2))); }

+

+  void Sort() { _v.Sort(CompareObjectItems, 0); }

 };

 

+#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++)

+

 #endif

diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp
new file mode 100644
index 0000000..bc9f7be
--- /dev/null
+++ b/CPP/Common/MyWindows.cpp
@@ -0,0 +1,145 @@
+// MyWindows.cpp

+

+#include "StdAfx.h"

+

+#ifndef _WIN32

+

+#include <stdlib.h>

+

+#include "MyWindows.h"

+

+static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }

+static inline void FreeForBSTR(void *pv) { ::free(pv);}

+

+/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string.

+  We must select CBstrSizeType for another systems (not Win32):

+

+    if (CBstrSizeType is UINT32),

+          then we support only strings smaller than 4 GB.

+          Win32 version always has that limitation.

+  

+    if (CBstrSizeType is UINT),

+          (UINT can be 16/32/64-bit)

+          We can support strings larger than 4 GB (if UINT is 64-bit),

+          but sizeof(UINT) can be different in parts compiled by

+          different compilers/settings,

+          and we can't send such BSTR strings between such parts.

+*/

+

+typedef UINT32 CBstrSizeType;

+// typedef UINT CBstrSizeType;

+

+#define k_BstrSize_Max 0xFFFFFFFF

+// #define k_BstrSize_Max UINT_MAX

+// #define k_BstrSize_Max ((UINT)(INT)-1)

+

+BSTR SysAllocStringByteLen(LPCSTR s, UINT len)

+{

+  /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end.

+     We provide also aligned null OLECHAR at the end. */

+

+  if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(OLECHAR) - sizeof(CBstrSizeType)))

+    return NULL;

+

+  UINT size = (len + sizeof(OLECHAR) + sizeof(OLECHAR) - 1) & ~(sizeof(OLECHAR) - 1);

+  void *p = AllocateForBSTR(size + sizeof(CBstrSizeType));

+  if (!p)

+    return NULL;

+  *(CBstrSizeType *)p = (CBstrSizeType)len;

+  BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);

+  if (s)

+    memcpy(bstr, s, len);

+  for (; len < size; len++)

+    ((Byte *)bstr)[len] = 0;

+  return bstr;

+}

+

+BSTR SysAllocStringLen(const OLECHAR *s, UINT len)

+{

+  if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(CBstrSizeType)) / sizeof(OLECHAR))

+    return NULL;

+

+  UINT size = len * sizeof(OLECHAR);

+  void *p = AllocateForBSTR(size + sizeof(CBstrSizeType) + sizeof(OLECHAR));

+  if (!p)

+    return NULL;

+  *(CBstrSizeType *)p = (CBstrSizeType)size;

+  BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);

+  if (s)

+    memcpy(bstr, s, size);

+  bstr[len] = 0;

+  return bstr;

+}

+

+BSTR SysAllocString(const OLECHAR *s)

+{

+  if (!s)

+    return 0;

+  const OLECHAR *s2 = s;

+  while (*s2 != 0)

+    s2++;

+  return SysAllocStringLen(s, (UINT)(s2 - s));

+}

+

+void SysFreeString(BSTR bstr)

+{

+  if (bstr)

+    FreeForBSTR((CBstrSizeType *)bstr - 1);

+}

+

+UINT SysStringByteLen(BSTR bstr)

+{

+  if (!bstr)

+    return 0;

+  return *((CBstrSizeType *)bstr - 1);

+}

+

+UINT SysStringLen(BSTR bstr)

+{

+  if (!bstr)

+    return 0;

+  return *((CBstrSizeType *)bstr - 1) / sizeof(OLECHAR);

+}

+

+

+HRESULT VariantClear(VARIANTARG *prop)

+{

+  if (prop->vt == VT_BSTR)

+    SysFreeString(prop->bstrVal);

+  prop->vt = VT_EMPTY;

+  return S_OK;

+}

+

+HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src)

+{

+  HRESULT res = ::VariantClear(dest);

+  if (res != S_OK)

+    return res;

+  if (src->vt == VT_BSTR)

+  {

+    dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,

+        SysStringByteLen(src->bstrVal));

+    if (!dest->bstrVal)

+      return E_OUTOFMEMORY;

+    dest->vt = VT_BSTR;

+  }

+  else

+    *dest = *src;

+  return S_OK;

+}

+

+LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)

+{

+  if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;

+  if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;

+  if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;

+  if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;

+  return 0;

+}

+

+DWORD GetLastError()

+{

+  return 0;

+}

+

+#endif

diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
old mode 100755
new mode 100644
index 5cfded1..33145b1
--- a/CPP/Common/MyWindows.h
+++ b/CPP/Common/MyWindows.h
@@ -1,12 +1,17 @@
 // MyWindows.h

 

-#ifndef __MYWINDOWS_H

-#define __MYWINDOWS_H

+#ifndef __MY_WINDOWS_H

+#define __MY_WINDOWS_H

 

 #ifdef _WIN32

 

 #include <windows.h>

 

+#ifdef UNDER_CE

+  #undef VARIANT_TRUE

+  #define VARIANT_TRUE ((VARIANT_BOOL)-1)

+#endif

+

 #else

 

 #include <stddef.h> // for wchar_t

@@ -14,6 +19,8 @@
 

 #include "MyGuidDef.h"

 

+#define WINAPI

+

 typedef char CHAR;

 typedef unsigned char UCHAR;

 

@@ -40,8 +47,8 @@
 typedef Int64 LONGLONG;

 typedef UInt64 ULONGLONG;

 

-typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;

-typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;

+typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER;

+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER;

 

 typedef const CHAR *LPCSTR;

 typedef CHAR TCHAR;

@@ -57,7 +64,7 @@
 {

   DWORD dwLowDateTime;

   DWORD dwHighDateTime;

-}FILETIME;

+} FILETIME;

 

 #define HRESULT LONG

 #define FAILED(Status) ((HRESULT)(Status)<0)

@@ -145,8 +152,6 @@
 typedef WORD PROPVAR_PAD2;

 typedef WORD PROPVAR_PAD3;

 

-#ifdef __cplusplus

-

 typedef struct tagPROPVARIANT

 {

   VARTYPE vt;

@@ -177,11 +182,17 @@
 typedef VARIANT VARIANTARG;

 

 MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);

-MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);

+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src);

 

-#endif

+typedef struct tagSTATPROPSTG

+{

+  LPOLESTR lpwstrName;

+  PROPID propid;

+  VARTYPE vt;

+} STATPROPSTG;

 

 MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);

+MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len);

 MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);

 MY_EXTERN_C void SysFreeString(BSTR bstr);

 MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);

@@ -192,6 +203,7 @@
 

 #define CP_ACP    0

 #define CP_OEMCP  1

+#define CP_UTF8   65001

 

 typedef enum tagSTREAM_SEEK

 {

diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
old mode 100755
new mode 100644
index 611bbd8..f004889
--- a/CPP/Common/NewHandler.cpp
+++ b/CPP/Common/NewHandler.cpp
@@ -11,6 +11,32 @@
 #ifndef DEBUG_MEMORY_LEAK

 

 #ifdef _WIN32

+

+/*

+void * my_new(size_t size)

+{

+  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);

+  void *p = ::malloc(size);

+  if (p == 0)

+    throw CNewException();

+  return p;

+}

+

+void my_delete(void *p) throw()

+{

+  // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);

+  ::free(p);

+}

+

+void * my_Realloc(void *p, size_t newSize, size_t oldSize)

+{

+  void *newBuf = my_new(newSize);

+  memcpy(newBuf, p, oldSize);

+  my_delete(p);

+  return newBuf;

+}

+*/

+

 void *

 #ifdef _MSC_VER

 __cdecl

@@ -30,18 +56,42 @@
 #endif

 operator delete(void *p) throw()

 {

-  /*

-  if (p == 0)

-    return;

-  ::HeapFree(::GetProcessHeap(), 0, p);

-  */

+  // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);

   ::free(p);

 }

+

+/*

+void *

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator new[](size_t size)

+{

+  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);

+  void *p = ::malloc(size);

+  if (p == 0)

+    throw CNewException();

+  return p;

+}

+

+void

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator delete[](void *p) throw()

+{

+  // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);

+  ::free(p);

+}

+*/

+

 #endif

 

 #else

 

-#pragma init_seg(lib)

+#include <stdio.h>

+

+// #pragma init_seg(lib)

 const int kDebugSize = 1000000;

 static void *a[kDebugSize];

 static int index = 0;

@@ -51,10 +101,6 @@
 {

   numAllocs++;

   void *p = HeapAlloc(GetProcessHeap(), 0, size);

-  if (index == 40)

-  {

-    int t = 1;

-  }

   if (index < kDebugSize)

   {

     a[index] = p;

diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
old mode 100755
new mode 100644
index 6f710cd..d1f4a14
--- a/CPP/Common/NewHandler.h
+++ b/CPP/Common/NewHandler.h
@@ -1,16 +1,68 @@
 // Common/NewHandler.h

 

-#ifndef __COMMON_NEWHANDLER_H

-#define __COMMON_NEWHANDLER_H

+#ifndef __COMMON_NEW_HANDLER_H

+#define __COMMON_NEW_HANDLER_H

+

+/*

+This file must be included before any code that uses operators "delete" or "new".

+Also you must compile and link "NewHandler.cpp", if you use MSVC 6.0.

+The operator "new" in MSVC 6.0 doesn't throw exception "bad_alloc".

+So we define another version of operator "new" that throws "CNewException" on failure.

+

+If you use compiler that throws exception in "new" operator (GCC or new version of MSVC),

+you can compile without "NewHandler.cpp". So standard exception "bad_alloc" will be used.

+

+It's still allowed to use redefined version of operator "new" from "NewHandler.cpp"

+with any compiler. 7-Zip's code can work with "bad_alloc" and "CNewException" exceptions.

+But if you use some additional code (outside of 7-Zip's code), you must check

+that redefined version of operator "new" (that throws CNewException) is not

+problem for your code.

+

+Also we declare delete(void *p) throw() that creates smaller code.

+*/

+

 

 class CNewException {};

 

+#ifdef WIN32

+// We can compile my_new and my_delete with _fastcall

+/*

+void * my_new(size_t size);

+void my_delete(void *p) throw();

+// void * my_Realloc(void *p, size_t newSize, size_t oldSize);

+*/

+#endif

+

 #ifdef _WIN32

+

+void *

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator new(size_t size);

+

 void

 #ifdef _MSC_VER

 __cdecl

 #endif

 operator delete(void *p) throw();

+

 #endif

 

+/*

+#ifdef _WIN32

+void *

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator new[](size_t size);

+

+void

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator delete[](void *p) throw();

+#endif

+*/

+

 #endif

diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp
new file mode 100644
index 0000000..eaab65c
--- /dev/null
+++ b/CPP/Common/Sha256Reg.cpp
@@ -0,0 +1,52 @@
+// Sha256Reg.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/Sha256.h"

+

+#include "../Common/MyCom.h"

+

+#include "../7zip/ICoder.h"

+#include "../7zip/Common/RegisterCodec.h"

+

+class CSha256Hasher:

+  public IHasher,

+  public CMyUnknownImp

+{

+  CSha256 _sha;

+public:

+  CSha256Hasher() { Init(); };

+

+  MY_UNKNOWN_IMP

+

+  STDMETHOD_(void, Init)();

+  STDMETHOD_(void, Update)(const void *data, UInt32 size);

+  STDMETHOD_(void, Final)(Byte *digest);

+  STDMETHOD_(UInt32, GetDigestSize)();

+};

+

+STDMETHODIMP_(void) CSha256Hasher::Init()

+{

+  Sha256_Init(&_sha);

+}

+

+STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size)

+{

+  Sha256_Update(&_sha, (const Byte *)data, size);

+}

+

+STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest)

+{

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

diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h
old mode 100755
new mode 100644
index 9b43572..3f1890a
--- a/CPP/Common/StdAfx.h
+++ b/CPP/Common/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-// #include "MyWindows.h"

-#include "NewHandler.h"

+#include "Common.h"

 

 #endif

diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
old mode 100755
new mode 100644
index 442191e..0799c2c
--- a/CPP/Common/StdInStream.cpp
+++ b/CPP/Common/StdInStream.cpp
@@ -8,12 +8,6 @@
 #include "StringConvert.h"

 #include "UTFConvert.h"

 

-#ifdef _MSC_VER

-// "was declared deprecated" disabling

-#pragma warning(disable : 4996 )

-#endif

-

-static const char kIllegalChar = '\0';

 static const char kNewLineChar = '\n';

 

 static const char *kEOFMessage = "Unexpected end of input stream";

@@ -26,7 +20,7 @@
 

 CStdInStream g_StdIn(stdin);

 

-bool CStdInStream::Open(LPCTSTR fileName)

+bool CStdInStream::Open(LPCTSTR fileName) throw()

 {

   Close();

   _stream = _tfopen(fileName, kFileOpenMode);

@@ -34,7 +28,7 @@
   return _streamIsOpen;

 }

 

-bool CStdInStream::Close()

+bool CStdInStream::Close() throw()

 {

   if (!_streamIsOpen)

     return true;

@@ -42,11 +36,6 @@
   return !_streamIsOpen;

 }

 

-CStdInStream::~CStdInStream()

-{

-  Close();

-}

-

 AString CStdInStream::ScanStringUntilNewLine(bool allowEOF)

 {

   AString s;

@@ -59,8 +48,8 @@
         break;

       throw kEOFMessage;

     }

-    char c = char(intChar);

-    if (c == kIllegalChar)

+    char c = (char)intChar;

+    if (c == 0)

       throw kIllegalCharMessage;

     if (c == kNewLineChar)

       break;

@@ -88,10 +77,10 @@
   resultString.Empty();

   int c;

   while ((c = GetChar()) != EOF)

-    resultString += char(c);

+    resultString += (char)c;

 }

 

-bool CStdInStream::Eof()

+bool CStdInStream::Eof() throw()

 {

   return (feof(_stream) != 0);

 }

@@ -103,5 +92,3 @@
     throw kReadErrorMessage;

   return c;

 }

-

-

diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h
old mode 100755
new mode 100644
index 67ef82b..c017d0a
--- a/CPP/Common/StdInStream.h
+++ b/CPP/Common/StdInStream.h
@@ -1,29 +1,30 @@
 // Common/StdInStream.h

 

-#ifndef __COMMON_STDINSTREAM_H

-#define __COMMON_STDINSTREAM_H

+#ifndef __COMMON_STD_IN_STREAM_H

+#define __COMMON_STD_IN_STREAM_H

 

 #include <stdio.h>

 

 #include "MyString.h"

-#include "Types.h"

+#include "MyTypes.h"

 

 class CStdInStream

 {

-  bool _streamIsOpen;

   FILE *_stream;

+  bool _streamIsOpen;

 public:

-  CStdInStream(): _streamIsOpen(false) {};

-  CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {};

-  ~CStdInStream();

-  bool Open(LPCTSTR fileName);

-  bool Close();

+  CStdInStream(): _stream(0), _streamIsOpen(false) {};

+  CStdInStream(FILE *stream): _stream(stream), _streamIsOpen(false) {};

+  ~CStdInStream() { Close(); }

+

+  bool Open(LPCTSTR fileName) throw();

+  bool Close() throw();

 

   AString ScanStringUntilNewLine(bool allowEOF = false);

   void ReadToString(AString &resultString);

   UString ScanUStringUntilNewLine();

 

-  bool Eof();

+  bool Eof() throw();

   int GetChar();

 };

 

diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
old mode 100755
new mode 100644
index f7ec2a6..eec83bb
--- a/CPP/Common/StdOutStream.cpp
+++ b/CPP/Common/StdOutStream.cpp
@@ -9,21 +9,16 @@
 #include "StringConvert.h"

 #include "UTFConvert.h"

 

-#ifdef _MSC_VER

-// "was declared deprecated" disabling

-#pragma warning(disable : 4996 )

-#endif

-

 static const char kNewLineChar =  '\n';

 

 static const char *kFileOpenMode = "wt";

 

 extern int g_CodePage;

 

-CStdOutStream  g_StdOut(stdout);

-CStdOutStream  g_StdErr(stderr);

+CStdOutStream g_StdOut(stdout);

+CStdOutStream g_StdErr(stderr);

 

-bool CStdOutStream::Open(const char *fileName)

+bool CStdOutStream::Open(const char *fileName) throw()

 {

   Close();

   _stream = fopen(fileName, kFileOpenMode);

@@ -31,7 +26,7 @@
   return _streamIsOpen;

 }

 

-bool CStdOutStream::Close()

+bool CStdOutStream::Close() throw()

 {

   if (!_streamIsOpen)

     return true;

@@ -42,33 +37,16 @@
   return true;

 }

 

-bool CStdOutStream::Flush()

+bool CStdOutStream::Flush() throw()

 {

   return (fflush(_stream) == 0);

 }

 

-CStdOutStream::~CStdOutStream ()

-{

-  Close();

-}

-

-CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream  &))

-{

-  (*aFunction)(*this);

-  return *this;

-}

-

-CStdOutStream & endl(CStdOutStream & outStream)

+CStdOutStream & endl(CStdOutStream & outStream) throw()

 {

   return outStream << kNewLineChar;

 }

 

-CStdOutStream & CStdOutStream::operator<<(const char *s)

-{

-  fputs(s, _stream);

-  return *this;

-}

-

 CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)

 {

   int codePage = g_CodePage;

@@ -78,27 +56,51 @@
   if (codePage == CP_UTF8)

     ConvertUnicodeToUTF8(s, dest);

   else

-    dest = UnicodeStringToMultiByte(s, (UINT)codePage);

-  *this << (const char *)dest;

-  return *this;

+    UnicodeStringToMultiByte2(dest, s, (UINT)codePage);

+  return operator<<((const char *)dest);

 }

 

-CStdOutStream & CStdOutStream::operator<<(char c)

+void StdOut_Convert_UString_to_AString(const UString &s, AString &temp)

 {

-  fputc(c, _stream);

-  return *this;

+  int codePage = g_CodePage;

+  if (codePage == -1)

+    codePage = CP_OEMCP;

+  if (codePage == CP_UTF8)

+    ConvertUnicodeToUTF8(s, temp);

+  else

+    UnicodeStringToMultiByte2(temp, s, (UINT)codePage);

 }

 

-CStdOutStream & CStdOutStream::operator<<(int number)

+void CStdOutStream::PrintUString(const UString &s, AString &temp)

 {

-  char textString[32];

-  ConvertInt64ToString(number, textString);

-  return operator<<(textString);

+  StdOut_Convert_UString_to_AString(s, temp);

+  *this << (const char *)temp;

 }

 

-CStdOutStream & CStdOutStream::operator<<(UInt64 number)

+CStdOutStream & CStdOutStream::operator<<(Int32 number) throw()

 {

-  char textString[32];

-  ConvertUInt64ToString(number, textString);

-  return operator<<(textString);

+  char s[32];

+  ConvertInt64ToString(number, s);

+  return operator<<(s);

+}

+

+CStdOutStream & CStdOutStream::operator<<(Int64 number) throw()

+{

+  char s[32];

+  ConvertInt64ToString(number, s);

+  return operator<<(s);

+}

+

+CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw()

+{

+  char s[16];

+  ConvertUInt32ToString(number, s);

+  return operator<<(s);

+}

+

+CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw()

+{

+  char s[32];

+  ConvertUInt64ToString(number, s);

+  return operator<<(s);

 }

diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
old mode 100755
new mode 100644
index c2fcd9d..4ade958
--- a/CPP/Common/StdOutStream.h
+++ b/CPP/Common/StdOutStream.h
@@ -1,35 +1,62 @@
 // Common/StdOutStream.h

 

-#ifndef __COMMON_STDOUTSTREAM_H

-#define __COMMON_STDOUTSTREAM_H

+#ifndef __COMMON_STD_OUT_STREAM_H

+#define __COMMON_STD_OUT_STREAM_H

 

 #include <stdio.h>

 

-#include "Types.h"

+#include "MyString.h"

+#include "MyTypes.h"

 

 class CStdOutStream

 {

-  bool _streamIsOpen;

   FILE *_stream;

+  bool _streamIsOpen;

 public:

-  CStdOutStream (): _streamIsOpen(false), _stream(0) {};

-  CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {};

-  ~CStdOutStream ();

+  CStdOutStream(): _stream(0), _streamIsOpen(false) {};

+  CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {};

+  ~CStdOutStream() { Close(); }

+

+  // void AttachStdStream(FILE *stream) { _stream  = stream; _streamIsOpen = false; }

+  // bool IsDefined() const { return _stream  != NULL; }

+

   operator FILE *() { return _stream; }

-  bool Open(const char *fileName);

-  bool Close();

-  bool Flush();

-  CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream  &));

-  CStdOutStream & operator<<(const char *string);

-  CStdOutStream & operator<<(const wchar_t *string);

-  CStdOutStream & operator<<(char c);

-  CStdOutStream & operator<<(int number);

-  CStdOutStream & operator<<(UInt64 number);

+  bool Open(const char *fileName) throw();

+  bool Close() throw();

+  bool Flush() throw();

+  

+  CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream  &))

+  {

+    (*func)(*this);

+    return *this;

+  }

+

+  CStdOutStream & operator<<(const char *s) throw()

+  {

+    fputs(s, _stream);

+    return *this;

+  }

+

+  CStdOutStream & operator<<(char c) throw()

+  {

+    fputc(c, _stream);

+    return *this;

+  }

+

+  CStdOutStream & operator<<(Int32 number) throw();

+  CStdOutStream & operator<<(Int64 number) throw();

+  CStdOutStream & operator<<(UInt32 number) throw();

+  CStdOutStream & operator<<(UInt64 number) throw();

+

+  CStdOutStream & operator<<(const wchar_t *s);

+  void PrintUString(const UString &s, AString &temp);

 };

 

-CStdOutStream & endl(CStdOutStream & outStream);

+CStdOutStream & endl(CStdOutStream & outStream) throw();

 

 extern CStdOutStream g_StdOut;

 extern CStdOutStream g_StdErr;

 

+void StdOut_Convert_UString_to_AString(const UString &s, AString &temp);

+

 #endif

diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
old mode 100755
new mode 100644
index 7f9999c..825b16f
--- a/CPP/Common/StringConvert.cpp
+++ b/CPP/Common/StringConvert.cpp
@@ -15,8 +15,8 @@
   if (!srcString.IsEmpty())

   {

     int numChars = MultiByteToWideChar(codePage, 0, srcString,

-      srcString.Length(), resultString.GetBuffer(srcString.Length()),

-      srcString.Length() + 1);

+        srcString.Len(), resultString.GetBuffer(srcString.Len()),

+        srcString.Len() + 1);

     if (numChars == 0)

       throw 282228;

     resultString.ReleaseBuffer(numChars);

@@ -24,15 +24,83 @@
   return resultString;

 }

 

+void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage)

+{

+  dest.Empty();

+  if (!srcString.IsEmpty())

+  {

+    wchar_t *destBuf = dest.GetBuffer(srcString.Len());

+    const char *sp = (const char *)srcString;

+    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];

+      if (c >= 0x80 || c == 0)

+        break;

+      destBuf[i++] = (char)c;

+    }

+    defaultCharWasUsed = false;

+    if (i != s.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;

+    }

+    dest.ReleaseBuffer(i);

+  }

+}

+

+void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage)

+{

+  bool defaultCharWasUsed;

+  UnicodeStringToMultiByte2(dest, srcString, codePage, '_', defaultCharWasUsed);

+}

+

 AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

 {

   AString dest;

   defaultCharWasUsed = false;

   if (!s.IsEmpty())

   {

-    int numRequiredBytes = s.Length() * 2;

+    unsigned numRequiredBytes = s.Len() * 2;

     BOOL defUsed;

-    int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(),

+    int numChars = WideCharToMultiByte(codePage, 0, s, s.Len(),

         dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1,

         &defaultChar, &defUsed);

     defaultCharWasUsed = (defUsed != FALSE);

@@ -53,7 +121,7 @@
 AString SystemStringToOemString(const CSysString &srcString)

 {

   AString result;

-  CharToOem(srcString, result.GetBuffer(srcString.Length() * 2));

+  CharToOem(srcString, result.GetBuffer(srcString.Len() * 2));

   result.ReleaseBuffer();

   return result;

 }

@@ -64,12 +132,12 @@
 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)

 {

   UString resultString;

-  for (int i = 0; i < srcString.Length(); i++)

-    resultString += wchar_t(srcString[i]);

+  for (unsigned i = 0; i < srcString.Len(); i++)

+    resultString += (wchar_t)srcString[i];

   /*

   if (!srcString.IsEmpty())

   {

-    int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 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);

   }

@@ -80,12 +148,12 @@
 AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)

 {

   AString resultString;

-  for (int i = 0; i < srcString.Length(); i++)

-    resultString += char(srcString[i]);

+  for (unsigned i = 0; i < srcString.Len(); i++)

+    resultString += (char)srcString[i];

   /*

   if (!srcString.IsEmpty())

   {

-    int numRequiredBytes = srcString.Length() * 6 + 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);

diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
old mode 100755
new mode 100644
index 1c7a951..d5518eb
--- a/CPP/Common/StringConvert.h
+++ b/CPP/Common/StringConvert.h
@@ -3,15 +3,19 @@
 #ifndef __COMMON_STRING_CONVERT_H

 #define __COMMON_STRING_CONVERT_H

 

-#include "MyWindows.h"

 #include "MyString.h"

-#include "Types.h"

+#include "MyWindows.h"

 

 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);

+

+// 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 &srcString, UINT codePage);

+

 AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);

 AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);

 

-

 inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)

   { return unicodeString; }

 inline const UString& GetUnicodeString(const UString &unicodeString)

diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
old mode 100755
new mode 100644
index 77ce7c5..f9d483e
--- a/CPP/Common/StringToInt.cpp
+++ b/CPP/Common/StringToInt.cpp
@@ -4,87 +4,141 @@
 

 #include "StringToInt.h"

 

-UInt64 ConvertStringToUInt64(const char *s, const char **end)

+static const UInt32 k_UInt32_max = 0xFFFFFFFF;

+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) \

+  uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \

+    if (end) *end = s; \

+    uintType res = 0; \

+    for (;; s++) { \

+      charType c = *s; \

+      if (c < '0' || c > '9') { if (end) *end = s; return res; } \

+      if (res > (k_ ## uintType ## _max) / 10) return 0; \

+      res *= 10; \

+      unsigned v = (c - '0'); \

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

+

+Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()

 {

-  UInt64 result = 0;

-  for (;;)

+  if (end)

+    *end = s;

+  const wchar_t *s2 = s;

+  if (*s == '-')

+    s2++;

+  if (*s2 == 0)

+    return 0;

+  const wchar_t *end2;

+  UInt32 res = ConvertStringToUInt32(s2, &end2);

+  if (*s == '-')

   {

-    char c = *s;

-    if (c < '0' || c > '9')

-    {

-      if (end != NULL)

-        *end = s;

-      return result;

-    }

-    result *= 10;

-    result += (c - '0');

-    s++;

+    if (res > ((UInt32)1 << (32 - 1)))

+      return 0;

   }

+  else if ((res & ((UInt32)1 << (32 - 1))) != 0)

+    return 0;

+  if (end)

+    *end = end2;

+  if (*s == '-')

+    return -(Int32)res;

+  return (Int32)res;

 }

 

-UInt64 ConvertOctStringToUInt64(const char *s, const char **end)

+UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw()

 {

-  UInt64 result = 0;

-  for (;;)

+  if (end)

+    *end = s;

+  UInt32 res = 0;

+  for (;; s++)

   {

     char c = *s;

     if (c < '0' || c > '7')

     {

-      if (end != NULL)

+      if (end)

         *end = s;

-      return result;

+      return res;

     }

-    result <<= 3;

-    result += (c - '0');

-    s++;

+    if ((res & (UInt32)7 << (32 - 3)) != 0)

+      return 0;

+    res <<= 3;

+    res |= (unsigned)(c - '0');

   }

 }

 

-UInt64 ConvertHexStringToUInt64(const char *s, const char **end)

+UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw()

 {

-  UInt64 result = 0;

-  for (;;)

+  if (end)

+    *end = s;

+  UInt64 res = 0;

+  for (;; s++)

   {

     char c = *s;

-    UInt32 v;

+    if (c < '0' || c > '7')

+    {

+      if (end)

+        *end = s;

+      return res;

+    }

+    if ((res & (UInt64)7 << (64 - 3)) != 0)

+      return 0;

+    res <<= 3;

+    res |= (unsigned)(c - '0');

+  }

+}

+

+UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw()

+{

+  if (end)

+    *end = s;

+  UInt32 res = 0;

+  for (;; s++)

+  {

+    char c = *s;

+    unsigned v;

     if (c >= '0' && c <= '9') v = (c - '0');

     else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');

     else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');

     else

     {

-      if (end != NULL)

+      if (end)

         *end = s;

-      return result;

+      return res;

     }

-    result <<= 4;

-    result |= v;

-    s++;

+    if ((res & (UInt32)0xF << (32 - 4)) != 0)

+      return 0;

+    res <<= 4;

+    res |= v;

   }

 }

 

-

-UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end)

+UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw()

 {

-  UInt64 result = 0;

-  for (;;)

+  if (end)

+    *end = s;

+  UInt64 res = 0;

+  for (;; s++)

   {

-    wchar_t c = *s;

-    if (c < '0' || c > '9')

+    char c = *s;

+    unsigned v;

+    if (c >= '0' && c <= '9') v = (c - '0');

+    else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');

+    else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');

+    else

     {

-      if (end != NULL)

+      if (end)

         *end = s;

-      return result;

+      return res;

     }

-    result *= 10;

-    result += (c - '0');

-    s++;

+    if ((res & (UInt64)0xF << (64 - 4)) != 0)

+      return 0;

+    res <<= 4;

+    res |= v;

   }

 }

-

-

-Int64 ConvertStringToInt64(const char *s, const char **end)

-{

-  if (*s == '-')

-    return -(Int64)ConvertStringToUInt64(s + 1, end);

-  return ConvertStringToUInt64(s, end);

-}

diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h
old mode 100755
new mode 100644
index 16a1a4f..140d1ee
--- a/CPP/Common/StringToInt.h
+++ b/CPP/Common/StringToInt.h
@@ -1,18 +1,21 @@
 // Common/StringToInt.h

 

-#ifndef __COMMON_STRINGTOINT_H

-#define __COMMON_STRINGTOINT_H

+#ifndef __COMMON_STRING_TO_INT_H

+#define __COMMON_STRING_TO_INT_H

 

-#include <string.h>

-#include "Types.h"

+#include "MyTypes.h"

 

-UInt64 ConvertStringToUInt64(const char *s, const char **end);

-UInt64 ConvertOctStringToUInt64(const char *s, const char **end);

-UInt64 ConvertHexStringToUInt64(const char *s, const char **end);

-UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end);

+UInt32 ConvertStringToUInt32(const char *s, const char **end) throw();

+UInt64 ConvertStringToUInt64(const char *s, const char **end) throw();

+UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw();

+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw();

 

-Int64 ConvertStringToInt64(const char *s, const char **end);

+Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw();

+

+UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw();

+UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();

+

+UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();

+UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();

 

 #endif

-

-

diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
new file mode 100644
index 0000000..a77e770
--- /dev/null
+++ b/CPP/Common/TextConfig.cpp
@@ -0,0 +1,124 @@
+// Common/TextConfig.cpp

+

+#include "StdAfx.h"

+

+#include "TextConfig.h"

+#include "UTFConvert.h"

+

+static inline bool IsDelimitChar(char c)

+{

+  return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t');

+}

+    

+static AString GetIDString(const char *s, unsigned &finishPos)

+{

+  AString result;

+  for (finishPos = 0; ; finishPos++)

+  {

+    char c = s[finishPos];

+    if (IsDelimitChar(c) || c == '=')

+      break;

+    result += c;

+  }

+  return result;

+}

+

+static bool WaitNextLine(const AString &s, unsigned &pos)

+{

+  for (; pos < s.Len(); pos++)

+    if (s[pos] == 0x0A)

+      return true;

+  return false;

+}

+

+static bool SkipSpaces(const AString &s, unsigned &pos)

+{

+  for (; pos < s.Len(); pos++)

+  {

+    char c = s[pos];

+    if (!IsDelimitChar(c))

+    {

+      if (c != ';')

+        return true;

+      if (!WaitNextLine(s, pos))

+        return false;

+    }

+  }

+  return false;

+}

+

+bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)

+{

+  pairs.Clear();

+  unsigned pos = 0;

+

+  /////////////////////

+  // read strings

+

+  for (;;)

+  {

+    if (!SkipSpaces(s, pos))

+      break;

+    CTextConfigPair pair;

+    unsigned finishPos;

+    AString temp = GetIDString(((const char *)s) + pos, finishPos);

+    if (!ConvertUTF8ToUnicode(temp, pair.ID))

+      return false;

+    if (finishPos == 0)

+      return false;

+    pos += finishPos;

+    if (!SkipSpaces(s, pos))

+      return false;

+    if (s[pos] != '=')

+      return false;

+    pos++;

+    if (!SkipSpaces(s, pos))

+      return false;

+    if (s[pos] != '\"')

+      return false;

+    pos++;

+    AString message;

+    for (;;)

+    {

+      if (pos >= s.Len())

+        return false;

+      char c = s[pos++];

+      if (c == '\"')

+        break;

+      if (c == '\\')

+      {

+        char c = s[pos++];

+        switch(c)

+        {

+          case 'n': message += '\n'; break;

+          case 't': message += '\t'; break;

+          case '\\': message += '\\'; break;

+          case '\"': message += '\"'; break;

+          default: message += '\\'; message += c; break;

+        }

+      }

+      else

+        message += c;

+    }

+    if (!ConvertUTF8ToUnicode(message, pair.String))

+      return false;

+    pairs.Add(pair);

+  }

+  return true;

+}

+

+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw()

+{

+  FOR_VECTOR (i, pairs)

+    if (pairs[i].ID == id)

+      return i;

+  return -1;

+}

+

+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id)

+{

+  int index = FindTextConfigItem(pairs, id);

+  if (index < 0)

+    return UString();

+  return pairs[index].String;

+}

diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h
new file mode 100644
index 0000000..9281fcf
--- /dev/null
+++ b/CPP/Common/TextConfig.h
@@ -0,0 +1,21 @@
+// Common/TextConfig.h

+

+#ifndef __COMMON_TEXT_CONFIG_H

+#define __COMMON_TEXT_CONFIG_H

+

+#include "MyString.h"

+

+struct CTextConfigPair

+{

+  UString ID;

+  UString String;

+};

+

+bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);

+

+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw();

+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id);

+

+#endif

+

+

diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h
deleted file mode 100755
index fd00237..0000000
--- a/CPP/Common/Types.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// Common/Types.h

-

-#ifndef __COMMON_TYPES_H

-#define __COMMON_TYPES_H

-

-#include "../../C/Types.h"

-

-typedef int HRes;

-

-#endif

-

diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
old mode 100755
new mode 100644
index d3935b1..0d3ff68
--- a/CPP/Common/UTFConvert.cpp
+++ b/CPP/Common/UTFConvert.cpp
@@ -2,18 +2,53 @@
 

 #include "StdAfx.h"

 

+#include "MyTypes.h"

 #include "UTFConvert.h"

-#include "Types.h"

 

 static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

 

-static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen)

+bool CheckUTF8(const char *src) throw()

+{

+  for (;;)

+  {

+    Byte c;

+    unsigned numAdds;

+    c = *src++;

+    if (c == 0)

+      return true;

+

+    if (c < 0x80)

+      continue;

+    if (c < 0xC0)

+      return false;

+    for (numAdds = 1; numAdds < 5; numAdds++)

+      if (c < kUtf8Limits[numAdds])

+        break;

+    UInt32 value = (c - kUtf8Limits[numAdds - 1]);

+

+    do

+    {

+      Byte c2 = *src++;

+      if (c2 < 0x80 || c2 >= 0xC0)

+        return false;

+      value <<= 6;

+      value |= (c2 - 0x80);

+    }

+    while (--numAdds);

+    

+    if (value >= 0x110000)

+      return false;

+  }

+}

+

+

+static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) throw()

 {

   size_t destPos = 0, srcPos = 0;

   for (;;)

   {

     Byte c;

-    int numAdds;

+    unsigned numAdds;

     if (srcPos == srcLen)

     {

       *destLen = destPos;

@@ -46,7 +81,7 @@
       value <<= 6;

       value |= (c2 - 0x80);

     }

-    while (--numAdds != 0);

+    while (--numAdds);

     

     if (value < 0x10000)

     {

@@ -124,11 +159,9 @@
 {

   dest.Empty();

   size_t destLen = 0;

-  Utf8_To_Utf16(NULL, &destLen, src, src.Length());

-  wchar_t *p = dest.GetBuffer((int)destLen);

-  Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length());

-  p[destLen] = 0;

-  dest.ReleaseBuffer();

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

 }

 

@@ -136,10 +169,8 @@
 {

   dest.Empty();

   size_t destLen = 0;

-  Utf16_To_Utf8(NULL, &destLen, src, src.Length());

-  char *p = dest.GetBuffer((int)destLen);

-  Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length());

-  p[destLen] = 0;

-  dest.ReleaseBuffer();

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

 }

diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
old mode 100755
new mode 100644
index d553101..601b674
--- a/CPP/Common/UTFConvert.h
+++ b/CPP/Common/UTFConvert.h
@@ -1,10 +1,11 @@
 // Common/UTFConvert.h

 

-#ifndef __COMMON_UTFCONVERT_H

-#define __COMMON_UTFCONVERT_H

+#ifndef __COMMON_UTF_CONVERT_H

+#define __COMMON_UTF_CONVERT_H

 

 #include "MyString.h"

 

+bool CheckUTF8(const char *src) throw();

 bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);

 bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);

 

diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
old mode 100755
new mode 100644
index 024d7a5..a7f47c3
--- a/CPP/Common/Wildcard.cpp
+++ b/CPP/Common/Wildcard.cpp
@@ -2,8 +2,6 @@
 

 #include "StdAfx.h"

 

-#include "../../C/Types.h"

-

 #include "Wildcard.h"

 

 bool g_CaseSensitive =

@@ -13,38 +11,44 @@
     true;

   #endif

 

-static const wchar_t kAnyCharsChar = L'*';

-static const wchar_t kAnyCharChar = L'?';

 

-#ifdef _WIN32

-static const wchar_t kDirDelimiter1 = L'\\';

-#endif

-static const wchar_t kDirDelimiter2 = L'/';

-

-static const UString kWildCardCharSet = L"?*";

-

-static const UString kIllegalWildCardFileNameChars=

-  L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"

-  L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"

-  L"\"/:<>\\|";

-

-

-static inline bool IsCharDirLimiter(wchar_t c)

-{

-  return (

-    #ifdef _WIN32

-    c == kDirDelimiter1 ||

-    #endif

-    c == kDirDelimiter2);

-}

-

-int CompareFileNames(const UString &s1, const UString &s2)

+bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)

 {

   if (g_CaseSensitive)

-    return s1.Compare(s2);

-  return s1.CompareNoCase(s2);

+  {

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

+  }

 }

 

+int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW

+{

+  if (g_CaseSensitive)

+    return wcscmp(s1, s2);

+  return MyStringCompareNoCase(s1, s2);

+}

+

+#ifndef USE_UNICODE_FSTRING

+int CompareFileNames(const char *s1, const char *s2)

+{

+  if (g_CaseSensitive)

+    return wcscmp(fs2us(s1), fs2us(s2));

+  return MyStringCompareNoCase(fs2us(s1), fs2us(s2));

+}

+#endif

+

 // -----------------------------------------

 // this function compares name with mask

 // ? - any char

@@ -58,7 +62,7 @@
     wchar_t c = *name;

     if (m == 0)

       return (c == 0);

-    if (m == kAnyCharsChar)

+    if (m == '*')

     {

       if (EnhancedMaskTest(mask + 1, name))

         return true;

@@ -67,7 +71,7 @@
     }

     else

     {

-      if (m == kAnyCharChar)

+      if (m == '?')

       {

         if (c == 0)

           return false;

@@ -87,61 +91,84 @@
 void SplitPathToParts(const UString &path, UStringVector &pathParts)

 {

   pathParts.Clear();

-  UString name;

-  int len = path.Length();

+  unsigned len = path.Len();

   if (len == 0)

     return;

-  for (int i = 0; i < len; i++)

-  {

-    wchar_t c = path[i];

-    if (IsCharDirLimiter(c))

+  UString name;

+  unsigned prev = 0;

+  for (unsigned i = 0; i < len; i++)

+    if (IsCharDirLimiter(path[i]))

     {

+      name.SetFrom(path.Ptr(prev), i - prev);

       pathParts.Add(name);

-      name.Empty();

+      prev = i + 1;

     }

-    else

-      name += c;

-  }

+  name.SetFrom(path.Ptr(prev), len - prev);

   pathParts.Add(name);

 }

 

-void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name)

+void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)

 {

-  int i;

-  for (i = path.Length() - 1; i >= 0; i--)

-    if (IsCharDirLimiter(path[i]))

+  const wchar_t *start = path;

+  const wchar_t *p = start + path.Len();

+  for (; p != start; p--)

+    if (IsCharDirLimiter(*(p - 1)))

       break;

-  dirPrefix = path.Left(i + 1);

-  name = path.Mid(i + 1);

+  dirPrefix.SetFrom(path, (unsigned)(p - start));

+  name = p;

+}

+

+void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)

+{

+  const wchar_t *start = path;

+  const wchar_t *p = start + path.Len();

+  if (p != start)

+  {

+    if (IsCharDirLimiter(*(p - 1)))

+      p--;

+    for (; p != start; p--)

+      if (IsCharDirLimiter(*(p - 1)))

+        break;

+  }

+  dirPrefix.SetFrom(path, (unsigned)(p - start));

+  name = p;

 }

 

 UString ExtractDirPrefixFromPath(const UString &path)

 {

-  int i;

-  for (i = path.Length() - 1; i >= 0; i--)

-    if (IsCharDirLimiter(path[i]))

+  const wchar_t *start = path;

+  const wchar_t *p = start + path.Len();

+  for (; p != start; p--)

+    if (IsCharDirLimiter(*(p - 1)))

       break;

-  return path.Left(i + 1);

+  return path.Left((unsigned)(p - start));

 }

 

 UString ExtractFileNameFromPath(const UString &path)

 {

-  int i;

-  for (i = path.Length() - 1; i >= 0; i--)

-    if (IsCharDirLimiter(path[i]))

+  const wchar_t *start = path;

+  const wchar_t *p = start + path.Len();

+  for (; p != start; p--)

+    if (IsCharDirLimiter(*(p - 1)))

       break;

-  return path.Mid(i + 1);

+  return p;

 }

 

 

-bool CompareWildCardWithName(const UString &mask, const UString &name)

+bool DoesWildcardMatchName(const UString &mask, const UString &name)

 {

   return EnhancedMaskTest(mask, name);

 }

 

-bool DoesNameContainWildCard(const UString &path)

+bool DoesNameContainWildcard(const UString &path)

 {

-  return (path.FindOneOf(kWildCardCharSet) >= 0);

+  for (unsigned i = 0; i < path.Len(); i++)

+  {

+    wchar_t c = path[i];

+    if (c == '*' || c == '?')

+      return true;

+  }

+  return false;

 }

 

 

@@ -151,22 +178,36 @@
 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();

 N = TestNameParts.Size();

 

                            File                          Dir

-ForFile     req   M<=N  [N-M, N)                          -

-         nonreq   M=N   [0, M)                            -

+ForFile     rec   M<=N  [N-M, N)                          -

+!ForDir  nonrec   M=N   [0, M)                            -

  

-ForDir      req   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File

-         nonreq         [0, M)                   same as ForBoth-File

+ForDir      rec   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File

+!ForFile nonrec         [0, M)                   same as ForBoth-File

 

-ForBoth     req   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File

-         nonreq         [0, M)                   same as ForBoth-File

+ForFile     rec   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File

+ForDir   nonrec         [0, M)                   same as ForBoth-File

 

 */

 

+bool CItem::AreAllAllowed() const

+{

+  return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*";

+}

+

 bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const

 {

   if (!isFile && !ForDir)

@@ -176,36 +217,62 @@
     return false;

   int start = 0;

   int finish = 0;

+  

   if (isFile)

   {

-    if (!ForDir && !Recursive && delta !=0)

-      return false;

+    if (!ForDir)

+    {

+      if (Recursive)

+        start = delta;

+      else if (delta !=0)

+        return false;

+    }

     if (!ForFile && delta == 0)

       return false;

-    if (!ForDir && Recursive)

-      start = delta;

   }

+  

   if (Recursive)

   {

     finish = delta;

     if (isFile && !ForFile)

       finish = delta - 1;

   }

+  

   for (int d = start; d <= finish; d++)

   {

-    int i;

+    unsigned i;

     for (i = 0; i < PathParts.Size(); i++)

-      if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))

-        break;

+    {

+      if (WildcardMatching)

+      {

+        if (!DoesWildcardMatchName(PathParts[i], pathParts[i + d]))

+          break;

+      }

+      else

+      {

+        if (CompareFileNames(PathParts[i], pathParts[i + d]) != 0)

+          break;

+      }

+    }

     if (i == PathParts.Size())

       return true;

   }

   return false;

 }

 

+bool CCensorNode::AreAllAllowed() const

+{

+  if (!Name.IsEmpty() ||

+      !SubNodes.IsEmpty() ||

+      !ExcludeItems.IsEmpty() ||

+      IncludeItems.Size() != 1)

+    return false;

+  return IncludeItems.Front().AreAllAllowed();

+}

+

 int CCensorNode::FindSubNode(const UString &name) const

 {

-  for (int i = 0; i < SubNodes.Size(); i++)

+  FOR_VECTOR (i, SubNodes)

     if (CompareFileNames(SubNodes[i].Name, name) == 0)

       return i;

   return -1;

@@ -223,11 +290,19 @@
 {

   if (item.PathParts.Size() <= 1)

   {

+    if (item.PathParts.Size() != 0 && item.WildcardMatching)

+    {

+      if (!DoesNameContainWildcard(item.PathParts.Front()))

+        item.WildcardMatching = false;

+    }

     AddItemSimple(include, item);

     return;

   }

   const UString &front = item.PathParts.Front();

-  if (DoesNameContainWildCard(front))

+  

+  // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name

+  // if (item.Wildcard)

+  if (DoesNameContainWildcard(front))

   {

     AddItemSimple(include, item);

     return;

@@ -239,19 +314,20 @@
   SubNodes[index].AddItem(include, item);

 }

 

-void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)

+void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching)

 {

   CItem item;

   SplitPathToParts(path, item.PathParts);

   item.Recursive = recursive;

   item.ForFile = forFile;

   item.ForDir = forDir;

+  item.WildcardMatching = wildcardMatching;

   AddItem(include, item);

 }

 

 bool CCensorNode::NeedCheckSubDirs() const

 {

-  for (int i = 0; i < IncludeItems.Size(); i++)

+  FOR_VECTOR (i, IncludeItems)

   {

     const CItem &item = IncludeItems[i];

     if (item.Recursive || item.PathParts.Size() > 1)

@@ -264,7 +340,7 @@
 {

   if (IncludeItems.Size() > 0)

     return true;

-  for (int i = 0; i < SubNodes.Size(); i++)

+  FOR_VECTOR (i, SubNodes)

     if (SubNodes[i].AreThereIncludeItems())

       return true;

   return false;

@@ -273,13 +349,13 @@
 bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const

 {

   const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;

-  for (int i = 0; i < items.Size(); i++)

+  FOR_VECTOR (i, items)

     if (items[i].CheckPath(pathParts, isFile))

       return true;

   return false;

 }

 

-bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const

+bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const

 {

   if (CheckPathCurrent(false, pathParts, isFile))

   {

@@ -288,30 +364,45 @@
   }

   include = true;

   bool finded = CheckPathCurrent(true, pathParts, isFile);

-  if (pathParts.Size() == 1)

+  if (pathParts.Size() <= 1)

     return finded;

   int index = FindSubNode(pathParts.Front());

   if (index >= 0)

   {

     UStringVector pathParts2 = pathParts;

     pathParts2.Delete(0);

-    if (SubNodes[index].CheckPath(pathParts2, isFile, include))

+    if (SubNodes[index].CheckPathVect(pathParts2, isFile, include))

       return true;

   }

   return finded;

 }

 

-bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const

+bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const

 {

   UStringVector pathParts;

   SplitPathToParts(path, pathParts);

-  return CheckPath(pathParts, isFile, include);

+  if (CheckPathVect(pathParts, isFile, include))

+  {

+    if (!include || !isAltStream)

+      return true;

+  }

+  if (isAltStream && !pathParts.IsEmpty())

+  {

+    UString &back = pathParts.Back();

+    int pos = back.Find(L':');

+    if (pos > 0)

+    {

+      back.DeleteFrom(pos);

+      return CheckPathVect(pathParts, isFile, include);

+    }

+  }

+  return false;

 }

 

-bool CCensorNode::CheckPath(const UString &path, bool isFile) const

+bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const

 {

   bool include;

-  if (CheckPath(path, isFile, include))

+  if (CheckPath2(isAltStream, path, isFile, include))

     return include;

   return false;

 }

@@ -335,25 +426,25 @@
 }

 */

 

-void CCensorNode::AddItem2(bool include, const UString &path, bool recursive)

+void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching)

 {

   if (path.IsEmpty())

     return;

   bool forFile = true;

   bool forFolder = true;

   UString path2 = path;

-  if (IsCharDirLimiter(path[path.Length() - 1]))

+  if (IsCharDirLimiter(path.Back()))

   {

-    path2.Delete(path.Length() - 1);

+    path2.DeleteBack();

     forFile = false;

   }

-  AddItem(include, path2, recursive, forFile, forFolder);

+  AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching);

 }

 

 void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)

 {

   ExcludeItems += fromNodes.ExcludeItems;

-  for (int i = 0; i < fromNodes.SubNodes.Size(); i++)

+  FOR_VECTOR (i, fromNodes.SubNodes)

   {

     const CCensorNode &node = fromNodes.SubNodes[i];

     int subNodeIndex = FindSubNode(node.Name);

@@ -365,13 +456,13 @@
 

 int CCensor::FindPrefix(const UString &prefix) const

 {

-  for (int i = 0; i < Pairs.Size(); i++)

+  FOR_VECTOR (i, Pairs)

     if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)

       return i;

   return -1;

 }

 

-void CCensor::AddItem(bool include, const UString &path, bool recursive)

+void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching)

 {

   UStringVector pathParts;

   if (path.IsEmpty())

@@ -383,40 +474,82 @@
     forFile = false;

     pathParts.DeleteBack();

   }

-  const UString &front = pathParts.Front();

-  bool isAbs = false;

-  if (front.IsEmpty())

-    isAbs = true;

-  else if (front.Length() == 2 && front[1] == L':')

-    isAbs = true;

-  else

-  {

-    for (int i = 0; i < pathParts.Size(); i++)

-    {

-      const UString &part = pathParts[i];

-      if (part == L".." || part == L".")

-      {

-        isAbs = true;

-        break;

-      }

-    }

-  }

-  int numAbsParts = 0;

-  if (isAbs)

-    if (pathParts.Size() > 1)

-      numAbsParts = pathParts.Size() - 1;

-    else

-      numAbsParts = 1;

+  

   UString prefix;

-  for (int i = 0; i < numAbsParts; i++)

+  

+  if (pathMode != k_AbsPath)

   {

     const UString &front = pathParts.Front();

-    if (DoesNameContainWildCard(front))

-      break;

-    prefix += front;

-    prefix += WCHAR_PATH_SEPARATOR;

-    pathParts.Delete(0);

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

+

+    // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name

+    // if (wildcardMatching)

+    for (unsigned i = 0; i < numAbsParts; i++)

+    {

+      {

+        const UString &front = pathParts.Front();

+        if (DoesNameContainWildcard(front))

+          break;

+        prefix += front;

+        prefix += WCHAR_PATH_SEPARATOR;

+      }

+      pathParts.Delete(0);

+    }

   }

+

   int index = FindPrefix(prefix);

   if (index < 0)

     index = Pairs.Add(CPair(prefix));

@@ -426,16 +559,17 @@
   item.ForDir = true;

   item.ForFile = forFile;

   item.Recursive = recursive;

+  item.WildcardMatching = wildcardMatching;

   Pairs[index].Head.AddItem(include, item);

 }

 

-bool CCensor::CheckPath(const UString &path, bool isFile) const

+bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const

 {

   bool finded = false;

-  for (int i = 0; i < Pairs.Size(); i++)

+  FOR_VECTOR (i, Pairs)

   {

     bool include;

-    if (Pairs[i].Head.CheckPath(path, isFile, include))

+    if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))

     {

       if (!include)

         return false;

@@ -447,16 +581,35 @@
 

 void CCensor::ExtendExclude()

 {

-  int i;

+  unsigned i;

   for (i = 0; i < Pairs.Size(); i++)

     if (Pairs[i].Prefix.IsEmpty())

       break;

   if (i == Pairs.Size())

     return;

-  int index = i;

+  unsigned index = i;

   for (i = 0; i < Pairs.Size(); i++)

     if (index != i)

       Pairs[i].Head.ExtendExclude(Pairs[index].Head);

 }

 

+void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)

+{

+  FOR_VECTOR(i, CensorPaths)

+  {

+    const CCensorPath &cp = CensorPaths[i];

+    AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching);

+  }

+  CensorPaths.Clear();

+}

+

+void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching)

+{

+  CCensorPath &cp = CensorPaths.AddNew();

+  cp.Path = path;

+  cp.Include = include;

+  cp.Recursive = recursive;

+  cp.WildcardMatching = wildcardMatching;

+}

+

 }

diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
old mode 100755
new mode 100644
index e2a42c8..5db765c
--- a/CPP/Common/Wildcard.h
+++ b/CPP/Common/Wildcard.h
@@ -5,51 +5,90 @@
 

 #include "MyString.h"

 

-int CompareFileNames(const UString &s1, const UString &s2);

+int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;

+#ifndef USE_UNICODE_FSTRING

+  int CompareFileNames(const char *s1, const char *s2);

+#endif

+

+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(const UString &path, UString &dirPrefix, UString &name);

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

+

 UString ExtractDirPrefixFromPath(const UString &path);

 UString ExtractFileNameFromPath(const UString &path);

-bool DoesNameContainWildCard(const UString &path);

-bool CompareWildCardWithName(const UString &mask, const UString &name);

+

+bool DoesNameContainWildcard(const UString &path);

+bool DoesWildcardMatchName(const UString &mask, const UString &name);

 

 namespace NWildcard {

 

+#ifdef _WIN32

+// returns true, if name is like "a:", "c:", ...

+bool IsDriveColonName(const wchar_t *s);

+#endif

+

+

 struct CItem

 {

   UStringVector PathParts;

   bool Recursive;

   bool ForFile;

   bool ForDir;

+  bool WildcardMatching;

+  

+  #ifdef _WIN32

+  bool IsDriveItem() const

+  {

+    return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]);

+  }

+  #endif

+

+  // CItem(): WildcardMatching(true) {}

+

+  bool AreAllAllowed() const;

   bool CheckPath(const UStringVector &pathParts, bool isFile) const;

 };

 

 class CCensorNode

 {

   CCensorNode *Parent;

+  

   bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;

   void AddItemSimple(bool include, CItem &item);

-  bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const;

+  bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;

 public:

   CCensorNode(): Parent(0) { };

   CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };

-  UString Name;

+

+  UString Name; // wildcard is not allowed here

   CObjectVector<CCensorNode> SubNodes;

   CObjectVector<CItem> IncludeItems;

   CObjectVector<CItem> ExcludeItems;

 

+  bool AreAllAllowed() const;

+

   int FindSubNode(const UString &path) const;

 

   void AddItem(bool include, CItem &item);

-  void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir);

-  void AddItem2(bool include, const UString &path, bool recursive);

+  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 CheckPath(const UString &path, bool isFile, bool &include) const;

-  bool CheckPath(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;

@@ -60,21 +99,59 @@
 {

   UString Prefix;

   CCensorNode Head;

+  

   CPair(const UString &prefix): Prefix(prefix) { };

 };

 

+enum ECensorPathMode

+{

+  k_RelatPath,  // absolute prefix as Prefix, remain path in Tree

+  k_FullPath,   // drive prefix as Prefix, remain path in Tree

+  k_AbsPath     // full path in Tree

+};

+

+struct CCensorPath

+{

+  UString Path;

+  bool Include;

+  bool Recursive;

+  bool WildcardMatching;

+

+  CCensorPath():

+    Include(true),

+    Recursive(false),

+    WildcardMatching(true)

+    {}

+};

+

 class CCensor

 {

   int FindPrefix(const UString &prefix) const;

 public:

   CObjectVector<CPair> Pairs;

+

+  CObjectVector<NWildcard::CCensorPath> CensorPaths;

+  

   bool AllAreRelative() const

     { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }

-  void AddItem(bool include, const UString &path, bool recursive);

-  bool CheckPath(const UString &path, bool isFile) const;

+  

+  void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching);

+  bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;

   void ExtendExclude();

+

+  void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);

+  void AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching);

+  void AddPreItem(const UString &path)

+  {

+    AddPreItem(true, path, false, false);

+  }

+  void AddPreItem_Wildcard()

+  {

+    AddPreItem(true, L"*", false, true);

+  }

 };

 

+

 }

 

 #endif

diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp
new file mode 100644
index 0000000..c69d2e3
--- /dev/null
+++ b/CPP/Common/XzCrc64Reg.cpp
@@ -0,0 +1,54 @@
+// XzCrc64Reg.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/CpuArch.h"

+#include "../../C/XzCrc64.h"

+

+#include "../Common/MyCom.h"

+

+#include "../7zip/ICoder.h"

+#include "../7zip/Common/RegisterCodec.h"

+

+class CXzCrc64Hasher:

+  public IHasher,

+  public CMyUnknownImp

+{

+  UInt64 _crc;

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

+};

+

+STDMETHODIMP_(void) CXzCrc64Hasher::Init()

+{

+  _crc = CRC64_INIT_VAL;

+}

+

+STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size)

+{

+  _crc = Crc64Update(_crc, data, size);

+}

+

+STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest)

+{

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

diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
new file mode 100644
index 0000000..8aa6d28
--- /dev/null
+++ b/CPP/Windows/COM.h
@@ -0,0 +1,68 @@
+// Windows/COM.h

+

+#ifndef __WINDOWS_COM_H

+#define __WINDOWS_COM_H

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+namespace NCOM {

+

+#ifdef _WIN32

+  

+class CComInitializer

+{

+public:

+  CComInitializer()

+  {

+    #ifdef UNDER_CE

+    CoInitializeEx(NULL, COINIT_MULTITHREADED);

+    #else

+    // it's single thread. Do we need multithread?

+    CoInitialize(NULL);

+    #endif

+  };

+  ~CComInitializer() { CoUninitialize(); };

+};

+

+class CStgMedium

+{

+  STGMEDIUM _object;

+public:

+  bool _mustBeReleased;

+  CStgMedium(): _mustBeReleased(false) {}

+  ~CStgMedium() { Free(); }

+  void Free()

+  {

+    if (_mustBeReleased)

+      ReleaseStgMedium(&_object);

+    _mustBeReleased = false;

+  }

+  const STGMEDIUM* operator->() const { return &_object;}

+  STGMEDIUM* operator->() { return &_object;}

+  STGMEDIUM* operator&() { return &_object; }

+};

+

+#endif

+

+//////////////////////////////////

+// GUID <--> String Conversions

+UString GUIDToStringW(REFGUID guid);

+AString GUIDToStringA(REFGUID guid);

+#ifdef UNICODE

+  #define GUIDToString GUIDToStringW

+#else

+  #define GUIDToString GUIDToStringA

+#endif

+

+HRESULT StringToGUIDW(const wchar_t *string, GUID &classID);

+HRESULT StringToGUIDA(const char *string, GUID &classID);

+#ifdef UNICODE

+  #define StringToGUID StringToGUIDW

+#else

+  #define StringToGUID StringToGUIDA

+#endif

+

+}}

+

+#endif

diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp
new file mode 100644
index 0000000..60b5b26
--- /dev/null
+++ b/CPP/Windows/CommonDialog.cpp
@@ -0,0 +1,183 @@
+// Windows/CommonDialog.cpp

+

+#include "StdAfx.h"

+

+#ifdef UNDER_CE

+#include <commdlg.h>

+#endif

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "CommonDialog.h"

+#include "Defs.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+

+#ifndef _UNICODE

+

+class CDoubleZeroStringListA

+{

+  LPTSTR Buf;

+  unsigned Size;

+public:

+  CDoubleZeroStringListA(LPSTR buf, unsigned size): Buf(buf), Size(size) {}

+  bool Add(LPCSTR s) throw();

+  void Finish() { *Buf = 0; }

+};

+

+bool CDoubleZeroStringListA::Add(LPCSTR s) throw()

+{

+  unsigned len = MyStringLen(s) + 1;

+  if (len >= Size)

+    return false;

+  MyStringCopy(Buf, s);

+  Buf += len;

+  Size -= len;

+  return true;

+}

+

+#endif

+

+class CDoubleZeroStringListW

+{

+  LPWSTR Buf;

+  unsigned Size;

+public:

+  CDoubleZeroStringListW(LPWSTR buf, unsigned size): Buf(buf), Size(size) {}

+  bool Add(LPCWSTR s) throw();

+  void Finish() { *Buf = 0; }

+};

+

+bool CDoubleZeroStringListW::Add(LPCWSTR s) throw()

+{

+  unsigned len = MyStringLen(s) + 1;

+  if (len >= Size)

+    return false;

+  MyStringCopy(Buf, s);

+  Buf += len;

+  Size -= len;

+  return true;

+}

+

+#define MY__OFN_PROJECT  0x00400000

+#define MY__OFN_SHOW_ALL 0x01000000

+

+/* if (lpstrFilter == NULL && nFilterIndex == 0)

+  MSDN : "the system doesn't show any files",

+  but WinXP-64 shows all files. Why ??? */

+

+/*

+structures

+  OPENFILENAMEW

+  OPENFILENAMEA

+contain additional members:

+#if (_WIN32_WINNT >= 0x0500)

+  void *pvReserved;

+  DWORD dwReserved;

+  DWORD FlagsEx;

+#endif

+

+If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions

+will not work at NT 4.0, if we use sizeof(OPENFILENAME*).

+So we use size of old version of structure. */

+

+#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)

+// || !defined(WINVER)

+  #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)

+  #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)

+#else

+  #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A

+  #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W

+#endif

+

+#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }

+

+bool MyGetOpenFileName(HWND hwnd, LPCWSTR title,

+    LPCWSTR initialDir,

+    LPCWSTR filePath,

+    LPCWSTR filterDescription,

+    LPCWSTR filter,

+    UString &resPath

+    #ifdef UNDER_CE

+    , bool openFolder

+    #endif

+    )

+{

+  const unsigned kBufSize = MAX_PATH * 2;

+  const unsigned kFilterBufSize = MAX_PATH;

+  if (!filter)

+    filter = L"*.*";

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    CHAR buf[kBufSize];

+    MyStringCopy(buf, (const char *)GetSystemString(filePath));

+    // OPENFILENAME_NT4A

+    OPENFILENAMEA p;

+    memset(&p, 0, sizeof(p));

+    p.lStructSize = my_compatib_OPENFILENAMEA_size;

+    p.hwndOwner = hwnd;

+    CHAR filterBuf[kFilterBufSize];

+    {

+      CDoubleZeroStringListA dz(filterBuf, kFilterBufSize);

+      dz.Add(GetSystemString(filterDescription ? filterDescription : filter));

+      dz.Add(GetSystemString(filter));

+      dz.Finish();

+      p.lpstrFilter = filterBuf;

+      p.nFilterIndex = 1;

+    }

+    

+    p.lpstrFile = buf;

+    p.nMaxFile = kBufSize;

+    CONV_U_To_A(p.lpstrInitialDir, initialDir, initialDirA);

+    CONV_U_To_A(p.lpstrTitle, title, titleA);

+    p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;

+

+    bool res = BOOLToBool(::GetOpenFileNameA(&p));

+    resPath = GetUnicodeString(buf);

+    return res;

+  }

+  else

+  #endif

+  {

+    WCHAR buf[kBufSize];

+    MyStringCopy(buf, filePath);

+    // OPENFILENAME_NT4W

+    OPENFILENAMEW p;

+    memset(&p, 0, sizeof(p));

+    p.lStructSize = my_compatib_OPENFILENAMEW_size;

+    p.hwndOwner = hwnd;

+    

+    WCHAR filterBuf[kFilterBufSize];

+    {

+      CDoubleZeroStringListW dz(filterBuf, kFilterBufSize);

+      dz.Add(filterDescription ? filterDescription : filter);

+      dz.Add(filter);

+      dz.Finish();

+      p.lpstrFilter = filterBuf;

+      p.nFilterIndex = 1;

+    }

+        

+    p.lpstrFile = buf;

+    p.nMaxFile = kBufSize;

+    p.lpstrInitialDir = initialDir;

+    p.lpstrTitle = title;

+    p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY

+        #ifdef UNDER_CE

+        | (openFolder ? (MY__OFN_PROJECT | MY__OFN_SHOW_ALL) : 0)

+        #endif

+        ;

+

+    bool res = BOOLToBool(::GetOpenFileNameW(&p));

+    resPath = buf;

+    return res;

+  }

+}

+

+}

diff --git a/CPP/Windows/CommonDialog.h b/CPP/Windows/CommonDialog.h
new file mode 100644
index 0000000..2bfec28
--- /dev/null
+++ b/CPP/Windows/CommonDialog.h
@@ -0,0 +1,23 @@
+// Windows/CommonDialog.h

+

+#ifndef __WINDOWS_COMMON_DIALOG_H

+#define __WINDOWS_COMMON_DIALOG_H

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+

+bool MyGetOpenFileName(HWND hwnd, LPCWSTR title,

+    LPCWSTR initialDir,  // can be NULL, so dir prefix in filePath will be used

+    LPCWSTR filePath,    // full path

+    LPCWSTR filterDescription,  // like "All files (*.*)"

+    LPCWSTR filter,             // like "*.exe"

+    UString &resPath

+    #ifdef UNDER_CE

+    , bool openFolder = false

+    #endif

+);

+

+}

+

+#endif

diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp
new file mode 100644
index 0000000..ca102f3
--- /dev/null
+++ b/CPP/Windows/Control/ComboBox.cpp
@@ -0,0 +1,58 @@
+// Windows/Control/ComboBox.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../../Common/StringConvert.h"

+#endif

+

+#include "ComboBox.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NControl {

+

+LRESULT CComboBox::GetLBText(int index, CSysString &s)

+{

+  s.Empty();

+  LRESULT len = GetLBTextLen(index);

+  if (len == CB_ERR)

+    return len;

+  len = GetLBText(index, s.GetBuffer((int)len + 1));

+  s.ReleaseBuffer();

+  return len;

+}

+

+#ifndef _UNICODE

+LRESULT CComboBox::AddString(LPCWSTR s)

+{

+  if (g_IsNT)

+    return SendMessageW(CB_ADDSTRING, 0, (LPARAM)s);

+  return AddString(GetSystemString(s));

+}

+

+LRESULT CComboBox::GetLBText(int index, UString &s)

+{

+  s.Empty();

+  if (g_IsNT)

+  {

+    LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0);

+    if (len == CB_ERR)

+      return len;

+    len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1));

+    s.ReleaseBuffer();

+    return len;

+  }

+  AString sa;

+  LRESULT len = GetLBText(index, sa);

+  if (len == CB_ERR)

+    return len;

+  s = GetUnicodeString(sa);

+  return s.Len();

+}

+#endif

+

+}}

diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h
new file mode 100644
index 0000000..25e1730
--- /dev/null
+++ b/CPP/Windows/Control/ComboBox.h
@@ -0,0 +1,63 @@
+// Windows/Control/ComboBox.h

+

+#ifndef __WINDOWS_CONTROL_COMBOBOX_H

+#define __WINDOWS_CONTROL_COMBOBOX_H

+

+#include <commctrl.h>

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CComboBox: public CWindow

+{

+public:

+  void ResetContent() { SendMessage(CB_RESETCONTENT, 0, 0); }

+  LRESULT AddString(LPCTSTR s) { return SendMessage(CB_ADDSTRING, 0, (LPARAM)s); }

+  #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 GetLBTextLen(int index) { return SendMessage(CB_GETLBTEXTLEN, index, 0); }

+  LRESULT GetLBText(int index, LPTSTR s) { return SendMessage(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 GetItemData_of_CurSel() { return GetItemData(GetCurSel()); }

+

+  void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0);  }

+};

+

+#ifndef UNDER_CE

+

+class CComboBoxEx: public CComboBox

+{

+public:

+  bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMessage(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); }

+  #ifndef _UNICODE

+  LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMessage(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); }

+};

+

+#endif

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h
new file mode 100644
index 0000000..00c5df7
--- /dev/null
+++ b/CPP/Windows/Control/CommandBar.h
@@ -0,0 +1,48 @@
+// Windows/Control/CommandBar.h

+  

+#ifndef __WINDOWS_CONTROL_COMMANDBAR_H

+#define __WINDOWS_CONTROL_COMMANDBAR_H

+

+#ifdef UNDER_CE

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CCommandBar: public NWindows::CWindow

+{

+public:

+  bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar)

+  {

+    _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar);

+    return (_window != NULL);

+  }

+  

+  // 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 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); }

+  bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); }

+  HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); }

+  int Height() { return CommandBar_Height(_window); }

+  HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); }

+  bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); }

+  bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); }

+  bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); }

+  

+

+  // CE 4.0

+  void AlignAdornments() { CommandBar_AlignAdornments(_window); }

+};

+

+}}

+

+#endif

+

+#endif

diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
new file mode 100644
index 0000000..c8a09ed
--- /dev/null
+++ b/CPP/Windows/Control/Dialog.cpp
@@ -0,0 +1,250 @@
+// Windows/Control/Dialog.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../../Common/StringConvert.h"

+#endif

+

+#include "Dialog.h"

+

+extern HINSTANCE g_hInstance;

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NControl {

+

+static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)

+{

+  CWindow tempDialog(dialogHWND);

+  if (message == WM_INITDIALOG)

+    tempDialog.SetUserDataLongPtr(lParam);

+  CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());

+  if (dialog == NULL)

+    return FALSE;

+  if (message == WM_INITDIALOG)

+    dialog->Attach(dialogHWND);

+  try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }

+  catch(...) { return TRUE; }

+}

+

+bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  switch (message)

+  {

+    case WM_INITDIALOG: return OnInit();

+    case WM_COMMAND: return OnCommand(wParam, lParam);

+    case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam);

+    case WM_TIMER: return OnTimer(wParam, lParam);

+    case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam));

+    case WM_HELP: OnHelp(); return true;

+    /*

+        OnHelp(

+          #ifdef UNDER_CE

+          (void *)

+          #else

+          (LPHELPINFO)

+          #endif

+          lParam);

+        return true;

+    */

+    default: return false;

+  }

+}

+

+bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam)

+{

+  return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);

+}

+

+bool CDialog::OnCommand(int code, int itemID, LPARAM lParam)

+{

+  if (code == BN_CLICKED)

+    return OnButtonClicked(itemID, (HWND)lParam);

+  return false;

+}

+

+bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)

+{

+  switch (buttonID)

+  {

+    case IDOK: OnOK(); break;

+    case IDCANCEL: OnCancel(); break;

+    case IDHELP: OnHelp(); break;

+    default: return false;

+  }

+  return true;

+}

+

+static bool GetWorkAreaRect(RECT *rect)

+{

+  // use another function for multi-monitor.

+  return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0));

+}

+

+bool IsDialogSizeOK(int xSize, int ySize)

+{

+  // it returns for system font. Real font uses another values

+  LONG v = GetDialogBaseUnits();

+  int x = LOWORD(v);

+  int y = HIWORD(v);

+

+  RECT rect;

+  GetWorkAreaRect(&rect);

+  int wx = RECT_SIZE_X(rect);

+  int wy = RECT_SIZE_Y(rect);

+  return

+    xSize / 4 * x <= wx &&

+    ySize / 8 * y <= wy;

+}

+

+bool CDialog::GetMargins(int margin, int &x, int &y)

+{

+  x = margin;

+  y = margin;

+  RECT rect;

+  rect.left = 0;

+  rect.top = 0;

+  rect.right = margin;

+  rect.bottom = margin;

+  if (!MapRect(&rect))

+    return false;

+  x = rect.right - rect.left;

+  y = rect.bottom - rect.top;

+  return true;

+}

+

+int CDialog::Units_To_Pixels_X(int units)

+{

+  RECT rect;

+  rect.left = 0;

+  rect.top = 0;

+  rect.right = units;

+  rect.bottom = units;

+  if (!MapRect(&rect))

+    return units * 3 / 2;

+  return rect.right - rect.left;

+}

+

+bool CDialog::GetItemSizes(int id, int &x, int &y)

+{

+  RECT rect;

+  if (!::GetWindowRect(GetItem(id), &rect))

+    return false;

+  x = RECT_SIZE_X(rect);

+  y = RECT_SIZE_Y(rect);

+  return true;

+}

+

+void CDialog::GetClientRectOfItem(int id, RECT &rect)

+{

+  ::GetWindowRect(GetItem(id), &rect);

+  ScreenToClient(&rect);

+}

+

+bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint)

+{

+  return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint)));

+}

+

+void CDialog::NormalizeSize(bool fullNormalize)

+{

+  RECT workRect;

+  GetWorkAreaRect(&workRect);

+  int xSize = RECT_SIZE_X(workRect);

+  int ySize = RECT_SIZE_Y(workRect);

+  RECT rect;

+  GetWindowRect(&rect);

+  int xSize2 = RECT_SIZE_X(rect);

+  int ySize2 = RECT_SIZE_Y(rect);

+  bool needMove = (xSize2 > xSize || ySize2 > ySize);

+  if (xSize2 > xSize || (needMove && fullNormalize))

+  {

+    rect.left = workRect.left;

+    rect.right = workRect.right;

+    xSize2 = xSize;

+  }

+  if (ySize2 > ySize || (needMove && fullNormalize))

+  {

+    rect.top = workRect.top;

+    rect.bottom = workRect.bottom;

+    ySize2 = ySize;

+  }

+  if (needMove)

+  {

+    if (fullNormalize)

+      Show(SW_SHOWMAXIMIZED);

+    else

+      Move(rect.left, rect.top, xSize2, ySize2, true);

+  }

+}

+

+void CDialog::NormalizePosition()

+{

+  RECT workRect, rect;

+  GetWorkAreaRect(&workRect);

+  GetWindowRect(&rect);

+  if (rect.bottom > workRect.bottom && rect.top > workRect.top)

+    Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true);

+}

+

+bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)

+{

+  HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);

+  if (aHWND == 0)

+    return false;

+  Attach(aHWND);

+  return true;

+}

+

+INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow)

+{

+  return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);

+}

+

+#ifndef _UNICODE

+

+bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow)

+{

+  HWND aHWND;

+  if (g_IsNT)

+    aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);

+  else

+  {

+    AString name;

+    LPCSTR templateNameA;

+    if (IS_INTRESOURCE(templateName))

+      templateNameA = (LPCSTR)templateName;

+    else

+    {

+      name = GetSystemString(templateName);

+      templateNameA = name;

+    }

+    aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);

+  }

+  if (aHWND == 0)

+    return false;

+  Attach(aHWND);

+  return true;

+}

+

+INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow)

+{

+  if (g_IsNT)

+    return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);

+  AString name;

+  LPCSTR templateNameA;

+  if (IS_INTRESOURCE(templateName))

+    templateNameA = (LPCSTR)templateName;

+  else

+  {

+    name = GetSystemString(templateName);

+    templateNameA = name;

+  }

+  return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);

+}

+#endif

+

+}}

diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
new file mode 100644
index 0000000..66530e5
--- /dev/null
+++ b/CPP/Windows/Control/Dialog.h
@@ -0,0 +1,167 @@
+// Windows/Control/Dialog.h

+

+#ifndef __WINDOWS_CONTROL_DIALOG_H

+#define __WINDOWS_CONTROL_DIALOG_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CDialog: public CWindow

+{

+public:

+  CDialog(HWND wnd = NULL): CWindow(wnd){};

+  virtual ~CDialog() {};

+

+  HWND GetItem(int itemID) const

+    { return GetDlgItem(_window, itemID); }

+

+  bool EnableItem(int itemID, bool enable) const

+    { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); }

+

+  bool ShowItem(int itemID, int cmdShow) const

+    { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); }

+

+  bool ShowItem_Bool(int itemID, bool show) const

+    { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); }

+

+  bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); }

+

+  bool SetItemText(int itemID, LPCTSTR s)

+    { return BOOLToBool(SetDlgItemText(_window, itemID, s)); }

+

+  #ifndef _UNICODE

+  bool SetItemText(int itemID, LPCWSTR s)

+  {

+    CWindow window(GetItem(itemID));

+    return window.SetText(s);

+  }

+  #endif

+

+  UINT GetItemText(int itemID, LPTSTR string, int maxCount)

+    { return GetDlgItemText(_window, itemID, string, maxCount); }

+  #ifndef _UNICODE

+  /*

+  bool GetItemText(int itemID, LPWSTR string, int maxCount)

+  {

+    CWindow window(GetItem(itemID));

+    return window.GetText(string, maxCount);

+  }

+  */

+  #endif

+

+  bool SetItemInt(int itemID, UINT value, bool isSigned)

+    { return BOOLToBool(SetDlgItemInt(_window, itemID, value, BoolToBOOL(isSigned))); }

+  bool GetItemInt(int itemID, bool isSigned, UINT &value)

+  {

+    BOOL result;

+    value = GetDlgItemInt(_window, itemID, &result, BoolToBOOL(isSigned));

+    return BOOLToBool(result);

+  }

+

+  HWND GetNextGroupItem(HWND control, bool previous)

+    { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); }

+  HWND GetNextTabItem(HWND control, bool previous)

+    { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); }

+

+  bool MapRect(LPRECT rect)

+    { return BOOLToBool(MapDialogRect(_window, rect)); }

+

+  bool IsMessage(LPMSG message)

+    { return BOOLToBool(IsDialogMessage(_window, message)); }

+

+  LRESULT SendItemMessage(int itemID, UINT message, WPARAM wParam, LPARAM lParam)

+    { return SendDlgItemMessage(_window, itemID, message, wParam, lParam); }

+

+  bool CheckButton(int buttonID, UINT checkState)

+    { return BOOLToBool(CheckDlgButton(_window, buttonID, checkState)); }

+  bool CheckButton(int buttonID, bool checkState)

+    { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); }

+

+  UINT IsButtonChecked(int buttonID) const

+    { return IsDlgButtonChecked(_window, buttonID); }

+  bool IsButtonCheckedBool(int buttonID) const

+    { return (IsButtonChecked(buttonID) == BST_CHECKED); }

+

+  bool CheckRadioButton(int firstButtonID, int lastButtonID, int checkButtonID)

+    { return BOOLToBool(::CheckRadioButton(_window, firstButtonID, lastButtonID, checkButtonID)); }

+

+  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+  virtual bool OnInit() { return true; }

+  virtual bool OnCommand(WPARAM wParam, LPARAM lParam);

+  virtual bool OnCommand(int code, int itemID, LPARAM lParam);

+  virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }

+

+  /*

+  #ifdef UNDER_CE

+  virtual void OnHelp(void *) { OnHelp(); };

+  #else

+  virtual void OnHelp(LPHELPINFO) { OnHelp(); };

+  #endif

+  */

+  virtual void OnHelp() {};

+

+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  virtual void OnOK() {};

+  virtual void OnCancel() {};

+  virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }

+  virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; }

+

+  LONG_PTR SetMsgResult(LONG_PTR newLongPtr )

+    { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }

+  LONG_PTR GetMsgResult() const

+    { return GetLongPtr(DWLP_MSGRESULT); }

+

+  bool GetMargins(int margin, int &x, int &y);

+  int Units_To_Pixels_X(int units);

+  bool GetItemSizes(int id, int &x, int &y);

+  void GetClientRectOfItem(int id, RECT &rect);

+  bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true);

+

+  void NormalizeSize(bool fullNormalize = false);

+  void NormalizePosition();

+};

+

+class CModelessDialog: public CDialog

+{

+public:

+  bool Create(LPCTSTR templateName, HWND parentWindow);

+  bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }

+  #ifndef _UNICODE

+  bool Create(LPCWSTR templateName, HWND parentWindow);

+  #endif

+  virtual void OnOK() { Destroy(); }

+  virtual void OnCancel() { Destroy(); }

+};

+

+class CModalDialog: public CDialog

+{

+public:

+  INT_PTR Create(LPCTSTR templateName, HWND parentWindow);

+  INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }

+  #ifndef _UNICODE

+  INT_PTR Create(LPCWSTR templateName, HWND parentWindow);

+  #endif

+

+  bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }

+  virtual void OnOK() { End(IDOK); }

+  virtual void OnCancel() { End(IDCANCEL); }

+};

+

+class CDialogChildControl: public NWindows::CWindow

+{

+  int m_ID;

+public:

+  void Init(const NWindows::NControl::CDialog &parentDialog, int id)

+  {

+    m_ID = id;

+    Attach(parentDialog.GetItem(id));

+  }

+};

+

+bool IsDialogSizeOK(int xSize, int ySize);

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h
new file mode 100644
index 0000000..40e3899
--- /dev/null
+++ b/CPP/Windows/Control/Edit.h
@@ -0,0 +1,19 @@
+// Windows/Control/Edit.h

+

+#ifndef __WINDOWS_CONTROL_EDIT_H

+#define __WINDOWS_CONTROL_EDIT_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CEdit: public CWindow

+{

+public:

+  void SetPasswordChar(WPARAM c) { SendMessage(EM_SETPASSWORDCHAR, c); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/ImageList.cpp b/CPP/Windows/Control/ImageList.cpp
new file mode 100644
index 0000000..d201c8f
--- /dev/null
+++ b/CPP/Windows/Control/ImageList.cpp
@@ -0,0 +1,10 @@
+// Windows/Control/ImageList.cpp

+

+#include "StdAfx.h"

+

+#include "ImageList.h"

+

+namespace NWindows {

+namespace NControl {

+

+}}

diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h
new file mode 100644
index 0000000..f72ea0d
--- /dev/null
+++ b/CPP/Windows/Control/ImageList.h
@@ -0,0 +1,87 @@
+// Windows/Control/ImageList.h

+

+#ifndef __WINDOWS_CONTROL_IMAGE_LIST_H

+#define __WINDOWS_CONTROL_IMAGE_LIST_H

+

+#include <commctrl.h>

+

+#include "../Defs.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CImageList

+{

+  HIMAGELIST m_Object;

+public:

+  operator HIMAGELIST() const {return m_Object; }

+  CImageList(): m_Object(NULL) {}

+  bool Attach(HIMAGELIST imageList)

+  {

+    if (imageList == NULL)

+      return false;

+    m_Object = imageList;

+    return true;

+  }

+

+  HIMAGELIST Detach()

+  {

+    HIMAGELIST imageList = m_Object;

+    m_Object = NULL;

+    return imageList;

+  }

+  

+  bool Create(int width, int height, UINT flags, int initialNumber, int grow)

+  {

+    HIMAGELIST a = ImageList_Create(width, height, flags,

+      initialNumber, grow);

+    if (a == NULL)

+      return false;

+    return Attach(a);

+  }

+  

+  bool Destroy() // DeleteImageList() in MFC

+  {

+    if (m_Object == NULL)

+      return false;

+    return BOOLToBool(ImageList_Destroy(Detach()));

+  }

+

+  ~CImageList()

+    { Destroy(); }

+

+  int GetImageCount() const

+    { return ImageList_GetImageCount(m_Object); }

+

+  bool GetImageInfo(int index, IMAGEINFO* imageInfo) const

+    { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); }

+

+  int Add(HBITMAP hbmImage, HBITMAP hbmMask = 0)

+    { return ImageList_Add(m_Object, hbmImage, hbmMask); }

+  int AddMasked(HBITMAP hbmImage, COLORREF mask)

+    { return ImageList_AddMasked(m_Object, hbmImage, mask); }

+  int AddIcon(HICON icon)

+    { return ImageList_AddIcon(m_Object, icon); }

+  int Replace(int index, HICON icon)

+    { return ImageList_ReplaceIcon(m_Object, index, icon); }

+

+  // If index is -1, the function removes all images.

+  bool Remove(int index)

+    { return BOOLToBool(ImageList_Remove(m_Object, index)); }

+  bool RemoveAll()

+    { return BOOLToBool(ImageList_RemoveAll(m_Object)); }

+

+  HICON ExtractIcon(int index)

+    { return ImageList_ExtractIcon(NULL, m_Object, index); }

+  HICON GetIcon(int index, UINT flags)

+    { return ImageList_GetIcon(m_Object, index, flags); }

+

+  bool GetIconSize(int &width, int &height) const

+    { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); }

+  bool SetIconSize(int width, int height)

+    { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp
new file mode 100644
index 0000000..fb22f95
--- /dev/null
+++ b/CPP/Windows/Control/ListView.cpp
@@ -0,0 +1,155 @@
+// Windows/Control/ListView.cpp

+

+#include "StdAfx.h"

+

+#include "ListView.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NControl {

+

+bool CListView::CreateEx(DWORD exStyle, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam)

+{

+  return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width,

+      height, parentWindow, idOrHMenu, instance, createParam);

+}

+

+bool CListView::GetItemParam(int index, LPARAM &param) const

+{

+  LVITEM item;

+  item.iItem = index;

+  item.iSubItem = 0;

+  item.mask = LVIF_PARAM;

+  bool aResult = GetItem(&item);

+  param = item.lParam;

+  return aResult;

+}

+

+int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width)

+{

+  LVCOLUMN ci;

+  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;

+  ci.pszText = (LPTSTR)text;

+  ci.iSubItem = columnIndex;

+  ci.cx = width;

+  return InsertColumn(columnIndex, &ci);

+}

+

+int CListView::InsertItem(int index, LPCTSTR text)

+{

+  LVITEM item;

+  item.mask = LVIF_TEXT | LVIF_PARAM;

+  item.iItem = index;

+  item.lParam = index;

+  item.pszText = (LPTSTR)text;

+  item.iSubItem = 0;

+  return InsertItem(&item);

+}

+

+int CListView::SetSubItem(int index, int subIndex, LPCTSTR text)

+{

+  LVITEM item;

+  item.mask = LVIF_TEXT;

+  item.iItem = index;

+  item.pszText = (LPTSTR)text;

+  item.iSubItem = subIndex;

+  return SetItem(&item);

+}

+

+#ifndef _UNICODE

+

+int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width)

+{

+  LVCOLUMNW ci;

+  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;

+  ci.pszText = (LPWSTR)text;

+  ci.iSubItem = columnIndex;

+  ci.cx = width;

+  return InsertColumn(columnIndex, &ci);

+}

+

+int CListView::InsertItem(int index, LPCWSTR text)

+{

+  LVITEMW item;

+  item.mask = LVIF_TEXT | LVIF_PARAM;

+  item.iItem = index;

+  item.lParam = index;

+  item.pszText = (LPWSTR)text;

+  item.iSubItem = 0;

+  return InsertItem(&item);

+}

+

+int CListView::SetSubItem(int index, int subIndex, LPCWSTR text)

+{

+  LVITEMW item;

+  item.mask = LVIF_TEXT;

+  item.iItem = index;

+  item.pszText = (LPWSTR)text;

+  item.iSubItem = subIndex;

+  return SetItem(&item);

+}

+

+#endif

+

+static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

+{

+  CWindow window(hwnd);

+  CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr());

+  if (w == NULL)

+    return 0;

+  return w->OnMessage(message, wParam, lParam);

+}

+

+LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  #ifndef _UNICODE

+  if (g_IsNT)

+    return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);

+  else

+  #endif

+    return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);

+}

+

+void CListView2::SetWindowProc()

+{

+  SetUserDataLongPtr((LONG_PTR)this);

+  #ifndef _UNICODE

+  if (g_IsNT)

+    _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);

+  else

+  #endif

+    _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);

+}

+

+/*

+LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  LRESULT res = CListView2::OnMessage(message, wParam, lParam);

+  if (message == WM_GETDLGCODE)

+  {

+    // when user presses RETURN, windows sends default (first) button command to parent dialog.

+    // we disable this:

+    MSG *msg = (MSG *)lParam;

+    WPARAM key = wParam;

+    bool change = false;

+    if (msg)

+    {

+      if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN)

+        change = true;

+    }

+    else if (wParam == VK_RETURN)

+      change = true;

+    if (change)

+      res |= DLGC_WANTALLKEYS;

+  }

+  return res;

+}

+*/

+  

+}}

diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h
new file mode 100644
index 0000000..6897c81
--- /dev/null
+++ b/CPP/Windows/Control/ListView.h
@@ -0,0 +1,132 @@
+// Windows/Control/ListView.h

+

+#ifndef __WINDOWS_CONTROL_LISTVIEW_H

+#define __WINDOWS_CONTROL_LISTVIEW_H

+

+#include "../Window.h"

+

+#include <commctrl.h>

+

+namespace NWindows {

+namespace NControl {

+

+class CListView: public NWindows::CWindow

+{

+public:

+  bool CreateEx(DWORD exStyle, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam);

+

+  void SetUnicodeFormat()

+  {

+    #ifndef UNDER_CE

+    ListView_SetUnicodeFormat(_window, TRUE);

+    #endif

+  }

+ 

+  bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); }

+  bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); }

+

+  int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }

+  int InsertColumn(int columnIndex, LPCTSTR text, int width);

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

+  int SetSubItem(int index, int subIndex, LPCTSTR text);

+

+  #ifndef _UNICODE

+

+  int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMessage(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(int index, LPCWSTR text);

+  bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMessage(LVM_SETITEMW, 0, (LPARAM)item)); }

+  int SetSubItem(int index, int subIndex, LPCWSTR text);

+

+  #endif

+

+  bool DeleteItem(int itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); }

+

+  UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); }

+  int GetItemCount() const { return ListView_GetItemCount(_window); }

+

+  INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); }

+

+  void SetItemCount(int numItems) { ListView_SetItemCount(_window, numItems); }

+  void SetItemCountEx(int numItems, DWORD flags) {  ListView_SetItemCountEx(_window, numItems, flags); }

+

+  int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); }

+  int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); }

+  int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); }

+  

+  bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); }

+  bool GetItemParam(int itemIndex, LPARAM &param) const;

+  void GetItemText(int itemIndex, int subItemIndex, LPTSTR text, int textSizeMax) const

+    { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax); }

+  bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam)

+    { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); }

+

+  void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); }

+  void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); }

+  void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); }

+  void SelectAll() { SetItemState_Selected(-1); }

+  void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); }

+  UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); }

+  bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; }

+

+  bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const

+    { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); }

+

+  HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType)

+    { return ListView_SetImageList(_window, imageList, imageListType); }

+

+  // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3)

+  DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); }

+  void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); }

+  void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); }

+

+  void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)); }

+  bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); }

+

+  bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); }

+

+  bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); }

+

+  HWND GetEditControl() { return ListView_GetEditControl(_window) ; }

+  HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; }

+

+  bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); }

+  bool RedrawAllItems()

+  {

+    if (GetItemCount() > 0)

+      return RedrawItems(0, GetItemCount() - 1);

+    return true;

+  }

+  bool RedrawItem(int index) { return RedrawItems(index, index); }

+ 

+  int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); }

+  COLORREF GetBkColor() { return ListView_GetBkColor(_window); }

+  bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); }

+  bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); }

+};

+

+class CListView2: public CListView

+{

+  WNDPROC _origWindowProc;

+public:

+  void SetWindowProc();

+  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+};

+

+/*

+class CListView3: public CListView2

+{

+public:

+  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+};

+*/

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h
new file mode 100644
index 0000000..71dc912
--- /dev/null
+++ b/CPP/Windows/Control/ProgressBar.h
@@ -0,0 +1,31 @@
+// Windows/Control/ProgressBar.h

+

+#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H

+#define __WINDOWS_CONTROL_PROGRESSBAR_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CProgressBar: public CWindow

+{

+public:

+  LRESULT SetPos(int pos) { return SendMessage(PBM_SETPOS, pos, 0); }

+  LRESULT DeltaPos(int increment) { return SendMessage(PBM_DELTAPOS, increment, 0); }

+  UINT GetPos() { return (UINT)SendMessage(PBM_GETPOS, 0, 0); }

+  LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMessage(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }

+  DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMessage(PBM_SETRANGE32, minValue, maxValue); }

+  int SetStep(int step) { return (int)SendMessage(PBM_SETSTEP, step, 0); }

+  LRESULT StepIt() { return SendMessage(PBM_STEPIT, 0, 0); }

+  INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMessage(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }

+  

+  #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); }

+  #endif

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
new file mode 100644
index 0000000..6d940c8
--- /dev/null
+++ b/CPP/Windows/Control/PropertyPage.cpp
@@ -0,0 +1,143 @@
+// Windows/Control/PropertyPage.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../../Common/StringConvert.h"

+#endif

+

+#include "PropertyPage.h"

+

+extern HINSTANCE g_hInstance;

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NControl {

+

+static INT_PTR APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)

+{

+  CWindow tempDialog(dialogHWND);

+  if (message == WM_INITDIALOG)

+    tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam);

+  CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());

+  if (dialog == NULL)

+    return FALSE;

+  if (message == WM_INITDIALOG)

+    dialog->Attach(dialogHWND);

+  try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }

+  catch(...) { return TRUE; }

+}

+

+bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam)

+{

+  switch (lParam->code)

+  {

+    case PSN_APPLY: SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); break;

+    case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); break;

+    case PSN_SETACTIVE: SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); break;

+    case PSN_RESET: OnReset(LPPSHNOTIFY(lParam)); break;

+    case PSN_HELP: OnNotifyHelp(LPPSHNOTIFY(lParam)); break;

+    default: return false;

+  }

+  return true;

+}

+

+INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title)

+{

+  #ifndef _UNICODE

+  AStringVector titles;

+  #endif

+  #ifndef _UNICODE

+  CRecordVector<PROPSHEETPAGEA> pagesA;

+  #endif

+  CRecordVector<PROPSHEETPAGEW> pagesW;

+

+  unsigned i;

+  #ifndef _UNICODE

+  for (i = 0; i < pagesInfo.Size(); i++)

+    titles.Add(GetSystemString(pagesInfo[i].Title));

+  #endif

+

+  for (i = 0; i < pagesInfo.Size(); i++)

+  {

+    const CPageInfo &pageInfo = pagesInfo[i];

+    #ifndef _UNICODE

+    {

+      PROPSHEETPAGE page;

+      page.dwSize = sizeof(page);

+      page.dwFlags = PSP_HASHELP;

+      page.hInstance = g_hInstance;

+      page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID);

+      page.pszIcon = NULL;

+      page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure;

+      

+      if (titles[i].IsEmpty())

+        page.pszTitle = NULL;

+      else

+      {

+        page.dwFlags |= PSP_USETITLE;

+        page.pszTitle = titles[i];

+      }

+      page.lParam = (LPARAM)pageInfo.Page;

+      page.pfnCallback = NULL;

+      pagesA.Add(page);

+    }

+    #endif

+    {

+      PROPSHEETPAGEW page;

+      page.dwSize = sizeof(page);

+      page.dwFlags = PSP_HASHELP;

+      page.hInstance = g_hInstance;

+      page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID);

+      page.pszIcon = NULL;

+      page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure;

+      

+      if (pageInfo.Title.IsEmpty())

+        page.pszTitle = NULL;

+      else

+      {

+        page.dwFlags |= PSP_USETITLE;

+        page.pszTitle = pageInfo.Title;

+      }

+      page.lParam = (LPARAM)pageInfo.Page;

+      page.pfnCallback = NULL;

+      pagesW.Add(page);

+    }

+  }

+

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    PROPSHEETHEADER sheet;

+    sheet.dwSize = sizeof(sheet);

+    sheet.dwFlags = PSH_PROPSHEETPAGE;

+    sheet.hwndParent = hwndParent;

+    sheet.hInstance = g_hInstance;

+    AString titleA = GetSystemString(title);

+    sheet.pszCaption = titleA;

+    sheet.nPages = pagesInfo.Size();

+    sheet.nStartPage = 0;

+    sheet.ppsp = &pagesA.Front();

+    sheet.pfnCallback = NULL;

+    return ::PropertySheetA(&sheet);

+  }

+  else

+  #endif

+  {

+    PROPSHEETHEADERW sheet;

+    sheet.dwSize = sizeof(sheet);

+    sheet.dwFlags = PSH_PROPSHEETPAGE;

+    sheet.hwndParent = hwndParent;

+    sheet.hInstance = g_hInstance;

+    sheet.pszCaption = title;

+    sheet.nPages = pagesInfo.Size();

+    sheet.nStartPage = 0;

+    sheet.ppsp = &pagesW.Front();

+    sheet.pfnCallback = NULL;

+    return ::PropertySheetW(&sheet);

+  }

+}

+

+}}

diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h
new file mode 100644
index 0000000..053de09
--- /dev/null
+++ b/CPP/Windows/Control/PropertyPage.h
@@ -0,0 +1,48 @@
+// Windows/Control/PropertyPage.h

+

+#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H

+#define __WINDOWS_CONTROL_PROPERTYPAGE_H

+

+#include <prsht.h>

+

+#include "Dialog.h"

+

+namespace NWindows {

+namespace NControl {

+

+INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam);

+

+class CPropertyPage: public CDialog

+{

+public:

+  CPropertyPage(HWND window = NULL): CDialog(window){};

+  

+  void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); }

+  void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); }

+

+  virtual bool OnNotify(UINT controlID, LPNMHDR lParam);

+

+  virtual bool OnKillActive() { return false; } // false = OK

+  virtual bool OnKillActive(const PSHNOTIFY *) { return OnKillActive(); }

+  virtual LONG OnSetActive() { return false; } // false = OK

+  virtual LONG OnSetActive(const PSHNOTIFY *) { return OnSetActive(); }

+  virtual LONG OnApply() { return PSNRET_NOERROR; }

+  virtual LONG OnApply(const PSHNOTIFY *) { return OnApply(); }

+  virtual void OnNotifyHelp() {}

+  virtual void OnNotifyHelp(const PSHNOTIFY *) { OnNotifyHelp(); }

+  virtual void OnReset() {}

+  virtual void OnReset(const PSHNOTIFY *) { OnReset(); }

+};

+

+struct CPageInfo

+{

+  CPropertyPage *Page;

+  UString Title;

+  UINT ID;

+};

+

+INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndParent, const UString &title);

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h
new file mode 100644
index 0000000..cf47bf4
--- /dev/null
+++ b/CPP/Windows/Control/ReBar.h
@@ -0,0 +1,34 @@
+// Windows/Control/ReBar.h

+  

+#ifndef __WINDOWS_CONTROL_REBAR_H

+#define __WINDOWS_CONTROL_REBAR_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CReBar: public NWindows::CWindow

+{

+public:

+  bool SetBarInfo(LPREBARINFO barInfo)

+    { return LRESULTToBool(SendMessage(RB_SETBARINFO, 0, (LPARAM)barInfo)); }

+  bool InsertBand(int index, LPREBARBANDINFO bandInfo)

+    { return LRESULTToBool(SendMessage(RB_INSERTBAND, index, (LPARAM)bandInfo)); }

+  bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo)

+    { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); }

+  void MaximizeBand(unsigned index, bool ideal)

+    { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); }

+  bool SizeToRect(LPRECT rect)

+    { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); }

+  UINT GetHeight()

+    { return (UINT)SendMessage(RB_GETBARHEIGHT); }

+  UINT GetBandCount()

+    { return (UINT)SendMessage(RB_GETBANDCOUNT); }

+  bool DeleteBand(UINT index)

+    { return LRESULTToBool(SendMessage(RB_DELETEBAND, index)); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h
new file mode 100644
index 0000000..355b9e8
--- /dev/null
+++ b/CPP/Windows/Control/Static.h
@@ -0,0 +1,28 @@
+// Windows/Control/Static.h

+

+#ifndef __WINDOWS_CONTROL_STATIC_H

+#define __WINDOWS_CONTROL_STATIC_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CStatic: public CWindow

+{

+public:

+  HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMessage(STM_SETIMAGE, imageType, (LPARAM)handle); }

+  HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMessage(STM_GETIMAGE, imageType, 0); }

+

+  #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); }

+  #endif

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h
new file mode 100644
index 0000000..9185c42
--- /dev/null
+++ b/CPP/Windows/Control/StatusBar.h
@@ -0,0 +1,42 @@
+// Windows/Control/StatusBar.h

+

+#ifndef __WINDOWS_CONTROL_STATUSBAR_H

+#define __WINDOWS_CONTROL_STATUSBAR_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CStatusBar: public NWindows::CWindow

+{

+public:

+  bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id)

+    { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != 0; }

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

+  bool SetText(unsigned index, LPCTSTR text)

+    { return SetText(index, text, 0); }

+

+  #ifndef _UNICODE

+  bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id)

+    { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != 0; }

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

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

+  void Simple(bool simple)

+    { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 0); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/StdAfx.h b/CPP/Windows/Control/StdAfx.h
new file mode 100644
index 0000000..42a088f
--- /dev/null
+++ b/CPP/Windows/Control/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../Common/Common.h"

+

+#endif

diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h
new file mode 100644
index 0000000..6bc4443
--- /dev/null
+++ b/CPP/Windows/Control/ToolBar.h
@@ -0,0 +1,43 @@
+// Windows/Control/ToolBar.h

+  

+#ifndef __WINDOWS_CONTROL_TOOLBAR_H

+#define __WINDOWS_CONTROL_TOOLBAR_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CToolBar: public NWindows::CWindow

+{

+public:

+  void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); }

+  DWORD GetButtonSize() { return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0, 0); }

+  

+  bool GetMaxSize(LPSIZE size)

+  #ifdef UNDER_CE

+  {

+    // maybe it must be fixed for more than 1 buttons

+    DWORD val = GetButtonSize();

+    size->cx = LOWORD(val);

+    size->cy = HIWORD(val);

+    return true;

+  }

+  #else

+  {

+    return LRESULTToBool(SendMessage(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)); }

+  #ifndef _UNICODE

+  bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); }

+  #endif

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h
new file mode 100644
index 0000000..da1936b
--- /dev/null
+++ b/CPP/Windows/Control/Trackbar.h
@@ -0,0 +1,28 @@
+// Windows/Control/Trackbar.h

+

+#ifndef __WINDOWS_CONTROL_TRACKBAR_H

+#define __WINDOWS_CONTROL_TRACKBAR_H

+

+#include "../Window.h"

+#include "../Defs.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CTrackbar1: public CWindow

+{

+public:

+  void SetRange(int minimum, int maximum, bool redraw = true)

+    { SendMessage(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); }

+  void SetPos(int pos, bool redraw = true)

+    { SendMessage(TBM_SETPOS, BoolToBOOL(redraw), pos); }

+  void SetTicFreq(int freq)

+    { SendMessage(TBM_SETTICFREQ, freq); }

+  

+  int GetPos()

+    { return (int)SendMessage(TBM_GETPOS); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/Control/Window2.cpp b/CPP/Windows/Control/Window2.cpp
new file mode 100644
index 0000000..2588c3a
--- /dev/null
+++ b/CPP/Windows/Control/Window2.cpp
@@ -0,0 +1,200 @@
+// Windows/Control/Window2.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../../Common/StringConvert.h"

+#endif

+

+#include "Window2.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+

+#ifndef _UNICODE

+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);

+#endif

+

+namespace NControl {

+

+#ifdef UNDER_CE

+#define MY_START_WM_CREATE WM_CREATE

+#else

+#define MY_START_WM_CREATE WM_NCCREATE

+#endif

+

+static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, WPARAM wParam, LPARAM lParam)

+{

+  CWindow tempWindow(aHWND);

+  if (message == MY_START_WM_CREATE)

+    tempWindow.SetUserDataLongPtr((LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));

+  CWindow2 *window = (CWindow2 *)(tempWindow.GetUserDataLongPtr());

+  if (window != NULL && message == MY_START_WM_CREATE)

+    window->Attach(aHWND);

+  if (window == 0)

+  {

+    #ifndef _UNICODE

+    if (g_IsNT)

+      return DefWindowProcW(aHWND, message, wParam, lParam);

+    else

+    #endif

+      return DefWindowProc(aHWND, message, wParam, lParam);

+  }

+  return window->OnMessage(message, wParam, lParam);

+}

+

+bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName,

+    DWORD style, int x, int y, int width, int height,

+    HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance)

+{

+  WNDCLASS wc;

+  if (!::GetClassInfo(instance, className, &wc))

+  {

+    // wc.style          = CS_HREDRAW | CS_VREDRAW;

+    wc.style          = 0;

+    wc.lpfnWndProc    = WindowProcedure;

+    wc.cbClsExtra     = 0;

+    wc.cbWndExtra     = 0;

+    wc.hInstance      = instance;

+    wc.hIcon          = NULL;

+    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);

+    wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);

+    wc.lpszMenuName   = NULL;

+    wc.lpszClassName  = className;

+    if (::RegisterClass(&wc) == 0)

+      return false;

+  }

+  return CWindow::CreateEx(exStyle, className, windowName, style,

+      x, y, width, height, parentWindow, idOrHMenu, instance, this);

+}

+

+#ifndef _UNICODE

+

+bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName,

+    DWORD style, int x, int y, int width, int height,

+    HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance)

+{

+  bool needRegister;

+  if (g_IsNT)

+  {

+    WNDCLASSW wc;

+    needRegister = ::GetClassInfoW(instance, className, &wc) == 0;

+  }

+  else

+  {

+    WNDCLASSA windowClassA;

+    AString classNameA;

+    LPCSTR classNameP;

+    if (IS_INTRESOURCE(className))

+      classNameP = (LPCSTR)className;

+    else

+    {

+      classNameA = GetSystemString(className);

+      classNameP = classNameA;

+    }

+    needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0;

+  }

+  if (needRegister)

+  {

+    WNDCLASSW wc;

+    // wc.style          = CS_HREDRAW | CS_VREDRAW;

+    wc.style          = 0;

+    wc.lpfnWndProc    = WindowProcedure;

+    wc.cbClsExtra     = 0;

+    wc.cbWndExtra     = 0;

+    wc.hInstance      = instance;

+    wc.hIcon          = NULL;

+    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);

+    wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);

+    wc.lpszMenuName   = NULL;

+    wc.lpszClassName  = className;

+    if (MyRegisterClass(&wc) == 0)

+      return false;

+  }

+  return CWindow::CreateEx(exStyle, className, windowName, style,

+      x, y, width, height, parentWindow, idOrHMenu, instance, this);

+}

+

+#endif

+

+LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  #ifndef _UNICODE

+  if (g_IsNT)

+    return DefWindowProcW(_window, message, wParam, lParam);

+  else

+  #endif

+    return DefWindowProc(_window, message, wParam, lParam);

+}

+

+LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)

+{

+  LRESULT result;

+  switch (message)

+  {

+    case WM_CREATE:

+      if (!OnCreate((CREATESTRUCT *)lParam))

+        return -1;

+      break;

+    case WM_COMMAND:

+      if (OnCommand(wParam, lParam, result))

+        return result;

+      break;

+    case WM_NOTIFY:

+      if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result))

+        return result;

+      break;

+    case WM_DESTROY:

+      OnDestroy();

+      break;

+    case WM_CLOSE:

+      OnClose();

+      return 0;

+    case WM_SIZE:

+      if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam)))

+        return 0;

+  }

+  return DefProc(message, wParam, lParam);

+}

+

+bool CWindow2::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result)

+{

+  return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result);

+}

+

+bool CWindow2::OnCommand(int /* code */, int /* itemID */, LPARAM /* lParam */, LRESULT & /* result */)

+{

+  return false;

+  // return DefProc(message, wParam, lParam);

+  /*

+  if (code == BN_CLICKED)

+    return OnButtonClicked(itemID, (HWND)lParam);

+  */

+}

+

+/*

+bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND)

+{

+  switch(aButtonID)

+  {

+    case IDOK:

+      OnOK();

+      break;

+    case IDCANCEL:

+      OnCancel();

+      break;

+    case IDHELP:

+      OnHelp();

+      break;

+    default:

+      return false;

+  }

+  return true;

+}

+

+*/

+

+}}

diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h
new file mode 100644
index 0000000..f565daa
--- /dev/null
+++ b/CPP/Windows/Control/Window2.h
@@ -0,0 +1,51 @@
+// Windows/Control/Window2.h

+

+#ifndef __WINDOWS_CONTROL_WINDOW2_H

+#define __WINDOWS_CONTROL_WINDOW2_H

+

+#include "../Window.h"

+

+namespace NWindows {

+namespace NControl {

+

+class CWindow2: public CWindow

+{

+  LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam);

+public:

+  CWindow2(HWND newWindow = NULL): CWindow(newWindow){};

+  virtual ~CWindow2() {};

+

+  bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName,

+      DWORD style, int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance);

+

+  #ifndef _UNICODE

+  bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName,

+      DWORD style, int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance);

+  #endif

+

+  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);

+  virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; }

+  // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam);

+  virtual bool OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result);

+  virtual bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result);

+  virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }

+  virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; }

+  virtual void OnDestroy() { PostQuitMessage(0); }

+  virtual void OnClose() { Destroy(); }

+  /*

+  virtual LRESULT  OnHelp(LPHELPINFO helpInfo) { OnHelp(); };

+  virtual LRESULT  OnHelp() {};

+  virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);

+  virtual void OnOK() {};

+  virtual void OnCancel() {};

+  */

+

+  LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }

+  LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
old mode 100755
new mode 100644
index 6aaedb0..5485ba3
--- a/CPP/Windows/DLL.cpp
+++ b/CPP/Windows/DLL.cpp
@@ -2,109 +2,109 @@
 

 #include "StdAfx.h"

 

-#ifndef _UNICODE

-#include "../Common/StringConvert.h"

-#endif

-

 #include "DLL.h"

 

 #ifndef _UNICODE

 extern bool g_IsNT;

 #endif

 

+extern HINSTANCE g_hInstance;

+

 namespace NWindows {

 namespace NDLL {

 

-bool CLibrary::Free()

+bool CLibrary::Free() throw()

 {

   if (_module == 0)

     return true;

-  // MessageBox(0, TEXT(""), TEXT("Free"), 0);

-  // Sleep(5000);

   if (!::FreeLibrary(_module))

     return false;

   _module = 0;

   return true;

 }

 

-bool CLibrary::LoadOperations(HMODULE newModule)

+bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw()

 {

-  if (newModule == NULL)

-    return false;

   if (!Free())

     return false;

-  _module = newModule;

-  return true;

-}

-

-bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags)

-{

-  // MessageBox(0, fileName, TEXT("LoadEx"), 0);

-  return LoadOperations(::LoadLibraryEx(fileName, NULL, flags));

-}

-

-bool CLibrary::Load(LPCTSTR fileName)

-{

-  // MessageBox(0, fileName, TEXT("Load"), 0);

-  // Sleep(5000);

-  // OutputDebugString(fileName);

-  // OutputDebugString(TEXT("\n"));

-  return LoadOperations(::LoadLibrary(fileName));

-}

-

-#ifndef _UNICODE

-static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

-CSysString GetSysPath(LPCWSTR sysPath)

-  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }

-

-bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags)

-{

-  if (g_IsNT)

-    return LoadOperations(::LoadLibraryExW(fileName, NULL, flags));

-  return LoadEx(GetSysPath(fileName), flags);

-}

-bool CLibrary::Load(LPCWSTR fileName)

-{

-  if (g_IsNT)

-    return LoadOperations(::LoadLibraryW(fileName));

-  return Load(GetSysPath(fileName));

-}

-#endif

-

-bool MyGetModuleFileName(HMODULE hModule, CSysString &result)

-{

-  result.Empty();

-  TCHAR fullPath[MAX_PATH + 2];

-  DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1);

-  if (size <= MAX_PATH && size != 0)

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

-    result = fullPath;

-    return true;

+    _module = ::LoadLibraryEx(fs2fas(path), NULL, flags);

+  }

+  else

+  #endif

+  {

+    _module = ::LoadLibraryExW(fs2us(path), NULL, flags);

+  }

+  return (_module != NULL);

+}

+

+bool CLibrary::Load(CFSTR path) throw()

+{

+  if (!Free())

+    return false;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    _module = ::LoadLibrary(fs2fas(path));

+  }

+  else

+  #endif

+  {

+    _module = ::LoadLibraryW(fs2us(path));

+  }

+  return (_module != NULL);

+}

+

+bool MyGetModuleFileName(FString &path)

+{

+  HMODULE hModule = g_hInstance;

+  path.Empty();

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1);

+    if (size <= MAX_PATH && size != 0)

+    {

+      path = fas2fs(s);

+      return true;

+    }

+  }

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1);

+    if (size <= MAX_PATH && size != 0)

+    {

+      path = us2fs(s);

+      return true;

+    }

   }

   return false;

 }

 

-#ifndef _UNICODE

-bool MyGetModuleFileName(HMODULE hModule, UString &result)

+#ifndef _SFX

+

+FString GetModuleDirPrefix()

 {

-  result.Empty();

-  if (g_IsNT)

+  FString s;

+  if (MyGetModuleFileName(s))

   {

-    wchar_t fullPath[MAX_PATH + 2];

-    DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1);

-    if (size <= MAX_PATH && size != 0)

+    int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR);

+    if (pos >= 0)

     {

-      result = fullPath;

-      return true;

+      s.DeleteFrom(pos + 1);

+      return s;

     }

-    return false;

   }

-  CSysString resultSys;

-  if (!MyGetModuleFileName(hModule, resultSys))

-    return false;

-  result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage());

-  return true;

+  return FTEXT(".") FSTRING_PATH_SEPARATOR;

 }

+

 #endif

 

 }}

diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
old mode 100755
new mode 100644
index 7d02887..e61cf89
--- a/CPP/Windows/DLL.h
+++ b/CPP/Windows/DLL.h
@@ -9,15 +9,13 @@
 namespace NDLL {

 

 #ifdef UNDER_CE

-#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName)

+#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName)

 #else

-#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName)

+#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName)

 #endif

  

 class CLibrary

 {

-  bool LoadOperations(HMODULE newModule);

-protected:

   HMODULE _module;

 public:

   CLibrary(): _module(NULL) {};

@@ -39,20 +37,15 @@
     return m;

   }

 

-  bool Free();

-  bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);

-  bool Load(LPCTSTR fileName);

-  #ifndef _UNICODE

-  bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);

-  bool Load(LPCWSTR fileName);

-  #endif

+  bool Free() throw();

+  bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw();

+  bool Load(CFSTR path) throw();

   FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }

 };

 

-bool MyGetModuleFileName(HMODULE hModule, CSysString &result);

-#ifndef _UNICODE

-bool MyGetModuleFileName(HMODULE hModule, UString &result);

-#endif

+bool MyGetModuleFileName(FString &path);

+

+FString GetModuleDirPrefix();

 

 }}

 

diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h
old mode 100755
new mode 100644
diff --git a/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp
deleted file mode 100755
index fcba1e6..0000000
--- a/CPP/Windows/Error.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Windows/Error.h

-

-#include "StdAfx.h"

-

-#include "Windows/Error.h"

-#ifndef _UNICODE

-#include "Common/StringConvert.h"

-#endif

-

-#ifndef _UNICODE

-extern bool g_IsNT;

-#endif

-

-namespace NWindows {

-namespace NError {

-

-bool MyFormatMessage(DWORD messageID, CSysString &message)

-{

-  LPVOID msgBuf;

-  if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |

-      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

-      NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0)

-    return false;

-  message = (LPCTSTR)msgBuf;

-  ::LocalFree(msgBuf);

-  return true;

-}

-

-#ifndef _UNICODE

-bool MyFormatMessage(DWORD messageID, UString &message)

-{

-  if (g_IsNT)

-  {

-    LPVOID msgBuf;

-    if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |

-        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

-        NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)

-      return false;

-    message = (LPCWSTR)msgBuf;

-    ::LocalFree(msgBuf);

-    return true;

-  }

-  CSysString messageSys;

-  bool result = MyFormatMessage(messageID, messageSys);

-  message = GetUnicodeString(messageSys);

-  return result;

-}

-#endif

-

-}}

diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h
deleted file mode 100755
index d916e8e..0000000
--- a/CPP/Windows/Error.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Windows/Error.h

-

-#ifndef __WINDOWS_ERROR_H

-#define __WINDOWS_ERROR_H

-

-#include "Common/MyString.h"

-

-namespace NWindows {

-namespace NError {

-

-bool MyFormatMessage(DWORD messageID, CSysString &message);

-inline CSysString MyFormatMessage(DWORD messageID)

-{

-  CSysString message;

-  MyFormatMessage(messageID, message);

-  return message;

-}

-#ifdef _UNICODE

-inline UString MyFormatMessageW(DWORD messageID)

-  { return MyFormatMessage(messageID); }

-#else

-bool MyFormatMessage(DWORD messageID, UString &message);

-inline UString MyFormatMessageW(DWORD messageID)

-{

-  UString message;

-  MyFormatMessage(messageID, message);

-  return message;

-}

-#endif

-

-}}

-

-#endif

diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
new file mode 100644
index 0000000..e929e75
--- /dev/null
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -0,0 +1,61 @@
+// Windows/ErrorMsg.h

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "ErrorMsg.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NError {

+

+static bool MyFormatMessage(DWORD errorCode, UString &message)

+{

+  LPVOID msgBuf;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |

+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

+        NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0)

+      return false;

+    message = GetUnicodeString((LPCTSTR)msgBuf);

+  }

+  else

+  #endif

+  {

+    if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |

+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

+        NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)

+      return false;

+    message = (LPCWSTR)msgBuf;

+  }

+  ::LocalFree(msgBuf);

+  return true;

+}

+

+UString MyFormatMessage(DWORD errorCode)

+{

+  UString message;

+  if (!MyFormatMessage(errorCode, message))

+  {

+    wchar_t 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[8] = '\0';

+    message = (UString)L"Error #" + s;

+  }

+  return message;

+}

+

+}}

diff --git a/CPP/Windows/ErrorMsg.h b/CPP/Windows/ErrorMsg.h
new file mode 100644
index 0000000..e05e950
--- /dev/null
+++ b/CPP/Windows/ErrorMsg.h
@@ -0,0 +1,15 @@
+// Windows/ErrorMsg.h

+

+#ifndef __WINDOWS_ERROR_MSG_H

+#define __WINDOWS_ERROR_MSG_H

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+namespace NError {

+

+UString MyFormatMessage(DWORD errorCode);

+

+}}

+

+#endif

diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
old mode 100755
new mode 100644
index daec1d3..c215657
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -14,81 +14,62 @@
 extern bool g_IsNT;

 #endif

 

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+

 namespace NWindows {

 namespace NFile {

-

-#if defined(WIN_LONG_PATH) && defined(_UNICODE)

-#define WIN_LONG_PATH2

-#endif

-

-// SetCurrentDirectory doesn't support \\?\ prefix

-

-#ifdef WIN_LONG_PATH

-bool GetLongPathBase(LPCWSTR fileName, UString &res);

-bool GetLongPath(LPCWSTR fileName, UString &res);

-#endif

-

-namespace NDirectory {

-

-#ifndef _UNICODE

-static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

-static UString GetUnicodePath(const CSysString &sysPath)

-  { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }

-static CSysString GetSysPath(LPCWSTR sysPath)

-  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }

-#endif

+namespace NDir {

 

 #ifndef UNDER_CE

 

-bool MyGetWindowsDirectory(CSysString &path)

+bool GetWindowsDir(FString &path)

 {

-  UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

-  path.ReleaseBuffer();

+  UINT needLength;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetWindowsDirectory(s, MAX_PATH + 1);

+    path = fas2fs(s);

+  }

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1);

+    path = us2fs(s);

+  }

   return (needLength > 0 && needLength <= MAX_PATH);

 }

 

-bool MyGetSystemDirectory(CSysString &path)

+bool GetSystemDir(FString &path)

 {

-  UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

-  path.ReleaseBuffer();

+  UINT needLength;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetSystemDirectory(s, MAX_PATH + 1);

+    path = fas2fs(s);

+  }

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1);

+    path = us2fs(s);

+  }

   return (needLength > 0 && needLength <= MAX_PATH);

 }

-

 #endif

 

-#ifndef _UNICODE

-bool MyGetWindowsDirectory(UString &path)

-{

-  if (g_IsNT)

-  {

-    UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

-    path.ReleaseBuffer();

-    return (needLength > 0 && needLength <= MAX_PATH);

-  }

-  CSysString sysPath;

-  if (!MyGetWindowsDirectory(sysPath))

-    return false;

-  path = GetUnicodePath(sysPath);

-  return true;

-}

-

-bool MyGetSystemDirectory(UString &path)

-{

-  if (g_IsNT)

-  {

-    UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

-    path.ReleaseBuffer();

-    return (needLength > 0 && needLength <= MAX_PATH);

-  }

-  CSysString sysPath;

-  if (!MyGetSystemDirectory(sysPath))

-    return false;

-  path = GetUnicodePath(sysPath);

-  return true;

-}

-#endif

-

-bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

+bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

 {

   #ifndef _UNICODE

   if (!g_IsNT)

@@ -97,17 +78,18 @@
     return false;

   }

   #endif

-  HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,

-      FILE_SHARE_READ | FILE_SHARE_WRITE,

-      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

+  

+  HANDLE hDir = INVALID_HANDLE_VALUE;

+  IF_USE_MAIN_PATH

+    hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,

+        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

   #ifdef WIN_LONG_PATH

-  if (hDir == INVALID_HANDLE_VALUE)

+  if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)

   {

     UString longPath;

-    if (GetLongPath(fileName, longPath))

-      hDir = ::CreateFileW(longPath, GENERIC_WRITE,

-        FILE_SHARE_READ | FILE_SHARE_WRITE,

-        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

+    if (GetSuperPath(path, longPath, USE_MAIN_PATH))

+      hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,

+          NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

   }

   #endif

 

@@ -120,177 +102,172 @@
   return res;

 }

 

-bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)

+bool SetFileAttrib(CFSTR path, DWORD attrib)

 {

-  if (::SetFileAttributes(fileName, fileAttributes))

-    return true;

-  #ifdef WIN_LONG_PATH2

-  UString longPath;

-  if (GetLongPath(fileName, longPath))

-    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));

-  #endif

-  return false;

-}

-

-bool MyRemoveDirectory(LPCTSTR pathName)

-{

-  if (::RemoveDirectory(pathName))

-    return true;

-  #ifdef WIN_LONG_PATH2

-  UString longPath;

-  if (GetLongPath(pathName, longPath))

-    return BOOLToBool(::RemoveDirectoryW(longPath));

-  #endif

-  return false;

-}

-

-#ifdef WIN_LONG_PATH

-bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)

-{

-  if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))

-    return false;

-  if (d1.IsEmpty() && d2.IsEmpty()) return false;

-  if (d1.IsEmpty()) d1 = s1;

-  if (d2.IsEmpty()) d2 = s2;

-  return true;

-}

-#endif

-

-bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)

-{

-  if (::MoveFile(existFileName, newFileName))

-    return true;

-  #ifdef WIN_LONG_PATH2

-  UString d1, d2;

-  if (GetLongPaths(existFileName, newFileName, d1, d2))

-    return BOOLToBool(::MoveFileW(d1, d2));

-  #endif

-  return false;

-}

-

-#ifndef _UNICODE

-bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)

-{

+  #ifndef _UNICODE

   if (!g_IsNT)

-    return MySetFileAttributes(GetSysPath(fileName), fileAttributes);

-  if (::SetFileAttributesW(fileName, fileAttributes))

-    return true;

-  #ifdef WIN_LONG_PATH

-  UString longPath;

-  if (GetLongPath(fileName, longPath))

-    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));

-  #endif

-  return false;

-}

-

-

-bool MyRemoveDirectory(LPCWSTR pathName)

-{

-  if (!g_IsNT)

-    return MyRemoveDirectory(GetSysPath(pathName));

-  if (::RemoveDirectoryW(pathName))

-    return true;

-  #ifdef WIN_LONG_PATH

-  UString longPath;

-  if (GetLongPath(pathName, longPath))

-    return BOOLToBool(::RemoveDirectoryW(longPath));

-  #endif

-  return false;

-}

-

-bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)

-{

-  if (!g_IsNT)

-    return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));

-  if (::MoveFileW(existFileName, newFileName))

-    return true;

-  #ifdef WIN_LONG_PATH

-  UString d1, d2;

-  if (GetLongPaths(existFileName, newFileName, d1, d2))

-    return BOOLToBool(::MoveFileW(d1, d2));

-  #endif

-  return false;

-}

-#endif

-

-bool MyCreateDirectory(LPCTSTR pathName)

-{

-  if (::CreateDirectory(pathName, NULL))

-    return true;

-  #ifdef WIN_LONG_PATH2

-  if (::GetLastError() != ERROR_ALREADY_EXISTS)

   {

-    UString longPath;

-    if (GetLongPath(pathName, longPath))

-      return BOOLToBool(::CreateDirectoryW(longPath, NULL));

-  }

-  #endif

-  return false;

-}

-

-#ifndef _UNICODE

-bool MyCreateDirectory(LPCWSTR pathName)

-{

-  if (!g_IsNT)

-    return MyCreateDirectory(GetSysPath(pathName));

-  if (::CreateDirectoryW(pathName, NULL))

-    return true;

-  #ifdef WIN_LONG_PATH

-  if (::GetLastError() != ERROR_ALREADY_EXISTS)

-  {

-    UString longPath;

-    if (GetLongPath(pathName, longPath))

-      return BOOLToBool(::CreateDirectoryW(longPath, NULL));

-  }

-  #endif

-  return false;

-}

-#endif

-

-/*

-bool CreateComplexDirectory(LPCTSTR pathName)

-{

-  NName::CParsedPath path;

-  path.ParsePath(pathName);

-  CSysString fullPath = path.Prefix;

-  DWORD errorCode = ERROR_SUCCESS;

-  for (int i = 0; i < path.PathParts.Size(); i++)

-  {

-    const CSysString &string = path.PathParts[i];

-    if (string.IsEmpty())

-    {

-      if (i != path.PathParts.Size() - 1)

-        return false;

+    if (::SetFileAttributes(fs2fas(path), attrib))

       return true;

-    }

-    fullPath += path.PathParts[i];

-    if (!MyCreateDirectory(fullPath))

-    {

-      DWORD errorCode = GetLastError();

-      if (errorCode != ERROR_ALREADY_EXISTS)

-        return false;

-    }

-    fullPath += NName::kDirDelimiter;

   }

-  return true;

-}

-*/

-

-bool CreateComplexDirectory(LPCTSTR _aPathName)

-{

-  CSysString pathName = _aPathName;

-  int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

-  if (pos > 0 && pos == pathName.Length() - 1)

+  else

+  #endif

   {

-    if (pathName.Length() == 3 && pathName[1] == ':')

+    IF_USE_MAIN_PATH

+      if (::SetFileAttributesW(fs2us(path), attrib))

+        return true;

+    #ifdef WIN_LONG_PATH

+    if (USE_SUPER_PATH)

+    {

+      UString longPath;

+      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

+        return BOOLToBool(::SetFileAttributesW(longPath, attrib));

+    }

+    #endif

+  }

+  return false;

+}

+

+bool RemoveDir(CFSTR path)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    if (::RemoveDirectory(fs2fas(path)))

+      return true;

+  }

+  else

+  #endif

+  {

+    IF_USE_MAIN_PATH

+      if (::RemoveDirectoryW(fs2us(path)))

+        return true;

+    #ifdef WIN_LONG_PATH

+    if (USE_SUPER_PATH)

+    {

+      UString longPath;

+      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

+        return BOOLToBool(::RemoveDirectoryW(longPath));

+    }

+    #endif

+  }

+  return false;

+}

+

+bool MyMoveFile(CFSTR oldFile, CFSTR newFile)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    if (::MoveFile(fs2fas(oldFile), fs2fas(newFile)))

+      return true;

+  }

+  else

+  #endif

+  {

+    IF_USE_MAIN_PATH_2(oldFile, newFile)

+      if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))

+        return true;

+    #ifdef WIN_LONG_PATH

+    if (USE_SUPER_PATH_2)

+    {

+      UString d1, d2;

+      if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))

+        return BOOLToBool(::MoveFileW(d1, d2));

+    }

+    #endif

+  }

+  return false;

+}

+

+#ifndef UNDER_CE

+

+EXTERN_C_BEGIN

+typedef BOOL (WINAPI *Func_CreateHardLinkW)(

+    LPCWSTR lpFileName,

+    LPCWSTR lpExistingFileName,

+    LPSECURITY_ATTRIBUTES lpSecurityAttributes

+    );

+EXTERN_C_END

+

+bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+    return false;

+    /*

+    if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL))

+      return true;

+    */

+  }

+  else

+  #endif

+  {

+    Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW)

+        ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");

+    if (!my_CreateHardLinkW)

+      return false;

+    IF_USE_MAIN_PATH_2(newFileName, existFileName)

+      if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))

+        return true;

+    #ifdef WIN_LONG_PATH

+    if (USE_SUPER_PATH_2)

+    {

+      UString d1, d2;

+      if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))

+        return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL));

+    }

+    #endif

+  }

+  return false;

+}

+

+#endif

+

+bool CreateDir(CFSTR path)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    if (::CreateDirectory(fs2fas(path), NULL))

+      return true;

+  }

+  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 longPath;

+      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

+        return BOOLToBool(::CreateDirectoryW(longPath, NULL));

+    }

+    #endif

+  }

+  return false;

+}

+

+bool CreateComplexDir(CFSTR _aPathName)

+{

+  FString pathName = _aPathName;

+  int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);

+  if (pos > 0 && (unsigned)pos == pathName.Len() - 1)

+  {

+    if (pathName.Len() == 3 && pathName[1] == L':')

       return true; // Disk folder;

     pathName.Delete(pos);

   }

-  CSysString pathName2 = pathName;

-  pos = pathName.Length();

+  const FString pathName2 = pathName;

+  pos = pathName.Len();

+  

   for (;;)

   {

-    if (MyCreateDirectory(pathName))

+    if (CreateDir(pathName))

       break;

     if (::GetLastError() == ERROR_ALREADY_EXISTS)

     {

@@ -301,609 +278,306 @@
         return false;

       break;

     }

-    pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

-    if (pos < 0 || pos == 0)

-      return false;

-    if (pathName[pos - 1] == ':')

-      return false;

-    pathName = pathName.Left(pos);

-  }

-  pathName = pathName2;

-  while (pos < pathName.Length())

-  {

-    pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);

-    if (pos < 0)

-      pos = pathName.Length();

-    if (!MyCreateDirectory(pathName.Left(pos)))

-      return false;

-  }

-  return true;

-}

-

-#ifndef _UNICODE

-

-bool CreateComplexDirectory(LPCWSTR _aPathName)

-{

-  UString pathName = _aPathName;

-  int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);

-  if (pos > 0 && pos == pathName.Length() - 1)

-  {

-    if (pathName.Length() == 3 && pathName[1] == L':')

-      return true; // Disk folder;

-    pathName.Delete(pos);

-  }

-  UString pathName2 = pathName;

-  pos = pathName.Length();

-  for (;;)

-  {

-    if (MyCreateDirectory(pathName))

-      break;

-    if (::GetLastError() == ERROR_ALREADY_EXISTS)

-    {

-      NFind::CFileInfoW fileInfo;

-      if (!fileInfo.Find(pathName)) // For network folders

-        return true;

-      if (!fileInfo.IsDir())

-        return false;

-      break;

-    }

-    pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);

+    pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);

     if (pos < 0 || pos == 0)

       return false;

     if (pathName[pos - 1] == L':')

       return false;

-    pathName = pathName.Left(pos);

+    pathName.DeleteFrom(pos);

   }

-  pathName = pathName2;

-  while (pos < pathName.Length())

+  

+  while (pos < (int)pathName2.Len())

   {

-    pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);

+    pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1);

     if (pos < 0)

-      pos = pathName.Length();

-    if (!MyCreateDirectory(pathName.Left(pos)))

+      pos = pathName2.Len();

+    pathName.SetFrom(pathName2, pos);

+    if (!CreateDir(pathName))

       return false;

   }

+  

   return true;

 }

 

-#endif

-

-bool DeleteFileAlways(LPCTSTR name)

+bool DeleteFileAlways(CFSTR path)

 {

-  if (!MySetFileAttributes(name, 0))

+  if (!SetFileAttrib(path, 0))

     return false;

-  if (::DeleteFile(name))

-    return true;

-  #ifdef WIN_LONG_PATH2

-  UString longPath;

-  if (GetLongPath(name, longPath))

-    return BOOLToBool(::DeleteFileW(longPath));

-  #endif

-  return false;

-}

-

-#ifndef _UNICODE

-bool DeleteFileAlways(LPCWSTR name)

-{

+  #ifndef _UNICODE

   if (!g_IsNT)

-    return DeleteFileAlways(GetSysPath(name));

-  if (!MySetFileAttributes(name, 0))

-    return false;

-  if (::DeleteFileW(name))

-    return true;

-  #ifdef WIN_LONG_PATH

-  UString longPath;

-  if (GetLongPath(name, longPath))

-    return BOOLToBool(::DeleteFileW(longPath));

+  {

+    if (::DeleteFile(fs2fas(path)))

+      return true;

+  }

+  else

   #endif

+  {

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

+    }

+    #endif

+  }

   return false;

 }

-#endif

 

-static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)

+bool RemoveDirWithSubItems(const FString &path)

 {

-  if (fileInfo.IsDir())

-    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);

-  return DeleteFileAlways(pathPrefix + fileInfo.Name);

-}

-

-bool RemoveDirectoryWithSubItems(const CSysString &path)

-{

-  NFind::CFileInfo fileInfo;

-  CSysString pathPrefix = path + NName::kDirDelimiter;

+  bool needRemoveSubItems = true;

   {

-    NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));

-    while (enumerator.Next(fileInfo))

-      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))

-        return false;

+    NFind::CFileInfo fi;

+    if (!fi.Find(path))

+      return false;

+    if (!fi.IsDir())

+    {

+      ::SetLastError(ERROR_DIRECTORY);

+      return false;

+    }

+    if (fi.HasReparsePoint())

+      needRemoveSubItems = false;

   }

-  if (!MySetFileAttributes(path, 0))

-    return false;

-  return MyRemoveDirectory(path);

-}

 

-#ifndef _UNICODE

-static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)

-{

-  if (fileInfo.IsDir())

-    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);

-  return DeleteFileAlways(pathPrefix + fileInfo.Name);

-}

-bool RemoveDirectoryWithSubItems(const UString &path)

-{

-  NFind::CFileInfoW fileInfo;

-  UString pathPrefix = path + UString(NName::kDirDelimiter);

+  if (needRemoveSubItems)

   {

-    NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));

-    while (enumerator.Next(fileInfo))

-      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))

+    FString s = path;

+    s += FCHAR_PATH_SEPARATOR;

+    unsigned prefixSize = s.Len();

+    s += FCHAR_ANY_MASK;

+    NFind::CEnumerator enumerator(s);

+    NFind::CFileInfo fi;

+    while (enumerator.Next(fi))

+    {

+      s.DeleteFrom(prefixSize);

+      s += fi.Name;

+      if (fi.IsDir())

+      {

+        if (!RemoveDirWithSubItems(s))

+          return false;

+      }

+      else if (!DeleteFileAlways(s))

         return false;

+    }

   }

-  if (!MySetFileAttributes(path, 0))

+  

+  if (!SetFileAttrib(path, 0))

     return false;

-  return MyRemoveDirectory(path);

-}

-#endif

-

-bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)

-{

-  int index;

-  if (!MyGetFullPathName(fileName, resultName, index))

-    return false;

-  resultName = resultName.Left(index);

-  return true;

-}

-

-bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)

-{

-  int index;

-  if (!MyGetFullPathName(fileName, resultName, index))

-    return false;

-  resultName = resultName.Mid(index);

-  return true;

+  return RemoveDir(path);

 }

 

 #ifdef UNDER_CE

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath)

-{

-  resultPath = fileName;

-  return true;

-}

 

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)

+bool MyGetFullPathName(CFSTR path, FString &resFullPath)

 {

-  resultPath = fileName;

-  // change it

-  fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR);

-  fileNamePartStartIndex++;

+  resFullPath = path;

   return true;

 }

 

 #else

 

-bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)

+bool MyGetFullPathName(CFSTR path, FString &resFullPath)

 {

-  DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

-  shortPath.ReleaseBuffer();

-  return (needLength > 0 && needLength < MAX_PATH);

+  return GetFullPath(path, resFullPath);

 }

 

-#ifdef WIN_LONG_PATH

-

-static UString GetLastPart(LPCWSTR path)

+bool SetCurrentDir(CFSTR path)

 {

-  int i = (int)wcslen(path);

-  for (; i > 0; i--)

+  // SetCurrentDirectory doesn't support \\?\ prefix

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

-    WCHAR c = path[i - 1];

-    if (c == WCHAR_PATH_SEPARATOR || c == '/')

-      break;

-  }

-  return path + i;

-}

-

-static void AddTrailingDots(LPCWSTR oldPath, UString &newPath)

-{

-  int len = (int)wcslen(oldPath);

-  int i;

-  for (i = len; i > 0 && oldPath[i - 1] == '.'; i--);

-  if (i == 0 || i == len)

-    return;

-  UString oldName = GetLastPart(oldPath);

-  UString newName = GetLastPart(newPath);

-  int nonDotsLen = oldName.Length() - (len - i);

-  if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0)

-    return;

-  for (; i != len; i++)

-    newPath += '.';

-}

-

-#endif

-

-bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)

-{

-  resultPath.Empty();

-  LPTSTR fileNamePointer = 0;

-  LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);

-  DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);

-  resultPath.ReleaseBuffer();

-  if (needLength == 0)

-    return false;

-  if (needLength >= MAX_PATH)

-  {

-    #ifdef WIN_LONG_PATH2

-    needLength++;

-    buffer = resultPath.GetBuffer(needLength + 1);

-    DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);

-    resultPath.ReleaseBuffer();

-    if (needLength2 == 0 || needLength2 > needLength)

-    #endif

-      return false;

-  }

-  if (fileNamePointer == 0)

-    fileNamePartStartIndex = lstrlen(fileName);

-  else

-    fileNamePartStartIndex = (int)(fileNamePointer - buffer);

-  #ifdef _UNICODE

-  #ifdef WIN_LONG_PATH

-  AddTrailingDots(fileName, resultPath);

-  #endif

-  #endif

-  return true;

-}

-

-#ifndef _UNICODE

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)

-{

-  resultPath.Empty();

-  if (g_IsNT)

-  {

-    LPWSTR fileNamePointer = 0;

-    LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);

-    DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);

-    resultPath.ReleaseBuffer();

-    if (needLength == 0)

-      return false;

-    if (needLength >= MAX_PATH)

-    {

-      #ifdef WIN_LONG_PATH

-      needLength++;

-      buffer = resultPath.GetBuffer(needLength + 1);

-      DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);

-      resultPath.ReleaseBuffer();

-      if (needLength2 == 0 || needLength2 > needLength)

-      #endif

-        return false;

-    }

-    if (fileNamePointer == 0)

-      fileNamePartStartIndex = MyStringLen(fileName);

-    else

-      fileNamePartStartIndex = (int)(fileNamePointer - buffer);

-    #ifdef WIN_LONG_PATH

-    AddTrailingDots(fileName, resultPath);

-    #endif

+    return BOOLToBool(::SetCurrentDirectory(fs2fas(path)));

   }

   else

+  #endif

   {

-    CSysString sysPath;

-    if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))

-      return false;

-    UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));

-    UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));

-    fileNamePartStartIndex = resultPath1.Length();

-    resultPath = resultPath1 + resultPath2;

+    return BOOLToBool(::SetCurrentDirectoryW(fs2us(path)));

   }

-  return true;

-}

-#endif

-

-

-bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)

-{

-  int index;

-  return MyGetFullPathName(fileName, path, index);

 }

 

-#ifndef _UNICODE

-bool MyGetFullPathName(LPCWSTR fileName, UString &path)

-{

-  int index;

-  return MyGetFullPathName(fileName, path, index);

-}

-#endif

-

-#ifndef _UNICODE

-bool GetOnlyName(LPCWSTR fileName, UString &resultName)

-{

-  int index;

-  if (!MyGetFullPathName(fileName, resultName, index))

-    return false;

-  resultName = resultName.Mid(index);

-  return true;

-}

-#endif

-

-#ifndef _UNICODE

-bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)

-{

-  int index;

-  if (!MyGetFullPathName(fileName, resultName, index))

-    return false;

-  resultName = resultName.Left(index);

-  return true;

-}

-#endif

-

-bool MyGetCurrentDirectory(CSysString &path)

-{

-  DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

-  path.ReleaseBuffer();

-  return (needLength > 0 && needLength <= MAX_PATH);

-}

-

-#ifndef _UNICODE

-bool MySetCurrentDirectory(LPCWSTR path)

-{

-  if (g_IsNT)

-    return BOOLToBool(::SetCurrentDirectoryW(path));

-  return MySetCurrentDirectory(GetSysPath(path));

-}

-bool MyGetCurrentDirectory(UString &path)

-{

-  if (g_IsNT)

-  {

-    DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

-    path.ReleaseBuffer();

-    return (needLength > 0 && needLength <= MAX_PATH);

-  }

-  CSysString sysPath;

-  if (!MyGetCurrentDirectory(sysPath))

-    return false;

-  path = GetUnicodePath(sysPath);

-  return true;

-}

-#endif

-

-bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension,

-  CSysString &resultPath, UINT32 &filePart)

-{

-  LPTSTR filePartPointer;

-  DWORD value = ::SearchPath(path, fileName, extension,

-    MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);

-  filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);

-  resultPath.ReleaseBuffer();

-  return (value > 0 && value <= MAX_PATH);

-}

-#endif

-

-#ifndef _UNICODE

-bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension,

-  UString &resultPath, UINT32 &filePart)

-{

-  if (g_IsNT)

-  {

-    LPWSTR filePartPointer = 0;

-    DWORD value = ::SearchPathW(path, fileName, extension,

-        MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);

-    filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);

-    resultPath.ReleaseBuffer();

-    return (value > 0 && value <= MAX_PATH);

-  }

-  

-  CSysString sysPath;

-  if (!MySearchPath(

-      path != 0 ? (LPCTSTR)GetSysPath(path): 0,

-      fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,

-      extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,

-      sysPath, filePart))

-    return false;

-  UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));

-  UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));

-  filePart = resultPath1.Length();

-  resultPath = resultPath1 + resultPath2;

-  return true;

-}

-#endif

-

-bool MyGetTempPath(CSysString &path)

-{

-  DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

-  path.ReleaseBuffer();

-  return (needLength > 0 && needLength <= MAX_PATH);

-}

-

-#ifndef _UNICODE

-bool MyGetTempPath(UString &path)

+bool GetCurrentDir(FString &path)

 {

   path.Empty();

-  if (g_IsNT)

+  DWORD needLength;

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

-    DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

-    path.ReleaseBuffer();

-    return (needLength > 0 && needLength <= MAX_PATH);

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);

+    path = fas2fs(s);

   }

-  CSysString sysPath;

-  if (!MyGetTempPath(sysPath))

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);

+    path = us2fs(s);

+  }

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+#endif

+

+bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)

+{

+  bool res = MyGetFullPathName(path, resDirPrefix);

+  if (!res)

+    resDirPrefix = path;

+  int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR);

+  resFileName = resDirPrefix.Ptr(pos + 1);

+  resDirPrefix.DeleteFrom(pos + 1);

+  return res;

+}

+

+bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)

+{

+  FString resFileName;

+  return GetFullPathAndSplit(path, resDirPrefix, resFileName);

+}

+

+bool MyGetTempPath(FString &path)

+{

+  path.Empty();

+  DWORD needLength;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetTempPath(MAX_PATH + 1, s);

+    path = fas2fs(s);

+  }

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetTempPathW(MAX_PATH + 1, s);;

+    path = us2fs(s);

+  }

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile)

+{

+  UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();

+  for (unsigned i = 0; i < 100; i++)

+  {

+    path = prefix;

+    if (addRandom)

+    {

+      FChar s[16];

+      UInt32 value = d;

+      unsigned k;

+      for (k = 0; k < 8; k++)

+      {

+        unsigned t = value & 0xF;

+        value >>= 4;

+        s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+      }

+      s[k] = '\0';

+      if (outFile)

+        path += FChar('.');

+      path += s;

+      UInt32 step = GetTickCount() + 2;

+      if (step == 0)

+        step = 1;

+      d += step;

+    }

+    addRandom = true;

+    if (outFile)

+      path += FTEXT(".tmp");

+    if (NFind::DoesFileOrDirExist(path))

+    {

+      SetLastError(ERROR_ALREADY_EXISTS);

+      continue;

+    }

+    if (outFile)

+    {

+      if (outFile->Create(path, false))

+        return true;

+    }

+    else

+    {

+      if (CreateDir(path))

+        return true;

+    }

+    DWORD error = GetLastError();

+    if (error != ERROR_FILE_EXISTS &&

+        error != ERROR_ALREADY_EXISTS)

+      break;

+  }

+  path.Empty();

+  return false;

+}

+

+bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)

+{

+  if (!Remove())

     return false;

-  path = GetUnicodePath(sysPath);

+  if (!CreateTempFile(prefix, false, _path, outFile))

+    return false;

+  _mustBeDeleted = true;

   return true;

 }

-#endif

 

-UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)

+bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile)

 {

-  UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));

-  path.ReleaseBuffer();

-  return number;

-}

-

-#ifndef _UNICODE

-UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)

-{

-  if (g_IsNT)

-  {

-    UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));

-    path.ReleaseBuffer();

-    return number;

-  }

-  CSysString sysPath;

-  UINT number = MyGetTempFileName(

-      dirPath ? (LPCTSTR)GetSysPath(dirPath): 0,

-      prefix ? (LPCTSTR)GetSysPath(prefix): 0,

-      sysPath);

-  path = GetUnicodePath(sysPath);

-  return number;

-}

-#endif

-

-UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)

-{

-  Remove();

-  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);

-  if (number != 0)

-  {

-    _fileName = resultPath;

-    _mustBeDeleted = true;

-  }

-  return number;

-}

-

-bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)

-{

-  CSysString tempPath;

+  if (!Remove())

+    return false;

+  FString tempPath;

   if (!MyGetTempPath(tempPath))

     return false;

-  if (Create(tempPath, prefix, resultPath) != 0)

-    return true;

-  #ifdef UNDER_CE

-  return false;

-  #else

-  if (!MyGetWindowsDirectory(tempPath))

+  if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile))

     return false;

-  return (Create(tempPath, prefix, resultPath) != 0);

-  #endif

+  _mustBeDeleted = true;

+  return true;

 }

 

 bool CTempFile::Remove()

 {

   if (!_mustBeDeleted)

     return true;

-  _mustBeDeleted = !DeleteFileAlways(_fileName);

+  _mustBeDeleted = !DeleteFileAlways(_path);

   return !_mustBeDeleted;

 }

 

-#ifndef _UNICODE

-

-UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)

+bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)

 {

-  Remove();

-  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);

-  if (number != 0)

-  {

-    _fileName = resultPath;

-    _mustBeDeleted = true;

-  }

-  return number;

+  if (deleteDestBefore)

+    if (NFind::DoesFileExist(name))

+      if (!DeleteFileAlways(name))

+        return false;

+  DisableDeleting();

+  return MyMoveFile(_path, name);

 }

 

-bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)

+bool CTempDir::Create(CFSTR prefix)

 {

-  UString tempPath;

+  if (!Remove())

+    return false;

+  FString tempPath;

   if (!MyGetTempPath(tempPath))

     return false;

-  if (Create(tempPath, prefix, resultPath) != 0)

-    return true;

-  if (!MyGetWindowsDirectory(tempPath))

+  if (!CreateTempFile(tempPath + prefix, true, _path, NULL))

     return false;

-  return (Create(tempPath, prefix, resultPath) != 0);

+  _mustBeDeleted = true;

+  return true;

 }

 

-bool CTempFileW::Remove()

+bool CTempDir::Remove()

 {

   if (!_mustBeDeleted)

     return true;

-  _mustBeDeleted = !DeleteFileAlways(_fileName);

+  _mustBeDeleted = !RemoveDirWithSubItems(_path);

   return !_mustBeDeleted;

 }

 

-#endif

-

-bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)

-{

-  /*

-  CSysString prefix = tempPath + prefixChars;

-  CRandom random;

-  random.Init();

-  */

-  for (;;)

-  {

-    {

-      CTempFile tempFile;

-      if (!tempFile.Create(prefix, dirName))

-        return false;

-      if (!tempFile.Remove())

-        return false;

-    }

-    /*

-    UINT32 randomNumber = random.Generate();

-    TCHAR randomNumberString[32];

-    _stprintf(randomNumberString, _T("%04X"), randomNumber);

-    dirName = prefix + randomNumberString;

-    */

-    if (NFind::DoesFileOrDirExist(dirName))

-      continue;

-    if (MyCreateDirectory(dirName))

-      return true;

-    if (::GetLastError() != ERROR_ALREADY_EXISTS)

-      return false;

-  }

-}

-

-bool CTempDirectory::Create(LPCTSTR prefix)

-{

-  Remove();

-  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));

-}

-

-#ifndef _UNICODE

-

-bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)

-{

-  /*

-  CSysString prefix = tempPath + prefixChars;

-  CRandom random;

-  random.Init();

-  */

-  for (;;)

-  {

-    {

-      CTempFileW tempFile;

-      if (!tempFile.Create(prefix, dirName))

-        return false;

-      if (!tempFile.Remove())

-        return false;

-    }

-    /*

-    UINT32 randomNumber = random.Generate();

-    TCHAR randomNumberString[32];

-    _stprintf(randomNumberString, _T("%04X"), randomNumber);

-    dirName = prefix + randomNumberString;

-    */

-    if (NFind::DoesFileOrDirExist(dirName))

-      continue;

-    if (MyCreateDirectory(dirName))

-      return true;

-    if (::GetLastError() != ERROR_ALREADY_EXISTS)

-      return false;

-  }

-}

-

-bool CTempDirectoryW::Create(LPCWSTR prefix)

-{

-  Remove();

-  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));

-}

-

-#endif

-

 }}}

diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
old mode 100755
new mode 100644
index 2c15071..1c75788
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -1,174 +1,94 @@
 // Windows/FileDir.h

 

-#ifndef __WINDOWS_FILEDIR_H

-#define __WINDOWS_FILEDIR_H

+#ifndef __WINDOWS_FILE_DIR_H

+#define __WINDOWS_FILE_DIR_H

 

 #include "../Common/MyString.h"

-#include "Defs.h"

+

+#include "FileIO.h"

 

 namespace NWindows {

 namespace NFile {

-namespace NDirectory {

+namespace NDir {

 

-#ifdef WIN_LONG_PATH

-bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2);

+bool GetWindowsDir(FString &path);

+bool GetSystemDir(FString &path);

+

+bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);

+bool SetFileAttrib(CFSTR path, DWORD attrib);

+bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);

+

+#ifndef UNDER_CE

+bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName);

 #endif

 

-bool MyGetWindowsDirectory(CSysString &path);

-bool MyGetSystemDirectory(CSysString &path);

-#ifndef _UNICODE

-bool MyGetWindowsDirectory(UString &path);

-bool MyGetSystemDirectory(UString &path);

-#endif

+bool RemoveDir(CFSTR path);

+bool CreateDir(CFSTR path);

+bool CreateComplexDir(CFSTR path);

+bool DeleteFileAlways(CFSTR name);

+bool RemoveDirWithSubItems(const FString &path);

 

-bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);

+bool MyGetFullPathName(CFSTR path, FString &resFullPath);

+bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName);

+bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix);

 

-bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes);

-bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName);

-bool MyRemoveDirectory(LPCTSTR pathName);

-bool MyCreateDirectory(LPCTSTR pathName);

-bool CreateComplexDirectory(LPCTSTR pathName);

-bool DeleteFileAlways(LPCTSTR name);

-bool RemoveDirectoryWithSubItems(const CSysString &path);

+#ifndef UNDER_CE

 

-#ifndef _UNICODE

-bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes);

-bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName);

-bool MyRemoveDirectory(LPCWSTR pathName);

-bool MyCreateDirectory(LPCWSTR pathName);

-bool CreateComplexDirectory(LPCWSTR pathName);

-bool DeleteFileAlways(LPCWSTR name);

-bool RemoveDirectoryWithSubItems(const UString &path);

-#endif

-

-bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName);

-bool GetOnlyName(LPCTSTR fileName, CSysString &resultName);

-#ifdef UNDER_CE

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex);

-#else

-bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath);

-

-bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex);

-bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath);

-#ifndef _UNICODE

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath,

-    int &fileNamePartStartIndex);

-bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);

-bool GetOnlyName(LPCWSTR fileName, UString &resultName);

-bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName);

-#endif

-

-inline bool MySetCurrentDirectory(LPCTSTR path)

-  { return BOOLToBool(::SetCurrentDirectory(path)); }

-bool MyGetCurrentDirectory(CSysString &resultPath);

-#ifndef _UNICODE

-bool MySetCurrentDirectory(LPCWSTR path);

-bool MyGetCurrentDirectory(UString &resultPath);

-#endif

-

-bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart);

-#ifndef _UNICODE

-bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart);

-#endif

-

-inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath)

-{

-  UINT32 value;

-  return MySearchPath(path, fileName, extension, resultPath, value);

-}

-

-#ifndef _UNICODE

-inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath)

-{

-  UINT32 value;

-  return MySearchPath(path, fileName, extension, resultPath, value);

-}

-#endif

+bool SetCurrentDir(CFSTR path);

+bool GetCurrentDir(FString &resultPath);

 

 #endif

 

-bool MyGetTempPath(CSysString &resultPath);

-#ifndef _UNICODE

-bool MyGetTempPath(UString &resultPath);

-#endif

-

-UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);

-#ifndef _UNICODE

-UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);

-#endif

+bool MyGetTempPath(FString &resultPath);

 

 class CTempFile

 {

   bool _mustBeDeleted;

-  CSysString _fileName;

+  FString _path;

+  void DisableDeleting() { _mustBeDeleted = false; }

 public:

   CTempFile(): _mustBeDeleted(false) {}

   ~CTempFile() { Remove(); }

+  const FString &GetPath() const { return _path; }

+  bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix

+  bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile);

+  bool Remove();

+  bool MoveTo(CFSTR name, bool deleteDestBefore);

+};

+

+class CTempDir

+{

+  bool _mustBeDeleted;

+  FString _path;

+public:

+  CTempDir(): _mustBeDeleted(false) {}

+  ~CTempDir() { Remove();  }

+  const FString &GetPath() const { return _path; }

   void DisableDeleting() { _mustBeDeleted = false; }

-  UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);

-  bool Create(LPCTSTR prefix, CSysString &resultPath);

+  bool Create(CFSTR namePrefix) ;

   bool Remove();

 };

 

-#ifdef _UNICODE

-typedef CTempFile CTempFileW;

-#else

-class CTempFileW

+#if !defined(UNDER_CE)

+class CCurrentDirRestorer

 {

-  bool _mustBeDeleted;

-  UString _fileName;

+  FString _path;

 public:

-  CTempFileW(): _mustBeDeleted(false) {}

-  ~CTempFileW() { Remove(); }

-  void DisableDeleting() { _mustBeDeleted = false; }

-  UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);

-  bool Create(LPCWSTR prefix, UString &resultPath);

-  bool Remove();

-};

-#endif

+  bool NeedRestore;

 

-bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName);

-

-class CTempDirectory

-{

-  bool _mustBeDeleted;

-  CSysString _tempDir;

-public:

-  const CSysString &GetPath() const { return _tempDir; }

-  CTempDirectory(): _mustBeDeleted(false) {}

-  ~CTempDirectory() { Remove();  }

-  bool Create(LPCTSTR prefix) ;

-  bool Remove()

+  CCurrentDirRestorer(): NeedRestore(true)

   {

-    if (!_mustBeDeleted)

-      return true;

-    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);

-    return (!_mustBeDeleted);

+    GetCurrentDir(_path);

   }

-  void DisableDeleting() { _mustBeDeleted = false; }

-};

-

-#ifdef _UNICODE

-typedef CTempDirectory CTempDirectoryW;

-#else

-class CTempDirectoryW

-{

-  bool _mustBeDeleted;

-  UString _tempDir;

-public:

-  const UString &GetPath() const { return _tempDir; }

-  CTempDirectoryW(): _mustBeDeleted(false) {}

-  ~CTempDirectoryW() { Remove();  }

-  bool Create(LPCWSTR prefix) ;

-  bool Remove()

+  ~CCurrentDirRestorer()

   {

-    if (!_mustBeDeleted)

-      return true;

-    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);

-    return (!_mustBeDeleted);

+    if (!NeedRestore)

+      return;

+    FString s;

+    if (GetCurrentDir(s))

+      if (s != _path)

+        SetCurrentDir(_path);

   }

-  void DisableDeleting() { _mustBeDeleted = false; }

 };

 #endif

 

diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
old mode 100755
new mode 100644
index 99fb706..35c0bf6
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -4,6 +4,7 @@
 

 #include "FileFind.h"

 #include "FileIO.h"

+#include "FileName.h"

 #ifndef _UNICODE

 #include "../Common/StringConvert.h"

 #endif

@@ -12,52 +13,63 @@
 extern bool g_IsNT;

 #endif

 

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+EXTERN_C_BEGIN

+

+typedef enum

+{

+  My_FindStreamInfoStandard,

+  My_FindStreamInfoMaxInfoLevel

+} MY_STREAM_INFO_LEVELS;

+

+typedef struct

+{

+  LARGE_INTEGER StreamSize;

+  WCHAR cStreamName[MAX_PATH + 36];

+} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA;

+

+typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,

+    LPVOID findStreamData, DWORD flags);

+

+typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData);

+

+EXTERN_C_END

+

+#endif

+

 namespace NWindows {

 namespace NFile {

 

 #ifdef SUPPORT_DEVICE_FILE

-bool IsDeviceName(LPCTSTR n);

-#ifndef _UNICODE

-bool IsDeviceName(LPCWSTR n);

+namespace NSystem

+{

+bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);

+}

 #endif

-#endif

-

-#if defined(WIN_LONG_PATH) && defined(_UNICODE)

-#define WIN_LONG_PATH2

-#endif

-

-bool GetLongPath(LPCWSTR fileName, UString &res);

 

 namespace NFind {

 

-static const TCHAR kDot = TEXT('.');

-

-bool CFileInfo::IsDots() const

+bool CFileInfo::IsDots() const throw()

 {

   if (!IsDir() || Name.IsEmpty())

     return false;

-  if (Name[0] != kDot)

+  if (Name[0] != FTEXT('.'))

     return false;

-  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);

+  return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.'));

 }

 

-#ifndef _UNICODE

-bool CFileInfoW::IsDots() const

-{

-  if (!IsDir() || Name.IsEmpty())

-    return false;

-  if (Name[0] != kDot)

-    return false;

-  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);

-}

-#endif

-

 #define WIN_FD_TO_MY_FI(fi, fd) \

   fi.Attrib = fd.dwFileAttributes; \

   fi.CTime = fd.ftCreationTime; \

   fi.ATime = fd.ftLastAccessTime; \

   fi.MTime = fd.ftLastWriteTime; \

   fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \

+  fi.IsAltStream = false; \

   fi.IsDevice = false;

 

   /*

@@ -68,33 +80,31 @@
   #endif

   */

 

-static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)

+static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi)

 {

   WIN_FD_TO_MY_FI(fi, fd);

-  fi.Name = fd.cFileName;

+  fi.Name = us2fs(fd.cFileName);

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  // fi.ShortName = us2fs(fd.cAlternateFileName);

+  #endif

 }

 

 #ifndef _UNICODE

 

-static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

-

-static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi)

+static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)

 {

   WIN_FD_TO_MY_FI(fi, fd);

-  fi.Name = fd.cFileName;

-}

-

-static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi)

-{

-  WIN_FD_TO_MY_FI(fi, fd);

-  fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage());

+  fi.Name = fas2fs(fd.cFileName);

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  // fi.ShortName = fas2fs(fd.cAlternateFileName);

+  #endif

 }

 #endif

   

 ////////////////////////////////

 // CFindFile

 

-bool CFindFile::Close()

+bool CFindFileBase::Close() throw()

 {

   if (_handle == INVALID_HANDLE_VALUE)

     return true;

@@ -104,183 +114,344 @@
   return true;

 }

 

-          

-bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi)

+bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)

 {

   if (!Close())

     return false;

-  WIN32_FIND_DATA fd;

-  _handle = ::FindFirstFile(wildcard, &fd);

-  #ifdef WIN_LONG_PATH2

-  if (_handle == INVALID_HANDLE_VALUE)

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

-    UString longPath;

-    if (GetLongPath(wildcard, longPath))

-      _handle = ::FindFirstFileW(longPath, &fd);

+    WIN32_FIND_DATAA fd;

+    _handle = ::FindFirstFileA(fs2fas(path), &fd);

+    if (_handle == INVALID_HANDLE_VALUE)

+      return false;

+    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);

   }

+  else

   #endif

-  if (_handle == INVALID_HANDLE_VALUE)

-    return false;

-  ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

-  return true;

-}

-

-#ifndef _UNICODE

-bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi)

-{

-  if (!Close())

-    return false;

-  if (g_IsNT)

   {

     WIN32_FIND_DATAW fd;

-    _handle = ::FindFirstFileW(wildcard, &fd);

+

+    IF_USE_MAIN_PATH

+      _handle = ::FindFirstFileW(fs2us(path), &fd);

     #ifdef WIN_LONG_PATH

-    if (_handle == INVALID_HANDLE_VALUE)

+    if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)

     {

       UString longPath;

-      if (GetLongPath(wildcard, longPath))

+      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

         _handle = ::FindFirstFileW(longPath, &fd);

     }

     #endif

-    if (_handle != INVALID_HANDLE_VALUE)

-      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+    if (_handle == INVALID_HANDLE_VALUE)

+      return false;

+    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);

   }

-  else

-  {

-    WIN32_FIND_DATAA fd;

-    _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,

-        GetCurrentCodePage()), &fd);

-    if (_handle != INVALID_HANDLE_VALUE)

-      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

-  }

-  return (_handle != INVALID_HANDLE_VALUE);

+  return true;

 }

-#endif

 

 bool CFindFile::FindNext(CFileInfo &fi)

 {

-  WIN32_FIND_DATA fd;

-  bool result = BOOLToBool(::FindNextFile(_handle, &fd));

-  if (result)

-    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

-  return result;

-}

-

-#ifndef _UNICODE

-bool CFindFile::FindNext(CFileInfoW &fi)

-{

-  if (g_IsNT)

-  {

-    WIN32_FIND_DATAW fd;

-    if (!::FindNextFileW(_handle, &fd))

-      return false;

-    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

-  }

-  else

+  #ifndef _UNICODE

+  if (!g_IsNT)

   {

     WIN32_FIND_DATAA fd;

     if (!::FindNextFileA(_handle, &fd))

       return false;

-    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);

+  }

+  else

+  #endif

+  {

+    WIN32_FIND_DATAW fd;

+    if (!::FindNextFileW(_handle, &fd))

+      return false;

+    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);

   }

   return true;

 }

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+////////////////////////////////

+// AltStreams

+

+static FindFirstStreamW_Ptr g_FindFirstStreamW;

+static FindNextStreamW_Ptr g_FindNextStreamW;

+

+struct CFindStreamLoader

+{

+  CFindStreamLoader()

+  {

+    g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW");

+    g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW");

+  }

+} g_FindStreamLoader;

+

+bool CStreamInfo::IsMainStream() const throw()

+{

+  return Name == L"::$DATA";

+};

+

+UString CStreamInfo::GetReducedName() const

+{

+  UString s = Name;

+  if (s.Len() >= 6)

+    if (wcscmp(s.RightPtr(6), L":$DATA") == 0)

+      s.DeleteFrom(s.Len() - 6);

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

+}

+

+bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)

+{

+  if (!Close())

+    return false;

+  if (!g_FindFirstStreamW)

+  {

+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+    return false;

+  }

+  {

+    MY_WIN32_FIND_STREAM_DATA sd;

+    IF_USE_MAIN_PATH

+      _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);

+    if (_handle == INVALID_HANDLE_VALUE)

+    {

+      if (::GetLastError() == ERROR_HANDLE_EOF)

+        return false;

+      // long name can be tricky for path like ".\dirName".

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

+      }

+      #endif

+    }

+    if (_handle == INVALID_HANDLE_VALUE)

+      return false;

+    Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);

+  }

+  return true;

+}

+

+bool CFindStream::FindNext(CStreamInfo &si)

+{

+  if (!g_FindNextStreamW)

+  {

+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+    return false;

+  }

+  {

+    MY_WIN32_FIND_STREAM_DATA sd;

+    if (!g_FindNextStreamW(_handle, &sd))

+      return false;

+    Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);

+  }

+  return true;

+}

+

+bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)

+{

+  bool res;

+  if (_find.IsHandleAllocated())

+    res = _find.FindNext(si);

+  else

+    res = _find.FindFirst(_filePath, si);

+  if (res)

+  {

+    found = true;

+    return true;

+  }

+  found = false;

+  return (::GetLastError() == ERROR_HANDLE_EOF);

+}

+

 #endif

 

+

 #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;

 

-void CFileInfoBase::Clear()

+void CFileInfoBase::Clear() throw()

 {

   Size = 0;

   MY_CLEAR_FILETIME(CTime);

   MY_CLEAR_FILETIME(ATime);

   MY_CLEAR_FILETIME(MTime);

   Attrib = 0;

+  IsAltStream = false;

+  IsDevice = false;

 }

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+static int FindAltStreamColon(CFSTR path)

+{

+  for (int i = 0;; i++)

+  {

+    FChar c = path[i];

+    if (c == 0)

+      return -1;

+    if (c == ':')

+    {

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

+    }

+  }

+}

+

+#endif

+

+bool CFileInfo::Find(CFSTR path)

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  if (IsDevicePath(path))

+  {

+    Clear();

+    Name = path + 4;

+

+    IsDevice = true;

+    if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */

+        path[5] == ':' && path[6] == 0)

+    {

+      FChar drive[4] = { path[4], ':', '\\', 0 };

+      UInt64 clusterSize, totalSize, freeSize;

+      if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize))

+      {

+        Size = totalSize;

+        return true;

+      }

+    }

+

+    NIO::CInFile inFile;

+    // ::OutputDebugStringW(path);

+    if (!inFile.Open(path))

+      return false;

+    // ::OutputDebugStringW(L"---");

+    if (inFile.SizeDefined)

+      Size = inFile.Size;

+    return true;

+  }

+  #endif

+

+  #if defined(_WIN32) && !defined(UNDER_CE)

+

+  int colonPos = FindAltStreamColon(path);

+  if (colonPos >= 0)

+  {

+    UString streamName = fs2us(path + (unsigned)colonPos);

+    FString filePath = path;

+    filePath.DeleteFrom(colonPos);

+    streamName += L":$DATA"; // change it!!!!

+    if (Find(filePath))

+    {

+      // if (IsDir())

+        Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;

+      Size = 0;

+      CStreamEnumerator enumerator(filePath);

+      for (;;)

+      {

+        CStreamInfo si;

+        bool found;

+        if (!enumerator.Next(si, found))

+          return false;

+        if (!found)

+        {

+          ::SetLastError(ERROR_FILE_NOT_FOUND);

+          return false;

+        }

+        if (si.Name.IsEqualToNoCase(streamName))

+        {

+          Name += us2fs(si.Name);

+          Name.DeleteFrom(Name.Len() - 6);

+          Size = si.Size;

+          IsAltStream = true;

+          return true;

+        }

+      }

+    }

+  }

   

-bool CFileInfo::Find(LPCTSTR wildcard)

-{

-  #ifdef SUPPORT_DEVICE_FILE

-  if (IsDeviceName(wildcard))

-  {

-    Clear();

-    IsDevice = true;

-    NIO::CInFile inFile;

-    if (!inFile.Open(wildcard))

-      return false;

-    Name = wildcard + 4;

-    if (inFile.LengthDefined)

-      Size = inFile.Length;

+  #endif

+

+  CFindFile finder;

+  if (finder.FindFirst(path, *this))

     return true;

+  #ifdef _WIN32

+  {

+    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"

+        )

+    {

+      unsigned len = MyStringLen(path);

+      if (len > 2 && path[0] == '\\' && path[1] == '\\')

+      {

+        int startPos = 2;

+        if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path))

+          startPos = kSuperUncPathPrefixSize;

+        int pos = FindCharPosInString(path + startPos, FTEXT('\\'));

+        if (pos >= 0)

+        {

+          pos += startPos + 1;

+          len -= pos;

+          int pos2 = FindCharPosInString(path + pos, FTEXT('\\'));

+          if (pos2 < 0 || pos2 == (int)len - 1)

+          {

+            FString s = path;

+            if (pos2 < 0)

+            {

+              pos2 = len;

+              s += FTEXT('\\');

+            }

+            s += FCHAR_ANY_MASK;

+            if (finder.FindFirst(s, *this))

+              if (Name == FTEXT("."))

+              {

+                Name.SetFrom(s.Ptr(pos), pos2);

+                return true;

+              }

+            ::SetLastError(lastError);

+          }

+        }

+      }

+    }

   }

   #endif

-  CFindFile finder;

-  return finder.FindFirst(wildcard, *this);

+  return false;

 }

 

-

-#ifndef _UNICODE

-bool CFileInfoW::Find(LPCWSTR wildcard)

-{

-  #ifdef SUPPORT_DEVICE_FILE

-  if (IsDeviceName(wildcard))

-  {

-    Clear();

-    IsDevice = true;

-    NIO::CInFile inFile;

-    if (!inFile.Open(wildcard))

-      return false;

-    Name = wildcard + 4;

-    if (inFile.LengthDefined)

-      Size = inFile.Length;

-    return true;

-  }

-  #endif

-  CFindFile finder;

-  return finder.FindFirst(wildcard, *this);

-}

-#endif

-

-bool DoesFileExist(LPCTSTR name)

+bool DoesFileExist(CFSTR name)

 {

   CFileInfo fi;

   return fi.Find(name) && !fi.IsDir();

 }

 

-bool DoesDirExist(LPCTSTR name)

+bool DoesDirExist(CFSTR name)

 {

   CFileInfo fi;

   return fi.Find(name) && fi.IsDir();

 }

-

-bool DoesFileOrDirExist(LPCTSTR name)

+bool DoesFileOrDirExist(CFSTR name)

 {

   CFileInfo fi;

   return fi.Find(name);

 }

 

-#ifndef _UNICODE

-bool DoesFileExist(LPCWSTR name)

-{

-  CFileInfoW fi;

-  return fi.Find(name) && !fi.IsDir();

-}

-

-bool DoesDirExist(LPCWSTR name)

-{

-  CFileInfoW fi;

-  return fi.Find(name) && fi.IsDir();

-}

-bool DoesFileOrDirExist(LPCWSTR name)

-{

-  CFileInfoW fi;

-  return fi.Find(name);

-}

-#endif

-

-/////////////////////////////////////

-// CEnumerator

-

 bool CEnumerator::NextAny(CFileInfo &fi)

 {

   if (_findFile.IsHandleAllocated())

@@ -311,44 +482,11 @@
   return (::GetLastError() == ERROR_NO_MORE_FILES);

 }

 

-#ifndef _UNICODE

-bool CEnumeratorW::NextAny(CFileInfoW &fi)

-{

-  if (_findFile.IsHandleAllocated())

-    return _findFile.FindNext(fi);

-  else

-    return _findFile.FindFirst(_wildcard, fi);

-}

-

-bool CEnumeratorW::Next(CFileInfoW &fi)

-{

-  for (;;)

-  {

-    if (!NextAny(fi))

-      return false;

-    if (!fi.IsDots())

-      return true;

-  }

-}

-

-bool CEnumeratorW::Next(CFileInfoW &fi, bool &found)

-{

-  if (Next(fi))

-  {

-    found = true;

-    return true;

-  }

-  found = false;

-  return (::GetLastError() == ERROR_NO_MORE_FILES);

-}

-

-#endif

-

 ////////////////////////////////

 // CFindChangeNotification

 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.

 

-bool CFindChangeNotification::Close()

+bool CFindChangeNotification::Close() throw()

 {

   if (!IsHandleAllocated())

     return true;

@@ -358,104 +496,83 @@
   return true;

 }

            

-HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)

+HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter)

 {

-  _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);

-  #ifdef WIN_LONG_PATH2

-  if (!IsHandleAllocated())

-  {

-    UString longPath;

-    if (GetLongPath(pathName, longPath))

-      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

-  }

-  #endif

-  return _handle;

-}

-

-#ifndef _UNICODE

-HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)

-{

+  #ifndef _UNICODE

   if (!g_IsNT)

-    return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);

-  _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);

-  #ifdef WIN_LONG_PATH

-  if (!IsHandleAllocated())

-  {

-    UString longPath;

-    if (GetLongPath(pathName, longPath))

-      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

-  }

+    _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter);

+  else

   #endif

+  {

+    IF_USE_MAIN_PATH

+    _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter);

+    #ifdef WIN_LONG_PATH

+    if (!IsHandleAllocated())

+    {

+      UString longPath;

+      if (GetSuperPath(path, longPath, USE_MAIN_PATH))

+        _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

+    }

+    #endif

+  }

   return _handle;

 }

-#endif

 

 #ifndef UNDER_CE

-bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)

-{

-  driveStrings.Clear();

-  UINT32 size = GetLogicalDriveStrings(0, NULL);

-  if (size == 0)

-    return false;

-  CSysString buffer;

-  UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));

-  if (newSize == 0)

-    return false;

-  if (newSize > size)

-    return false;

-  CSysString string;

-  for (UINT32 i = 0; i < newSize; i++)

-  {

-    TCHAR c = buffer[i];

-    if (c == TEXT('\0'))

-    {

-      driveStrings.Add(string);

-      string.Empty();

-    }

-    else

-      string += c;

-  }

-  if (!string.IsEmpty())

-    return false;

-  return true;

-}

 

-#ifndef _UNICODE

-bool MyGetLogicalDriveStrings(UStringVector &driveStrings)

+bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)

 {

   driveStrings.Clear();

-  if (g_IsNT)

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    driveStrings.Clear();

+    UINT32 size = GetLogicalDriveStrings(0, NULL);

+    if (size == 0)

+      return false;

+    AString buf;

+    UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size));

+    if (newSize == 0 || newSize > size)

+      return false;

+    AString s;

+    for (UINT32 i = 0; i < newSize; i++)

+    {

+      char c = buf[i];

+      if (c == '\0')

+      {

+        driveStrings.Add(fas2fs(s));

+        s.Empty();

+      }

+      else

+        s += c;

+    }

+    return s.IsEmpty();

+  }

+  else

+  #endif

   {

     UINT32 size = GetLogicalDriveStringsW(0, NULL);

     if (size == 0)

       return false;

-    UString buffer;

-    UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));

-    if (newSize == 0)

+    UString buf;

+    UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size));

+    if (newSize == 0 || newSize > size)

       return false;

-    if (newSize > size)

-      return false;

-    UString string;

+    UString s;

     for (UINT32 i = 0; i < newSize; i++)

     {

-      WCHAR c = buffer[i];

+      WCHAR c = buf[i];

       if (c == L'\0')

       {

-        driveStrings.Add(string);

-        string.Empty();

+        driveStrings.Add(us2fs(s));

+        s.Empty();

       }

       else

-        string += c;

+        s += c;

     }

-    return string.IsEmpty();

+    return s.IsEmpty();

   }

-  CSysStringVector driveStringsA;

-  bool res = MyGetLogicalDriveStrings(driveStringsA);

-  for (int i = 0; i < driveStringsA.Size(); i++)

-    driveStrings.Add(GetUnicodeString(driveStringsA[i]));

-  return res;

 }

-#endif

 

 #endif

 

diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
old mode 100755
new mode 100644
index 5affd83..1325253
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -1,12 +1,10 @@
 // Windows/FileFind.h

 

-#ifndef __WINDOWS_FILEFIND_H

-#define __WINDOWS_FILEFIND_H

+#ifndef __WINDOWS_FILE_FIND_H

+#define __WINDOWS_FILE_FIND_H

 

 #include "../Common/MyString.h"

-#include "../Common/Types.h"

 #include "Defs.h"

-#include "FileName.h"

 

 namespace NWindows {

 namespace NFile {

@@ -26,14 +24,13 @@
 class CFileInfoBase

 {

   bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }

-protected:

-  void Clear();

 public:

   UInt64 Size;

   FILETIME CTime;

   FILETIME ATime;

   FILETIME MTime;

   DWORD Attrib;

+  bool IsAltStream;

   bool IsDevice;

 

   /*

@@ -44,6 +41,11 @@
   #endif

   */

 

+  CFileInfoBase() { Clear(); }

+  void Clear() throw();

+

+  void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; }

+

   bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }

   bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }

   bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }

@@ -60,78 +62,80 @@
 

 struct CFileInfo: public CFileInfoBase

 {

-  CSysString Name;

+  FString Name;

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  // FString ShortName;

+  #endif

 

-  bool IsDots() const;

-  bool Find(LPCTSTR wildcard);

+  bool IsDots() const throw();

+  bool Find(CFSTR wildcard);

 };

 

-#ifdef _UNICODE

-typedef CFileInfo CFileInfoW;

-#else

-struct CFileInfoW: public CFileInfoBase

+class CFindFileBase

 {

-  UString Name;

-

-  bool IsDots() const;

-  bool Find(LPCWSTR wildcard);

-};

-#endif

-

-class CFindFile

-{

-  friend class CEnumerator;

+protected:

   HANDLE _handle;

 public:

   bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }

-  CFindFile(): _handle(INVALID_HANDLE_VALUE) {}

-  ~CFindFile() {  Close(); }

-  bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo);

-  bool FindNext(CFileInfo &fileInfo);

-  #ifndef _UNICODE

-  bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo);

-  bool FindNext(CFileInfoW &fileInfo);

-  #endif

-  bool Close();

+  CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {}

+  ~CFindFileBase() { Close(); }

+  bool Close() throw();

 };

 

-bool DoesFileExist(LPCTSTR name);

-bool DoesDirExist(LPCTSTR name);

-bool DoesFileOrDirExist(LPCTSTR name);

-#ifndef _UNICODE

-bool DoesFileExist(LPCWSTR name);

-bool DoesDirExist(LPCWSTR name);

-bool DoesFileOrDirExist(LPCWSTR name);

+class CFindFile: public CFindFileBase

+{

+public:

+  bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo);

+  bool FindNext(CFileInfo &fileInfo);

+};

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+

+struct CStreamInfo

+{

+  UString Name;

+  UInt64 Size;

+

+  UString GetReducedName() const;

+  bool IsMainStream() const throw();

+};

+

+class CFindStream: public CFindFileBase

+{

+public:

+  bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo);

+  bool FindNext(CStreamInfo &streamInfo);

+};

+

+class CStreamEnumerator

+{

+  CFindStream _find;

+  FString _filePath;

+

+  bool NextAny(CFileInfo &fileInfo);

+public:

+  CStreamEnumerator(const FString &filePath): _filePath(filePath) {}

+  bool Next(CStreamInfo &streamInfo, bool &found);

+};

+

 #endif

 

+bool DoesFileExist(CFSTR name);

+bool DoesDirExist(CFSTR name);

+bool DoesFileOrDirExist(CFSTR name);

+

 class CEnumerator

 {

   CFindFile _findFile;

-  CSysString _wildcard;

+  FString _wildcard;

+

   bool NextAny(CFileInfo &fileInfo);

 public:

-  CEnumerator(): _wildcard(NName::kAnyStringWildcard) {}

-  CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {}

+  CEnumerator(const FString &wildcard): _wildcard(wildcard) {}

   bool Next(CFileInfo &fileInfo);

   bool Next(CFileInfo &fileInfo, bool &found);

 };

 

-#ifdef _UNICODE

-typedef CEnumerator CEnumeratorW;

-#else

-class CEnumeratorW

-{

-  CFindFile _findFile;

-  UString _wildcard;

-  bool NextAny(CFileInfoW &fileInfo);

-public:

-  CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {}

-  CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {}

-  bool Next(CFileInfoW &fileInfo);

-  bool Next(CFileInfoW &fileInfo, bool &found);

-};

-#endif

-

 class CFindChangeNotification

 {

   HANDLE _handle;

@@ -140,22 +144,15 @@
   bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }

   CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}

   ~CFindChangeNotification() { Close(); }

-  bool Close();

-  HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter);

-  #ifndef _UNICODE

-  HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter);

-  #endif

+  bool Close() throw();

+  HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);

   bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }

 };

 

 #ifndef UNDER_CE

-bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings);

-#ifndef _UNICODE

-bool MyGetLogicalDriveStrings(UStringVector &driveStrings);

-#endif

+bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);

 #endif

 

 }}}

 

 #endif

-

diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
old mode 100755
new mode 100644
index a1a1bcc..3dcf5c1
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -2,161 +2,86 @@
 

 #include "StdAfx.h"

 

-#include "FileIO.h"

+#ifdef SUPPORT_DEVICE_FILE

+#include "../../C/Alloc.h"

+#endif

 

-#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE)

-#include "../Common/MyString.h"

-#endif

-#ifndef _UNICODE

-#include "../Common/StringConvert.h"

-#endif

+#include "FileIO.h"

+#include "FileName.h"

 

 #ifndef _UNICODE

 extern bool g_IsNT;

 #endif

 

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+

 namespace NWindows {

 namespace NFile {

 

 #ifdef SUPPORT_DEVICE_FILE

-bool IsDeviceName(LPCTSTR n)

+

+namespace NSystem

 {

-  #ifdef UNDER_CE

-  int len = (int)MyStringLen(n);

-  if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0)

-    return false;

-  if (n[4] != ':')

-    return false;

-  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));

-  #else

-  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')

-    return false;

-  int len = (int)MyStringLen(n);

-  if (len == 6 && n[5] == ':')

-    return true;

-  if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0)

-    return false;

-  for (int i = 17; i < len; i++)

-    if (n[i] < '0' || n[i] > '9')

-      return false;

-  #endif

-  return true;

-}

-

-#ifndef _UNICODE

-bool IsDeviceName(LPCWSTR n)

-{

-  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')

-    return false;

-  int len = (int)wcslen(n);

-  if (len == 6 && n[5] == ':')

-    return true;

-  if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0)

-    return false;

-  for (int i = 17; i < len; i++)

-    if (n[i] < '0' || n[i] > '9')

-      return false;

-  return true;

-}

-#endif

-#endif

-

-#if defined(WIN_LONG_PATH) && defined(_UNICODE)

-#define WIN_LONG_PATH2

-#endif

-

-#ifdef WIN_LONG_PATH

-bool GetLongPathBase(LPCWSTR s, UString &res)

-{

-  res.Empty();

-  int len = MyStringLen(s);

-  wchar_t c = s[0];

-  if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.'))

-    return true;

-  UString curDir;

-  bool isAbs = false;

-  if (len > 3)

-    isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z'));

-

-  if (!isAbs)

-    {

-      DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1));

-      curDir.ReleaseBuffer();

-      if (needLength == 0 || needLength > MAX_PATH)

-        return false;

-      if (curDir[curDir.Length() - 1] != L'\\')

-        curDir += L'\\';

-    }

-  res = UString(L"\\\\?\\") + curDir + s;

-  return true;

-}

-

-bool GetLongPath(LPCWSTR path, UString &longPath)

-{

-  if (GetLongPathBase(path, longPath))

-    return !longPath.IsEmpty();

-  return false;

+bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);

 }

 #endif

 

 namespace NIO {

 

-CFileBase::~CFileBase() { Close(); }

+/*

+WinXP-64 CreateFile():

+  ""             -  ERROR_PATH_NOT_FOUND

+  :stream        -  OK

+  .:stream       -  ERROR_PATH_NOT_FOUND

+  .\:stream      -  OK

+  

+  folder\:stream -  ERROR_INVALID_NAME

+  folder:stream  -  OK

 

-bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess,

+  c:\:stream     -  OK

+

+  c::stream      -  ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 )

+  c::stream      -  OK,                 if current dir is ROOT     ( c:\ )

+*/

+

+bool CFileBase::Create(CFSTR path, DWORD desiredAccess,

     DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

 {

   if (!Close())

     return false;

-  _handle = ::CreateFile(fileName, desiredAccess, shareMode,

-      (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

-      flagsAndAttributes, (HANDLE)NULL);

-  #ifdef WIN_LONG_PATH2

-  if (_handle == INVALID_HANDLE_VALUE)

-  {

-    UString longPath;

-    if (GetLongPath(fileName, longPath))

-      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,

-        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

-        flagsAndAttributes, (HANDLE)NULL);

-  }

-  #endif

+

   #ifdef SUPPORT_DEVICE_FILE

   IsDeviceFile = false;

   #endif

-  return (_handle != INVALID_HANDLE_VALUE);

-}

 

-#ifndef _UNICODE

-bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess,

-    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

-{

+  #ifndef _UNICODE

   if (!g_IsNT)

-    return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP),

-      desiredAccess, shareMode, creationDisposition, flagsAndAttributes);

-  if (!Close())

-    return false;

-  _handle = ::CreateFileW(fileName, desiredAccess, shareMode,

-    (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

-    flagsAndAttributes, (HANDLE)NULL);

-  #ifdef WIN_LONG_PATH

-  if (_handle == INVALID_HANDLE_VALUE)

   {

-    UString longPath;

-    if (GetLongPath(fileName, longPath))

-      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,

-        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

-        flagsAndAttributes, (HANDLE)NULL);

+    _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode,

+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);

   }

+  else

   #endif

-  #ifdef SUPPORT_DEVICE_FILE

-  IsDeviceFile = false;

-  #endif

+  {

+    IF_USE_MAIN_PATH

+      _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode,

+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);

+    #ifdef WIN_LONG_PATH

+    if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)

+    {

+      UString superPath;

+      if (GetSuperPath(path, superPath, USE_MAIN_PATH))

+        _handle = ::CreateFileW(superPath, desiredAccess, shareMode,

+            (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);

+    }

+    #endif

+  }

   return (_handle != INVALID_HANDLE_VALUE);

 }

-#endif

 

-bool CFileBase::Close()

+bool CFileBase::Close() throw()

 {

   if (_handle == INVALID_HANDLE_VALUE)

     return true;

@@ -166,17 +91,17 @@
   return true;

 }

 

-bool CFileBase::GetPosition(UInt64 &position) const

+bool CFileBase::GetPosition(UInt64 &position) const throw()

 {

   return Seek(0, FILE_CURRENT, position);

 }

 

-bool CFileBase::GetLength(UInt64 &length) const

+bool CFileBase::GetLength(UInt64 &length) const throw()

 {

   #ifdef SUPPORT_DEVICE_FILE

-  if (IsDeviceFile && LengthDefined)

+  if (IsDeviceFile && SizeDefined)

   {

-    length = Length;

+    length = Size;

     return true;

   }

   #endif

@@ -190,128 +115,212 @@
   return true;

 }

 

-bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const

+bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw()

 {

   #ifdef SUPPORT_DEVICE_FILE

-  if (IsDeviceFile && LengthDefined && moveMethod == FILE_END)

+  if (IsDeviceFile && SizeDefined && moveMethod == FILE_END)

   {

-    distanceToMove += Length;

+    distanceToMove += Size;

     moveMethod = FILE_BEGIN;

   }

   #endif

 

-  LARGE_INTEGER value;

-  value.QuadPart = distanceToMove;

-  value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);

-  if (value.LowPart == 0xFFFFFFFF)

+  LONG high = (LONG)(distanceToMove >> 32);

+  DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);

+  if (low == 0xFFFFFFFF)

     if (::GetLastError() != NO_ERROR)

       return false;

-  newPosition = value.QuadPart;

+  newPosition = (((UInt64)high) << 32) + low;

   return true;

 }

 

-bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)

+bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()

 {

   return Seek(position, FILE_BEGIN, newPosition);

 }

 

-bool CFileBase::SeekToBegin()

+bool CFileBase::SeekToBegin() const throw()

 {

   UInt64 newPosition;

   return Seek(0, newPosition);

 }

 

-bool CFileBase::SeekToEnd(UInt64 &newPosition)

+bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw()

 {

   return Seek(0, FILE_END, newPosition);

 }

 

-bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const

-{

-  BY_HANDLE_FILE_INFORMATION winFileInfo;

-  if (!::GetFileInformationByHandle(_handle, &winFileInfo))

-    return false;

-  fileInfo.Attrib = winFileInfo.dwFileAttributes;

-  fileInfo.CTime = winFileInfo.ftCreationTime;

-  fileInfo.ATime = winFileInfo.ftLastAccessTime;

-  fileInfo.MTime = winFileInfo.ftLastWriteTime;

-  fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes;

-  fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) +  winFileInfo.nFileSizeLow;

-  fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;

-  fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;

-  return true;

-}

-

-/////////////////////////

-// CInFile

+// ---------- CInFile ---------

 

 #ifdef SUPPORT_DEVICE_FILE

-void CInFile::GetDeviceLength()

+

+void CInFile::CorrectDeviceSize()

 {

-  if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile)

+  // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail

+  static const UInt32 kClusterSize = 1 << 14;

+  UInt64 pos = Size & ~(UInt64)(kClusterSize - 1);

+  UInt64 realNewPosition;

+  if (!Seek(pos, realNewPosition))

+    return;

+  Byte *buf = (Byte *)MidAlloc(kClusterSize);

+

+  bool needbackward = true;

+

+  for (;;)

   {

-    #ifdef UNDER_CE

-    LengthDefined = true;

-    Length = 128 << 20;

+    UInt32 processed = 0;

+    // up test is slow for "PhysicalDrive".

+    // processed size for latest block for "PhysicalDrive0" is 0.

+    if (!Read1(buf, kClusterSize, processed))

+      break;

+    if (processed == 0)

+      break;

+    needbackward = false;

+    Size = pos + processed;

+    if (processed != kClusterSize)

+      break;

+    pos += kClusterSize;

+  }

 

-    #else

-    PARTITION_INFORMATION partInfo;

-    LengthDefined = true;

-    Length = 0;

+  if (needbackward && pos != 0)

+  {

+    pos -= kClusterSize;

+    for (;;)

+    {

+      // break;

+      if (!Seek(pos, realNewPosition))

+        break;

+      if (!buf)

+      {

+        buf = (Byte *)MidAlloc(kClusterSize);

+        if (!buf)

+          break;

+      }

+      UInt32 processed = 0;

+      // that code doesn't work for "PhysicalDrive0"

+      if (!Read1(buf, kClusterSize, processed))

+        break;

+      if (processed != 0)

+      {

+        Size = pos + processed;

+        break;

+      }

+      if (pos == 0)

+        break;

+      pos -= kClusterSize;

+    }

+  }

+  MidFree(buf);

+}

 

-    if (GetPartitionInfo(&partInfo))

-      Length = partInfo.PartitionLength.QuadPart;

+

+void CInFile::CalcDeviceSize(CFSTR s)

+{

+  SizeDefined = false;

+  Size = 0;

+  if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile)

+    return;

+  #ifdef UNDER_CE

+

+  SizeDefined = true;

+  Size = 128 << 20;

+  

+  #else

+  

+  PARTITION_INFORMATION partInfo;

+  bool needCorrectSize = true;

+

+  /*

+    WinXP 64-bit:

+

+    HDD \\.\PhysicalDrive0 (MBR):

+      GetPartitionInfo == GeometryEx :  corrrect size? (includes tail)

+      Geometry   :  smaller than GeometryEx (no tail, maybe correct too?)

+      MyGetDiskFreeSpace : FAIL

+      Size correction is slow and block size (kClusterSize) must be small?

+

+    HDD partition \\.\N: (NTFS):

+      MyGetDiskFreeSpace   :  Size of NTFS clusters. Same size can be calculated after correction

+      GetPartitionInfo     :  size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS

+      Geometry / CdRomGeometry / GeometryEx :  size of HDD (not that partition)

+

+    CD-ROM drive (ISO):

+      MyGetDiskFreeSpace   :  correct size. Same size can be calculated after correction

+      Geometry == CdRomGeometry  :  smaller than corrrect size

+      GetPartitionInfo == GeometryEx :  larger than corrrect size

+

+    Floppy \\.\a: (FAT):

+      Geometry :  correct size.

+      CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL

+      correction works OK for FAT.

+      correction works OK for non-FAT, if kClusterSize = 512.

+  */

+

+  if (GetPartitionInfo(&partInfo))

+  {

+    Size = partInfo.PartitionLength.QuadPart;

+    SizeDefined = true;

+    needCorrectSize = false;

+    if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0)

+    {

+      FChar path[4] = { s[4], ':', '\\', 0 };

+      UInt64 clusterSize, totalSize, freeSize;

+      if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize))

+        Size = totalSize;

+      else

+        needCorrectSize = true;

+    }

+  }

+  

+  if (!SizeDefined)

+  {

+    my_DISK_GEOMETRY_EX geomEx;

+    SizeDefined = GetGeometryEx(&geomEx);

+    if (SizeDefined)

+      Size = geomEx.DiskSize.QuadPart;

     else

     {

       DISK_GEOMETRY geom;

-      if (!GetGeometry(&geom))

-        if (!GetCdRomGeometry(&geom))

-          LengthDefined = false;

-      if (LengthDefined)

-        Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;

+      SizeDefined = GetGeometry(&geom);

+      if (!SizeDefined)

+        SizeDefined = GetCdRomGeometry(&geom);

+      if (SizeDefined)

+        Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;

     }

-    // SeekToBegin();

-    #endif

   }

+  

+  if (needCorrectSize && SizeDefined && Size != 0)

+  {

+    CorrectDeviceSize();

+    SeekToBegin();

+  }

+

+  // SeekToBegin();

+  #endif

 }

 

 // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&

 

 #define MY_DEVICE_EXTRA_CODE \

-  IsDeviceFile = IsDeviceName(fileName); \

-  GetDeviceLength();

+  IsDeviceFile = IsDevicePath(fileName); \

+  CalcDeviceSize(fileName);

 #else

 #define MY_DEVICE_EXTRA_CODE

 #endif

 

-bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

 {

   bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);

   MY_DEVICE_EXTRA_CODE

   return res;

 }

 

-bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite)

+bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite)

 { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }

 

-bool CInFile::Open(LPCTSTR fileName)

+bool CInFile::Open(CFSTR fileName)

   { return OpenShared(fileName, false); }

 

-#ifndef _UNICODE

-bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

-{

-  bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);

-  MY_DEVICE_EXTRA_CODE

-  return res;

-}

-

-bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite)

-{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }

-

-bool CInFile::Open(LPCWSTR fileName)

-  { return OpenShared(fileName, false); }

-#endif

-

 // ReadFile and WriteFile functions in Windows have BUG:

 // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)

 // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES

@@ -323,7 +332,7 @@
 

 static UInt32 kChunkSizeMax = (1 << 22);

 

-bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize)

+bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()

 {

   DWORD processedLoc = 0;

   bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));

@@ -331,14 +340,14 @@
   return res;

 }

 

-bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize)

+bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw()

 {

   if (size > kChunkSizeMax)

     size = kChunkSizeMax;

   return Read1(data, size, processedSize);

 }

 

-bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)

+bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()

 {

   processedSize = 0;

   do

@@ -357,40 +366,29 @@
   return true;

 }

 

-/////////////////////////

-// COutFile

-

-bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

-  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }

+// ---------- COutFile ---------

 

 static inline DWORD GetCreationDisposition(bool createAlways)

   { return createAlways? CREATE_ALWAYS: CREATE_NEW; }

 

-bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)

-  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }

-

-bool COutFile::Create(LPCTSTR fileName, bool createAlways)

-  { return Open(fileName, GetCreationDisposition(createAlways)); }

-

-#ifndef _UNICODE

-

-bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

   { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }

 

-bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)

+bool COutFile::Open(CFSTR fileName, DWORD creationDisposition)

   { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }

 

-bool COutFile::Create(LPCWSTR fileName, bool createAlways)

+bool COutFile::Create(CFSTR fileName, bool createAlways)

   { return Open(fileName, GetCreationDisposition(createAlways)); }

 

-#endif

+bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes)

+  { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); }

 

-bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

+bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()

   { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }

 

-bool COutFile::SetMTime(const FILETIME *mTime) {  return SetTime(NULL, NULL, mTime); }

+bool COutFile::SetMTime(const FILETIME *mTime) throw() {  return SetTime(NULL, NULL, mTime); }

 

-bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize)

+bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw()

 {

   if (size > kChunkSizeMax)

     size = kChunkSizeMax;

@@ -400,7 +398,7 @@
   return res;

 }

 

-bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)

+bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw()

 {

   processedSize = 0;

   do

@@ -419,9 +417,9 @@
   return true;

 }

 

-bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }

+bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); }

 

-bool COutFile::SetLength(UInt64 length)

+bool COutFile::SetLength(UInt64 length) throw()

 {

   UInt64 newPosition;

   if (!Seek(length, newPosition))

diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
old mode 100755
new mode 100644
index 6f14817..96691b9
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -1,134 +1,199 @@
 // Windows/FileIO.h

 

-#ifndef __WINDOWS_FILEIO_H

-#define __WINDOWS_FILEIO_H

+#ifndef __WINDOWS_FILE_IO_H

+#define __WINDOWS_FILE_IO_H

 

-#include "../Common/Types.h"

+#if defined(_WIN32) && !defined(UNDER_CE)

+#include <winioctl.h>

+#endif

+

+#include "../Common/MyString.h"

+#include "../Common/MyBuffer.h"

 

 #include "Defs.h"

 

+#define _my_IO_REPARSE_TAG_MOUNT_POINT  (0xA0000003L)

+#define _my_IO_REPARSE_TAG_SYMLINK      (0xA000000CL)

+

+#define _my_SYMLINK_FLAG_RELATIVE 1

+

+#define my_FSCTL_SET_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER

+#define my_FSCTL_GET_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)     // REPARSE_DATA_BUFFER

+

 namespace NWindows {

 namespace NFile {

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink);

+#endif

+

+struct CReparseShortInfo

+{

+  unsigned Offset;

+  unsigned Size;

+

+  bool Parse(const Byte *p, size_t size);

+};

+

+struct CReparseAttr

+{

+  UInt32 Tag;

+  UInt32 Flags;

+  UString SubsName;

+  UString PrintName;

+

+  CReparseAttr(): Tag(0), Flags(0) {}

+  bool Parse(const Byte *p, size_t size);

+

+  bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction

+  bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }

+  bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }

+  // bool IsVolume() const;

+

+  bool IsOkNamePair() const;

+  UString GetPath() const;

+};

+

 namespace NIO {

 

-struct CByHandleFileInfo

-{

-  DWORD Attrib;

-  FILETIME CTime;

-  FILETIME ATime;

-  FILETIME MTime;

-  DWORD VolumeSerialNumber;

-  UInt64 Size;

-  DWORD NumberOfLinks;

-  UInt64 FileIndex;

-};

+bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);

+bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);

 

 class CFileBase

 {

 protected:

   HANDLE _handle;

   

-  bool Create(LPCTSTR fileName, DWORD desiredAccess,

+  bool Create(CFSTR path, DWORD desiredAccess,

       DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  #ifndef _UNICODE

-  bool Create(LPCWSTR fileName, DWORD desiredAccess,

-      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  #endif

 

 public:

-  #ifdef SUPPORT_DEVICE_FILE

-  bool IsDeviceFile;

-  bool LengthDefined;

-  UInt64 Length;

-  #endif

 

-  CFileBase(): _handle(INVALID_HANDLE_VALUE) {};

-  ~CFileBase();

-

-  bool Close();

-

-  bool GetPosition(UInt64 &position) const;

-  bool GetLength(UInt64 &length) const;

-

-  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const;

-  bool Seek(UInt64 position, UInt64 &newPosition);

-  bool SeekToBegin();

-  bool SeekToEnd(UInt64 &newPosition);

-  

-  bool GetFileInformation(CByHandleFileInfo &fileInfo) const;

-};

-

-#define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM

-#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)

-#define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)

-

-class CInFile: public CFileBase

-{

-  #ifdef SUPPORT_DEVICE_FILE

   bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,

-      LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const

+      LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const

   {

     return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,

         outBuffer, outSize, bytesReturned, overlapped));

   }

 

-  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer,

-      DWORD inSize, LPVOID outBuffer, DWORD outSize) const

+  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const

   {

-    DWORD ret;

-    return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0);

+    return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned);

   }

 

   bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const

-    { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); }

+  {

+    DWORD bytesReturned;

+    return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned);

+  }

+

+public:

+  #ifdef SUPPORT_DEVICE_FILE

+  bool IsDeviceFile;

+  bool SizeDefined;

+  UInt64 Size; // it can be larger than real available size

+  #endif

+

+  CFileBase(): _handle(INVALID_HANDLE_VALUE) {};

+  ~CFileBase() { Close(); }

+

+  bool Close() throw();

+

+  bool GetPosition(UInt64 &position) const throw();

+  bool GetLength(UInt64 &length) const throw();

+

+  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw();

+  bool Seek(UInt64 position, UInt64 &newPosition) const throw();

+  bool SeekToBegin() const throw();

+  bool SeekToEnd(UInt64 &newPosition) const throw();

+  

+  bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const

+    { return BOOLToBool(GetFileInformationByHandle(_handle, info)); }

+

+  static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info)

+  {

+    NIO::CFileBase file;

+    if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS))

+      return false;

+    return file.GetFileInformation(info);

+  }

+};

+

+#ifndef UNDER_CE

+#define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM

+#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)

+// #define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)

+

+// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP

+#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX  CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)

+

+struct my_DISK_GEOMETRY_EX

+{

+  DISK_GEOMETRY Geometry;

+  LARGE_INTEGER DiskSize;

+  BYTE Data[1];

+};

+#endif

+

+class CInFile: public CFileBase

+{

+  #ifdef SUPPORT_DEVICE_FILE

 

   #ifndef UNDER_CE

+  

   bool GetGeometry(DISK_GEOMETRY *res) const

     { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }

 

+  bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const

+    { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); }

+

   bool GetCdRomGeometry(DISK_GEOMETRY *res) const

     { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }

   

   bool GetPartitionInfo(PARTITION_INFORMATION *res)

     { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }

+  

   #endif

 

-  void GetDeviceLength();

+  void CorrectDeviceSize();

+  void CalcDeviceSize(CFSTR name);

+  

   #endif

 

 public:

-  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  bool OpenShared(LPCTSTR fileName, bool shareForWrite);

-  bool Open(LPCTSTR fileName);

-  #ifndef _UNICODE

-  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  bool OpenShared(LPCWSTR fileName, bool shareForWrite);

-  bool Open(LPCWSTR fileName);

+  bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool OpenShared(CFSTR fileName, bool shareForWrite);

+  bool Open(CFSTR fileName);

+

+  #ifndef UNDER_CE

+

+  bool OpenReparse(CFSTR fileName)

+  {

+    return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING,

+        FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);

+  }

+  

   #endif

-  bool Read1(void *data, UInt32 size, UInt32 &processedSize);

-  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize);

-  bool Read(void *data, UInt32 size, UInt32 &processedSize);

+

+  bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw();

+  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw();

+  bool Read(void *data, UInt32 size, UInt32 &processedSize) throw();

 };

 

 class COutFile: public CFileBase

 {

 public:

-  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  bool Open(LPCTSTR fileName, DWORD creationDisposition);

-  bool Create(LPCTSTR fileName, bool createAlways);

+  bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool Open(CFSTR fileName, DWORD creationDisposition);

+  bool Create(CFSTR fileName, bool createAlways);

+  bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes);

 

-  #ifndef _UNICODE

-  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

-  bool Open(LPCWSTR fileName, DWORD creationDisposition);

-  bool Create(LPCWSTR fileName, bool createAlways);

-  #endif

-

-  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);

-  bool SetMTime(const FILETIME *mTime);

-  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize);

-  bool Write(const void *data, UInt32 size, UInt32 &processedSize);

-  bool SetEndOfFile();

-  bool SetLength(UInt64 length);

+  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();

+  bool SetMTime(const FILETIME *mTime) throw();

+  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();

+  bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();

+  bool SetEndOfFile() throw();

+  bool SetLength(UInt64 length) throw();

 };

 

 }}}

diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp
new file mode 100644
index 0000000..1bd1d52
--- /dev/null
+++ b/CPP/Windows/FileLink.cpp
@@ -0,0 +1,426 @@
+// Windows/FileLink.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/CpuArch.h"

+

+#ifdef SUPPORT_DEVICE_FILE

+#include "../../C/Alloc.h"

+#endif

+

+#include "FileDir.h"

+#include "FileFind.h"

+#include "FileIO.h"

+#include "FileName.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NFile {

+

+using namespace NName;

+

+/*

+  Reparse Points (Junctions and Symbolic Links):

+  struct

+  {

+    UInt32 Tag;

+    UInt16 Size;     // not including starting 8 bytes

+    UInt16 Reserved; // = 0

+    

+    UInt16 SubstituteOffset; // offset in bytes from  start of namesChars

+    UInt16 SubstituteLen;    // size in bytes, it doesn't include tailed NUL

+    UInt16 PrintOffset;      // offset in bytes from  start of namesChars

+    UInt16 PrintLen;         // size in bytes, it doesn't include tailed NUL

+    

+    [UInt32] Flags;  // for Symbolic Links only.

+    

+    UInt16 namesChars[]

+  }

+

+  MOUNT_POINT (Junction point):

+    1) there is NUL wchar after path

+    2) Default Order in table:

+         Substitute Path

+         Print Path

+    3) pathnames can not contain dot directory names

+

+  SYMLINK:

+    1) there is no NUL wchar after path

+    2) Default Order in table:

+         Print Path

+         Substitute Path

+*/

+

+/*

+static const UInt32 kReparseFlags_Alias       = (1 << 29);

+static const UInt32 kReparseFlags_HighLatency = (1 << 30);

+static const UInt32 kReparseFlags_Microsoft   = ((UInt32)1 << 31);

+

+#define _my_IO_REPARSE_TAG_HSM          (0xC0000004L)

+#define _my_IO_REPARSE_TAG_HSM2         (0x80000006L)

+#define _my_IO_REPARSE_TAG_SIS          (0x80000007L)

+#define _my_IO_REPARSE_TAG_WIM          (0x80000008L)

+#define _my_IO_REPARSE_TAG_CSV          (0x80000009L)

+#define _my_IO_REPARSE_TAG_DFS          (0x8000000AL)

+#define _my_IO_REPARSE_TAG_DFSR         (0x80000012L)

+*/

+

+#define Get16(p) GetUi16(p)

+#define Get32(p) GetUi32(p)

+

+#define Set16(p, v) SetUi16(p, v)

+#define Set32(p, v) SetUi32(p, v)

+

+static const wchar_t *k_LinkPrefix = L"\\??\\";

+static const unsigned k_LinkPrefix_Size = 4;

+

+static const bool IsLinkPrefix(const wchar_t *s)

+{

+  return IsString1PrefixedByString2(s, k_LinkPrefix);

+}

+

+/*

+static const wchar_t *k_VolumePrefix = L"Volume{";

+static const bool IsVolumeName(const wchar_t *s)

+{

+  return IsString1PrefixedByString2(s, k_VolumePrefix);

+}

+*/

+

+void WriteString(Byte *dest, const wchar_t *path)

+{

+  for (;;)

+  {

+    wchar_t c = *path++;

+    if (c == 0)

+      return;

+    Set16(dest, (UInt16)c);

+    dest += 2;

+  }

+}

+

+bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)

+{

+  bool isAbs = IsAbsolutePath(path);

+  if (!isAbs && !isSymLink)

+    return false;

+

+  bool needPrintName = true;

+

+  if (IsSuperPath(path))

+  {

+    path += kSuperPathPrefixSize;

+    if (!IsDrivePath(path))

+      needPrintName = false;

+  }

+

+  const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0;

+    

+  unsigned len2 = MyStringLen(path) * 2;

+  const unsigned len1 = len2 + add_Prefix_Len * 2;

+  if (!needPrintName)

+    len2 = 0;

+

+  unsigned totalNamesSize = (len1 + len2);

+

+  /* some WIM imagex software uses old scheme for symbolic links.

+     so we can old scheme for byte to byte compatibility */

+

+  bool newOrderScheme = isSymLink;

+  // newOrderScheme = false;

+

+  if (!newOrderScheme)

+    totalNamesSize += 2 * 2;

+

+  const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize;

+  dest.Alloc(size);

+  memset(dest, 0, size);

+  const UInt32 tag = isSymLink ?

+      _my_IO_REPARSE_TAG_SYMLINK :

+      _my_IO_REPARSE_TAG_MOUNT_POINT;

+  Byte *p = dest;

+  Set32(p, tag);

+  Set16(p + 4, (UInt16)(size - 8));

+  Set16(p + 6, 0);

+  p += 8;

+

+  unsigned subOffs = 0;

+  unsigned printOffs = 0;

+  if (newOrderScheme)

+    subOffs = len2;

+  else

+    printOffs = len1 + 2;

+

+  Set16(p + 0, (UInt16)subOffs);

+  Set16(p + 2, (UInt16)len1);

+  Set16(p + 4, (UInt16)printOffs);

+  Set16(p + 6, (UInt16)len2);

+

+  p += 8;

+  if (isSymLink)

+  {

+    UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE;

+    Set32(p, flags);

+    p += 4;

+  }

+

+  if (add_Prefix_Len != 0)

+    WriteString(p + subOffs, k_LinkPrefix);

+  WriteString(p + subOffs + add_Prefix_Len * 2, path);

+  if (needPrintName)

+    WriteString(p + printOffs, path);

+  return true;

+}

+

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

+}

+

+bool CReparseAttr::Parse(const Byte *p, size_t size)

+{

+  if (size < 8)

+    return false;

+  Tag = Get32(p);

+  UInt32 len = Get16(p + 4);

+  if (len + 8 > size)

+    return false;

+  /*

+  if ((type & kReparseFlags_Alias) == 0 ||

+      (type & kReparseFlags_Microsoft) == 0 ||

+      (type & 0xFFFF) != 3)

+  */

+  if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&

+      Tag != _my_IO_REPARSE_TAG_SYMLINK)

+    // return true;

+    return false;

+

+  if (Get16(p + 6) != 0) // padding

+    return false;

+  

+  p += 8;

+  size -= 8;

+  

+  if (len != size) // do we need that check?

+    return false;

+  

+  if (len < 8)

+    return false;

+  unsigned subOffs = Get16(p);

+  unsigned subLen = Get16(p + 2);

+  unsigned printOffs = Get16(p + 4);

+  unsigned printLen = Get16(p + 6);

+  len -= 8;

+  p += 8;

+

+  Flags = 0;

+  if (Tag == _my_IO_REPARSE_TAG_SYMLINK)

+  {

+    if (len < 4)

+      return false;

+    Flags = Get32(p);

+    len -= 4;

+    p += 4;

+  }

+

+  if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)

+    return false;

+  if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)

+    return false;

+  GetString(p + subOffs, subLen >> 1, SubsName);

+  GetString(p + printOffs, printLen >> 1, PrintName);

+

+  return true;

+}

+

+bool CReparseShortInfo::Parse(const Byte *p, size_t size)

+{

+  const Byte *start = p;

+  Offset= 0;

+  Size = 0;

+  if (size < 8)

+    return false;

+  UInt32 Tag = Get32(p);

+  UInt32 len = Get16(p + 4);

+  if (len + 8 > size)

+    return false;

+  /*

+  if ((type & kReparseFlags_Alias) == 0 ||

+      (type & kReparseFlags_Microsoft) == 0 ||

+      (type & 0xFFFF) != 3)

+  */

+  if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&

+      Tag != _my_IO_REPARSE_TAG_SYMLINK)

+    // return true;

+    return false;

+

+  if (Get16(p + 6) != 0) // padding

+    return false;

+  

+  p += 8;

+  size -= 8;

+  

+  if (len != size) // do we need that check?

+    return false;

+  

+  if (len < 8)

+    return false;

+  unsigned subOffs = Get16(p);

+  unsigned subLen = Get16(p + 2);

+  unsigned printOffs = Get16(p + 4);

+  unsigned printLen = Get16(p + 6);

+  len -= 8;

+  p += 8;

+

+  // UInt32 Flags = 0;

+  if (Tag == _my_IO_REPARSE_TAG_SYMLINK)

+  {

+    if (len < 4)

+      return false;

+    // Flags = Get32(p);

+    len -= 4;

+    p += 4;

+  }

+

+  if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)

+    return false;

+  if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)

+    return false;

+

+  Offset = (unsigned)(p - start) + subOffs;

+  Size = subLen;

+  return true;

+}

+

+bool CReparseAttr::IsOkNamePair() const

+{

+  if (IsLinkPrefix(SubsName))

+  {

+    if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size)))

+      return PrintName.IsEmpty();

+    if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0)

+      return true;

+  }

+  return wcscmp(SubsName, PrintName) == 0;

+}

+

+/*

+bool CReparseAttr::IsVolume() const

+{

+  if (!IsLinkPrefix(SubsName))

+    return false;

+  return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size));

+}

+*/

+

+UString CReparseAttr::GetPath() const

+{

+  UString s = SubsName;

+  if (IsLinkPrefix(s))

+  {

+    s.ReplaceOneCharAtPos(1, '\\');

+    if (IsDrivePath(s.Ptr(k_LinkPrefix_Size)))

+      s.DeleteFrontal(k_LinkPrefix_Size);

+  }

+  return s;

+}

+

+

+#ifdef SUPPORT_DEVICE_FILE

+

+namespace NSystem

+{

+bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);

+}

+#endif

+

+#ifndef UNDER_CE

+

+namespace NIO {

+

+bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo)

+{

+  reparseData.Free();

+  CInFile file;

+  if (!file.OpenReparse(path))

+    return false;

+

+  if (fileInfo)

+    file.GetFileInformation(fileInfo);

+

+  const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;

+  CByteArr buf(kBufSize);

+  DWORD returnedSize;

+  if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))

+    return false;

+  reparseData.CopyFrom(buf, returnedSize);

+  return true;

+}

+

+static bool CreatePrefixDirOfFile(CFSTR path)

+{

+  FString path2 = path;

+  int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR);

+  if (pos < 0)

+    return true;

+  #ifdef _WIN32

+  if (pos == 2 && path2[1] == L':')

+    return true; // we don't create Disk folder;

+  #endif

+  path2.DeleteFrom(pos);

+  return NDir::CreateComplexDir(path2);

+}

+

+// If there is Reprase data already, it still writes new Reparse data

+bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)

+{

+  NFile::NFind::CFileInfo fi;

+  if (fi.Find(path))

+  {

+    if (fi.IsDir() != isDir)

+    {

+      ::SetLastError(ERROR_DIRECTORY);

+      return false;

+    }

+  }

+  else

+  {

+    if (isDir)

+    {

+      if (!NDir::CreateComplexDir(path))

+        return false;

+    }

+    else

+    {

+      CreatePrefixDirOfFile(path);

+      COutFile file;

+      if (!file.Create(path, CREATE_NEW))

+        return false;

+    }

+  }

+

+  COutFile file;

+  if (!file.Open(path,

+      FILE_SHARE_WRITE,

+      OPEN_EXISTING,

+      FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))

+    return false;

+

+  DWORD returnedSize;

+  if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize))

+    return false;

+  return true;

+}

+

+}

+

+#endif

+

+}}

diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp
old mode 100755
new mode 100644
index 857e70d..01c4a94
--- a/CPP/Windows/FileMapping.cpp
+++ b/CPP/Windows/FileMapping.cpp
@@ -2,7 +2,7 @@
 

 #include "StdAfx.h"

 

-#include "Windows/FileMapping.h"

+#include "FileMapping.h"

 

 namespace NWindows {

 namespace NFile {

diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h
old mode 100755
new mode 100644
index 138a175..27d076b
--- a/CPP/Windows/FileMapping.h
+++ b/CPP/Windows/FileMapping.h
@@ -3,7 +3,7 @@
 #ifndef __WINDOWS_FILEMAPPING_H

 #define __WINDOWS_FILEMAPPING_H

 

-#include "Common/Types.h"

+#include "../Common/MyTypes.h"

 

 #include "Handle.h"

 

@@ -18,7 +18,11 @@
     return ::GetLastError();

   }

 

-  WRes Open(DWORD desiredAccess, LPCTSTR name)

+  WRes Open(DWORD

+      #ifndef UNDER_CE

+      desiredAccess

+      #endif

+      , LPCTSTR name)

   {

     #ifdef UNDER_CE

     WRes res = Create(PAGE_READONLY, 0, name);

diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
old mode 100755
new mode 100644
index 4e55a53..9189ceb
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -2,49 +2,686 @@
 

 #include "StdAfx.h"

 

-#include "Windows/FileName.h"

-#include "Common/Wildcard.h"

+#include "FileName.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

 

 namespace NWindows {

 namespace NFile {

 namespace NName {

 

-void NormalizeDirPathPrefix(CSysString &dirPath)

+#ifndef USE_UNICODE_FSTRING

+void NormalizeDirPathPrefix(FString &dirPath)

 {

   if (dirPath.IsEmpty())

     return;

-  if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1)

-    dirPath += kDirDelimiter;

+  if (dirPath.Back() != FCHAR_PATH_SEPARATOR)

+    dirPath += FCHAR_PATH_SEPARATOR;

 }

+#endif

 

-#ifndef _UNICODE

 void NormalizeDirPathPrefix(UString &dirPath)

 {

   if (dirPath.IsEmpty())

     return;

-  if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1)

-    dirPath += wchar_t(kDirDelimiter);

+  if (dirPath.Back() != WCHAR_PATH_SEPARATOR)

+    dirPath += WCHAR_PATH_SEPARATOR;

+}

+

+

+#ifdef _WIN32

+

+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_UNC_WITH_SLASH(s) ( \

+  ((s)[0] == 'U' || (s)[0] == 'u') && \

+  ((s)[1] == 'N' || (s)[1] == 'n') && \

+  ((s)[2] == 'C' || (s)[2] == 'c') && \

+   (s)[3] == '\\')

+

+bool IsDevicePath(CFSTR s) throw()

+{

+  #ifdef UNDER_CE

+

+  s = s;

+  return false;

+  /*

+  // actually we don't know the way to open device file in WinCE.

+  unsigned len = MyStringLen(s);

+  if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0)

+    return false;

+  if (s[4] != ':')

+    return false;

+  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));

+  */

+  

+  #else

+  

+  if (!IS_DEVICE_PATH(s))

+    return false;

+  unsigned len = MyStringLen(s);

+  if (len == 6 && s[5] == ':')

+    return true;

+  if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0)

+    return false;

+  for (unsigned i = 17; i < len; i++)

+    if (s[i] < '0' || s[i] > '9')

+      return false;

+  return true;

+  

+  #endif

+}

+

+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()

+{

+  return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s);

+}

+

+static const unsigned kDrivePrefixSize = 3; /* c:\ */

+

+#ifndef USE_UNICODE_FSTRING

+

+static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw()

+{

+  // Network path: we look "server\path\" as root prefix

+  int pos = FindCharPosInString(s, '\\');

+  if (pos < 0)

+    return 0;

+  int pos2 = FindCharPosInString(s + pos + 1, '\\');

+  if (pos2 < 0)

+    return 0;

+  return pos + pos2 + 2;

+}

+

+static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw()

+{

+  if (IsDrivePath(s))

+    return kDrivePrefixSize;

+  if (s[0] != '\\' || s[1] != '\\')

+    return 0;

+  unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);

+  return (size == 0) ? 0 : 2 + size;

+}

+

+static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()

+{

+  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))

+  {

+    unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);

+    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;

+  }

+  // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"

+  int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR);

+  if (pos < 0)

+    return 0;

+  return kSuperPathPrefixSize + pos + 1;

+}

+

+unsigned GetRootPrefixSize(CFSTR s) throw()

+{

+  if (IS_DEVICE_PATH(s))

+    return kDevicePathPrefixSize;

+  if (IsSuperPath(s))

+    return GetRootPrefixSize_Of_SuperPath(s);

+  return GetRootPrefixSize_Of_SimplePath(s);

+}

+

+#endif // USE_UNICODE_FSTRING

+

+static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()

+{

+  // Network path: we look "server\path\" as root prefix

+  int pos = FindCharPosInString(s, L'\\');

+  if (pos < 0)

+    return 0;

+  int pos2 = FindCharPosInString(s + pos + 1, L'\\');

+  if (pos2 < 0)

+    return 0;

+  return pos + pos2 + 2;

+}

+

+static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()

+{

+  if (IsDrivePath(s))

+    return kDrivePrefixSize;

+  if (s[0] != '\\' || s[1] != '\\')

+    return 0;

+  unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);

+  return (size == 0) ? 0 : 2 + size;

+}

+

+static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()

+{

+  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))

+  {

+    unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);

+    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;

+  }

+  // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"

+  int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\');

+  if (pos < 0)

+    return 0;

+  return kSuperPathPrefixSize + pos + 1;

+}

+

+unsigned GetRootPrefixSize(const wchar_t *s) throw()

+{

+  if (IS_DEVICE_PATH(s))

+    return kDevicePathPrefixSize;

+  if (IsSuperPath(s))

+    return GetRootPrefixSize_Of_SuperPath(s);

+  return GetRootPrefixSize_Of_SimplePath(s);

+}

+

+#else // _WIN32

+

+bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR }

+

+#ifndef USE_UNICODE_FSTRING

+unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }

+#endif

+unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }

+

+#endif // _WIN32

+

+

+#ifndef UNDER_CE

+

+static bool GetCurDir(UString &path)

+{

+  path.Empty();

+  DWORD needLength;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);

+    path = fs2us(fas2fs(s));

+  }

+  else

+  #endif

+  {

+    WCHAR s[MAX_PATH + 2];

+    s[0] = 0;

+    needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);

+    path = s;

+  }

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+static bool ResolveDotsFolders(UString &s)

+{

+  #ifdef _WIN32

+  s.Replace(L'/', WCHAR_PATH_SEPARATOR);

+  #endif

+  for (int i = 0;;)

+  {

+    wchar_t c = s[i];

+    if (c == 0)

+      return true;

+    if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR))

+    {

+      wchar_t c1 = s[i + 1];

+      if (c1 == '.')

+      {

+        wchar_t c2 = s[i + 2];

+        if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0)

+        {

+          if (i == 0)

+            return false;

+          int k = i - 2;

+          for (; k >= 0; k--)

+            if (s[k] == WCHAR_PATH_SEPARATOR)

+              break;

+          unsigned num;

+          if (k >= 0)

+          {

+            num = i + 2 - k;

+            i = k;

+          }

+          else

+          {

+            num = (c2 == 0 ? (i + 2) : (i + 3));

+            i = 0;

+          }

+          s.Delete(i, num);

+          continue;

+        }

+      }

+      else

+      {

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

+        }

+      }

+    }

+    i++;

+  }

+}

+

+#endif // UNDER_CE

+

+#define LONG_PATH_DOTS_FOLDERS_PARSING

+

+

+/*

+Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\

+To solve that problem we check such path:

+   - super path contains        "." or ".." - we use kSuperPathType_UseOnlySuper

+   - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain

+*/

+#ifdef LONG_PATH_DOTS_FOLDERS_PARSING

+#ifndef UNDER_CE

+static bool AreThereDotsFolders(CFSTR s)

+{

+  for (unsigned i = 0;; i++)

+  {

+    FChar c = s[i];

+    if (c == 0)

+      return false;

+    if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR))

+    {

+      FChar c1 = s[i + 1];

+      if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR ||

+          (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR)))

+        return true;

+    }

+  }

 }

 #endif

+#endif // LONG_PATH_DOTS_FOLDERS_PARSING

 

-const wchar_t kExtensionDelimiter = L'.';

+#ifdef WIN_LONG_PATH

 

-void SplitNameToPureNameAndExtension(const UString &fullName,

-    UString &pureName, UString &extensionDelimiter, UString &extension)

+/*

+Most of Windows versions have problems, if some file or dir name

+contains '.' or ' ' at the end of name (Bad Path).

+To solve that problem, we always use Super Path ("\\?\" prefix and full path)

+in such cases. Note that "." and ".." are not bad names.

+

+There are 3 cases:

+  1) If the path is already Super Path, we use that path

+  2) If the path is not Super Path :

+     2.1) Bad Path;  we use only Super Path.

+     2.2) Good Path; we use Main Path. If it fails, we use Super Path.

+

+ NeedToUseOriginalPath returns:

+    kSuperPathType_UseOnlyMain    : Super already

+    kSuperPathType_UseOnlySuper    : not Super, Bad Path

+    kSuperPathType_UseMainAndSuper : not Super, Good Path

+*/

+

+int GetUseSuperPathType(CFSTR s) throw()

 {

-  int index = fullName.ReverseFind(kExtensionDelimiter);

-  if (index < 0)

+  if (IsSuperOrDevicePath(s))

   {

-    pureName = fullName;

-    extensionDelimiter.Empty();

-    extension.Empty();

+    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING

+    if ((s)[2] != '.')

+      if (AreThereDotsFolders(s + kSuperPathPrefixSize))

+        return kSuperPathType_UseOnlySuper;

+    #endif

+    return kSuperPathType_UseOnlyMain;

+  }

+

+  for (unsigned i = 0;; i++)

+  {

+    FChar c = s[i];

+    if (c == 0)

+      return kSuperPathType_UseMainAndSuper;

+    if (c == '.' || c == ' ')

+    {

+      FChar c2 = s[i + 1];

+      if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR)

+      {

+        // if it's "." or "..", it's not bad name.

+        if (c == '.')

+        {

+          if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)

+            continue;

+          if (s[i - 1] == '.')

+          {

+            if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR)

+              continue;

+          }

+        }

+        return kSuperPathType_UseOnlySuper;

+      }

+    }

+  }

+}

+

+

+/*

+   returns false in two cases:

+     - if GetCurDir was used, and GetCurDir returned error.

+     - if we can't resolve ".." name.

+   if path is ".", "..", res is empty.

+   if it's Super Path already, res is empty.

+   for \**** , and if GetCurDir is not drive (c:\), res is empty

+   for absolute paths, returns true, res is Super path.

+*/

+

+

+static bool GetSuperPathBase(CFSTR s, UString &res)

+{

+  res.Empty();

+  

+  FChar c = s[0];

+  if (c == 0)

+    return true;

+  if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))

+    return true;

+  

+  if (IsSuperOrDevicePath(s))

+  {

+    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING

+    

+    if ((s)[2] == '.')

+      return true;

+

+    // we will return true here, so we will try to use these problem paths.

+

+    if (!AreThereDotsFolders(s + kSuperPathPrefixSize))

+      return true;

+    

+    UString temp = fs2us(s);

+    unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp);

+    if (fixedSize == 0)

+      return true;

+

+    UString rem = &temp[fixedSize];

+    if (!ResolveDotsFolders(rem))

+      return true;

+

+    temp.DeleteFrom(fixedSize);

+    res += temp;

+    res += rem;

+    

+    #endif

+

+    return true;

+  }

+

+  if (c == CHAR_PATH_SEPARATOR)

+  {

+    if (s[1] == CHAR_PATH_SEPARATOR)

+    {

+      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?

+        return false;

+      UString rem = &temp[fixedSize];

+      if (!ResolveDotsFolders(rem))

+        return false;

+      res += kSuperUncPrefix;

+      temp.DeleteFrom(fixedSize);

+      res += temp;

+      res += rem;

+      return true;

+    }

   }

   else

   {

-    pureName = fullName.Left(index);

-    extensionDelimiter = kExtensionDelimiter;

-    extension = fullName.Mid(index + 1);

+    if (IsDrivePath(s))

+    {

+      UString temp = fs2us(s);

+      UString rem = &temp[kDrivePrefixSize];

+      if (!ResolveDotsFolders(rem))

+        return true;

+      res += kSuperPathPrefix;

+      temp.DeleteFrom(kDrivePrefixSize);

+      res += temp;

+      res += rem;

+      return true;

+    }

   }

+

+  UString curDir;

+  if (!GetCurDir(curDir))

+    return false;

+  if (curDir.Back() != WCHAR_PATH_SEPARATOR)

+    curDir += WCHAR_PATH_SEPARATOR;

+

+  unsigned fixedSizeStart = 0;

+  unsigned fixedSize = 0;

+  const wchar_t *superMarker = NULL;

+  if (IsSuperPath(curDir))

+  {

+    fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);

+    if (fixedSize == 0)

+      return false;

+  }

+  else

+  {

+    if (IsDrivePath(curDir))

+    {

+      superMarker = kSuperPathPrefix;

+      fixedSize = kDrivePrefixSize;

+    }

+    else

+    {

+      if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR)

+        return false;

+      fixedSizeStart = 2;

+      fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);

+      if (fixedSize == 0)

+        return false;

+      superMarker = kSuperUncPrefix;

+    }

+  }

+  

+  UString temp;

+  if (c == CHAR_PATH_SEPARATOR)

+  {

+    temp = fs2us(s + 1);

+  }

+  else

+  {

+    temp += &curDir[fixedSizeStart + fixedSize];

+    temp += fs2us(s);

+  }

+  if (!ResolveDotsFolders(temp))

+    return false;

+  if (superMarker)

+    res += superMarker;

+  res += curDir.Mid(fixedSizeStart, fixedSize);

+  res += temp;

+  return true;

+}

+

+

+/*

+  In that case if GetSuperPathBase doesn't return new path, we don't need

+  to use same path that was used as main path

+                        

+  GetSuperPathBase  superPath.IsEmpty() onlyIfNew

+     false            *                *          GetCurDir Error

+     true            false             *          use Super path

+     true            true             true        don't use any path, we already used mainPath

+     true            true             false       use main path as Super Path, we don't try mainMath

+                                                  That case is possible now if GetCurDir returns unknow

+                                                  type of path (not drive and not network)

+

+  We can change that code if we want to try mainPath, if GetSuperPathBase returns error,

+  and we didn't try mainPath still.

+  If we want to work that way, we don't need to use GetSuperPathBase return code.

+*/

+

+bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)

+{

+  if (GetSuperPathBase(path, superPath))

+  {

+    if (superPath.IsEmpty())

+    {

+      // actually the only possible when onlyIfNew == true and superPath is empty

+      // is case when

+

+      if (onlyIfNew)

+        return false;

+      superPath = fs2us(path);

+    }

+    return true;

+  }

+  return false;

+}

+

+bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)

+{

+  if (!GetSuperPathBase(s1, d1) ||

+      !GetSuperPathBase(s2, d2))

+    return false;

+  if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)

+    return false;

+  if (d1.IsEmpty()) d1 = fs2us(s1);

+  if (d2.IsEmpty()) d2 = fs2us(s2);

+  return true;

+}

+

+

+/*

+// returns true, if we need additional use with New Super path.

+bool GetSuperPath(CFSTR path, UString &superPath)

+{

+  if (GetSuperPathBase(path, superPath))

+    return !superPath.IsEmpty();

+  return false;

+}

+*/

+#endif // WIN_LONG_PATH

+

+bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)

+{

+  res = s;

+

+  #ifdef UNDER_CE

+

+  if (s[0] != CHAR_PATH_SEPARATOR)

+  {

+    if (!dirPrefix)

+      return false;

+    res = dirPrefix;

+    res += s;

+  }

+

+  #else

+

+  unsigned prefixSize = GetRootPrefixSize(s);

+  if (prefixSize != 0)

+  {

+    if (!AreThereDotsFolders(s + prefixSize))

+      return true;

+    

+    UString rem = fs2us(s + prefixSize);

+    if (!ResolveDotsFolders(rem))

+      return true; // maybe false;

+    res.DeleteFrom(prefixSize);

+    res += us2fs(rem);

+    return true;

+  }

+

+  /*

+  FChar c = s[0];

+  if (c == 0)

+    return true;

+  if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))

+    return true;

+  if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR)

+    return true;

+  if (IsDrivePath(s))

+    return true;

+  */

+

+  UString curDir;

+  if (dirPrefix)

+    curDir = fs2us(dirPrefix);

+  else

+  {

+    if (!GetCurDir(curDir))

+      return false;

+  }

+  if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR)

+    curDir += WCHAR_PATH_SEPARATOR;

+

+  unsigned fixedSize = 0;

+

+  #ifdef _WIN32

+

+  if (IsSuperPath(curDir))

+  {

+    fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);

+    if (fixedSize == 0)

+      return false;

+  }

+  else

+  {

+    if (IsDrivePath(curDir))

+      fixedSize = kDrivePrefixSize;

+    else

+    {

+      if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR)

+        return false;

+      fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);

+      if (fixedSize == 0)

+        return false;

+      fixedSize += 2;

+    }

+  }

+

+  #endif // _WIN32

+  

+  UString temp;

+  if (s[0] == CHAR_PATH_SEPARATOR)

+  {

+    temp = fs2us(s + 1);

+  }

+  else

+  {

+    temp += curDir.Ptr(fixedSize);

+    temp += fs2us(s);

+  }

+  if (!ResolveDotsFolders(temp))

+    return false;

+  curDir.DeleteFrom(fixedSize);

+  res = us2fs(curDir);

+  res += us2fs(temp);

+  

+  #endif // UNDER_CE

+

+  return true;

+}

+

+bool GetFullPath(CFSTR path, FString &fullPath)

+{

+  return GetFullPath(NULL, path, fullPath);

 }

 

 }}}

diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
old mode 100755
new mode 100644
index b980236..7455654
--- a/CPP/Windows/FileName.h
+++ b/CPP/Windows/FileName.h
@@ -1,9 +1,7 @@
 // Windows/FileName.h

 

-#ifndef __WINDOWS_FILENAME_H

-#define __WINDOWS_FILENAME_H

-

-#include "../../C/Types.h"

+#ifndef __WINDOWS_FILE_NAME_H

+#define __WINDOWS_FILE_NAME_H

 

 #include "../Common/MyString.h"

 

@@ -11,16 +9,65 @@
 namespace NFile {

 namespace NName {

 

-const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR;

-const TCHAR kAnyStringWildcard = '*';

+void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty

+void NormalizeDirPathPrefix(UString &dirPath);

 

-void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\'

-#ifndef _UNICODE

-void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'

+#ifdef _WIN32

+

+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 IsDrivePath(const wchar_t *s) throw();

+bool IsSuperPath(const wchar_t *s) throw();

+bool IsSuperOrDevicePath(const wchar_t *s) throw();

+

+#ifndef USE_UNICODE_FSTRING

+bool IsDrivePath(CFSTR s) throw();

+bool IsSuperPath(CFSTR s) throw();

+bool IsSuperOrDevicePath(CFSTR s) throw();

 #endif

 

-void SplitNameToPureNameAndExtension(const UString &fullName,

-    UString &pureName, UString &extensionDelimiter, UString &extension);

+#endif // _WIN32

+

+bool IsAbsolutePath(const wchar_t *s) throw();

+unsigned GetRootPrefixSize(const wchar_t *s) throw();

+

+#ifdef WIN_LONG_PATH

+

+const int kSuperPathType_UseOnlyMain = 0;

+const int kSuperPathType_UseOnlySuper = 1;

+const int kSuperPathType_UseMainAndSuper = 2;

+

+int GetUseSuperPathType(CFSTR s) throw();

+bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew);

+bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);

+

+#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper)

+#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper)

+

+#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain)

+#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain)

+

+#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH)

+#define IF_USE_MAIN_PATH_2(x1, x2) \

+    int __useSuperPathType1 = GetUseSuperPathType(x1); \

+    int __useSuperPathType2 = GetUseSuperPathType(x2); \

+    if (USE_MAIN_PATH_2)

+

+#else

+

+#define IF_USE_MAIN_PATH

+#define IF_USE_MAIN_PATH_2(x1, x2)

+

+#endif // WIN_LONG_PATH

+

+bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath);

+bool GetFullPath(CFSTR path, FString &fullPath);

 

 }}}

 

diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp
new file mode 100644
index 0000000..9861062
--- /dev/null
+++ b/CPP/Windows/FileSystem.cpp
@@ -0,0 +1,131 @@
+// Windows/FileSystem.cpp

+

+#include "StdAfx.h"

+

+#ifndef UNDER_CE

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "FileSystem.h"

+#include "Defs.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NFile {

+namespace NSystem {

+

+bool MyGetVolumeInformation(

+    CFSTR rootPath,

+    UString &volumeName,

+    LPDWORD volumeSerialNumber,

+    LPDWORD maximumComponentLength,

+    LPDWORD fileSystemFlags,

+    UString &fileSystemName)

+{

+  BOOL res;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    TCHAR v[MAX_PATH + 2]; v[0] = 0;

+    TCHAR f[MAX_PATH + 2]; f[0] = 0;

+    res = GetVolumeInformation(fs2fas(rootPath),

+        v, MAX_PATH,

+        volumeSerialNumber, maximumComponentLength, fileSystemFlags,

+        f, MAX_PATH);

+    volumeName = MultiByteToUnicodeString(v);

+    fileSystemName = MultiByteToUnicodeString(f);

+  }

+  else

+  #endif

+  {

+    WCHAR v[MAX_PATH + 2]; v[0] = 0;

+    WCHAR f[MAX_PATH + 2]; f[0] = 0;

+    res = GetVolumeInformationW(fs2us(rootPath),

+        v, MAX_PATH,

+        volumeSerialNumber, maximumComponentLength, fileSystemFlags,

+        f, MAX_PATH);

+    volumeName = v;

+    fileSystemName = f;

+  }

+  return BOOLToBool(res);

+}

+

+UINT MyGetDriveType(CFSTR pathName)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    return GetDriveType(fs2fas(pathName));

+  }

+  else

+  #endif

+  {

+    return GetDriveTypeW(fs2us(pathName));

+  }

+}

+

+typedef BOOL (WINAPI * GetDiskFreeSpaceExA_Pointer)(

+  LPCSTR lpDirectoryName,                  // directory name

+  PULARGE_INTEGER lpFreeBytesAvailable,    // bytes available to caller

+  PULARGE_INTEGER lpTotalNumberOfBytes,    // bytes on disk

+  PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk

+);

+

+typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)(

+  LPCWSTR lpDirectoryName,                 // directory name

+  PULARGE_INTEGER lpFreeBytesAvailable,    // bytes available to caller

+  PULARGE_INTEGER lpTotalNumberOfBytes,    // bytes on disk

+  PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk

+);

+

+bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)

+{

+  DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters;

+  bool sizeIsDetected = false;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)GetProcAddress(

+        GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");

+    if (pGetDiskFreeSpaceEx)

+    {

+      ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;

+      sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));

+      totalSize = totalSize2.QuadPart;

+      freeSize = freeSize2.QuadPart;

+    }

+    if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters))

+      return false;

+  }

+  else

+  #endif

+  {

+    GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)GetProcAddress(

+        GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW");

+    if (pGetDiskFreeSpaceEx)

+    {

+      ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;

+      sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));

+      totalSize = totalSize2.QuadPart;

+      freeSize = freeSize2.QuadPart;

+    }

+    if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters))

+      return false;

+  }

+  clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster;

+  if (!sizeIsDetected)

+  {

+    totalSize = clusterSize * (UInt64)numClusters;

+    freeSize = clusterSize * (UInt64)numFreeClusters;

+  }

+  return true;

+}

+

+}}}

+

+#endif

diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h
new file mode 100644
index 0000000..b0149de
--- /dev/null
+++ b/CPP/Windows/FileSystem.h
@@ -0,0 +1,27 @@
+// Windows/FileSystem.h

+

+#ifndef __WINDOWS_FILE_SYSTEM_H

+#define __WINDOWS_FILE_SYSTEM_H

+

+#include "../Common/MyString.h"

+#include "../Common/MyTypes.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NSystem {

+

+bool MyGetVolumeInformation(

+    CFSTR rootPath  ,

+    UString &volumeName,

+    LPDWORD volumeSerialNumber,

+    LPDWORD maximumComponentLength,

+    LPDWORD fileSystemFlags,

+    UString &fileSystemName);

+

+UINT MyGetDriveType(CFSTR pathName);

+

+bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);

+

+}}}

+

+#endif

diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h
old mode 100755
new mode 100644
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
old mode 100755
new mode 100644
index 9b2ffb8..559b6b0
--- a/CPP/Windows/MemoryLock.cpp
+++ b/CPP/Windows/MemoryLock.cpp
@@ -1,4 +1,4 @@
-// Common/MemoryLock.cpp

+// Windows/MemoryLock.cpp

 

 #include "StdAfx.h"

 

@@ -7,75 +7,63 @@
 

 #ifndef UNDER_CE

 

-#ifndef _UNICODE

-typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);

-typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID  lpLuid);

-typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges,

-    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength);

+#ifdef _UNICODE

+#define MY_FUNC_SELECT(f) :: f

+#else

+#define MY_FUNC_SELECT(f) my_ ## f

+extern "C" {

+typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);

+typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);

+typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges,

+    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);

+}

+#define GET_PROC_ADDR(fff, name) Func_ ## fff  my_ ## fff  = (Func_ ## fff)GetProcAddress(hModule, name)

 #endif

 

-#ifdef _UNICODE

-bool EnableLockMemoryPrivilege(

-#else

-static bool EnableLockMemoryPrivilege2(HMODULE hModule,

-#endif

-bool enable)

+bool EnablePrivilege(LPCTSTR privilegeName, bool enable)

 {

+  bool res = false;

+

   #ifndef _UNICODE

+

+  HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll"));

   if (hModule == NULL)

     return false;

-  OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken");

-  LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" );

-  AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges");

-  if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL)

-    return false;

+  

+  GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken");

+  GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA");

+  GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges");

+  

+  if (my_OpenProcessToken &&

+      my_AdjustTokenPrivileges &&

+      my_LookupPrivilegeValue)

+  

   #endif

 

-  HANDLE token;

-  if (!

-    #ifdef _UNICODE

-    ::OpenProcessToken

-    #else

-    openProcessToken

-    #endif

-    (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))

-    return false;

-  TOKEN_PRIVILEGES tp;

-  bool res = false;

-  if (

-    #ifdef _UNICODE

-    ::LookupPrivilegeValue

-    #else

-    lookupPrivilegeValue

-    #endif

-    (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)))

   {

-    tp.PrivilegeCount = 1;

-    tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0;

-    if (

-      #ifdef _UNICODE

-      ::AdjustTokenPrivileges

-      #else

-      adjustTokenPrivileges

-      #endif

-      (token, FALSE, &tp, 0, NULL, NULL))

-      res = (GetLastError() == ERROR_SUCCESS);

+    HANDLE token;

+    if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))

+    {

+      TOKEN_PRIVILEGES tp;

+      if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))

+      {

+        tp.PrivilegeCount = 1;

+        tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);

+        if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))

+          res = (GetLastError() == ERROR_SUCCESS);

+      }

+      ::CloseHandle(token);

+    }

   }

-  ::CloseHandle(token);

-  return res;

-}

+    

+  #ifndef _UNICODE

 

-#ifndef _UNICODE

-bool EnableLockMemoryPrivilege(bool enable)

-{

-  HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll"));

-  if (hModule == NULL)

-    return false;

-  bool res = EnableLockMemoryPrivilege2(hModule, enable);

   ::FreeLibrary(hModule);

+  

+  #endif

+

   return res;

 }

-#endif

 

 #endif

 

diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
old mode 100755
new mode 100644
index f2e574b..45c6bcb
--- a/CPP/Windows/MemoryLock.h
+++ b/CPP/Windows/MemoryLock.h
@@ -1,13 +1,34 @@
 // Windows/MemoryLock.h

 

-#ifndef __WINDOWS_MEMORYLOCK_H

-#define __WINDOWS_MEMORYLOCK_H

+#ifndef __WINDOWS_MEMORY_LOCK_H

+#define __WINDOWS_MEMORY_LOCK_H

 

 namespace NWindows {

 namespace NSecurity {

 

 #ifndef UNDER_CE

-bool EnableLockMemoryPrivilege(bool enable = true);

+

+  bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true);

+

+inline bool EnablePrivilege_LockMemory(bool enable = true)

+{

+  return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable);

+}

+

+inline void EnablePrivilege_SymLink()

+{

+  /* Probably we do not to set any Privilege for junction points.

+     But we need them for Symbolic links */

+  NSecurity::EnablePrivilege(SE_RESTORE_NAME);

+  

+  /* Probably we need only SE_RESTORE_NAME, but there is also

+     SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */

+

+  NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME

+  

+  // Do we need to set SE_BACKUP_NAME ?

+}

+

 #endif

 

 }}

diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h
old mode 100755
new mode 100644
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
old mode 100755
new mode 100644
index bcd85a5..6ab0e00
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -2,13 +2,43 @@
 

 #include "StdAfx.h"

 

-#include "PropVariant.h"

-

 #include "../Common/Defs.h"

 

+#include "PropVariant.h"

+

 namespace NWindows {

 namespace NCOM {

 

+HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()

+{

+  p->bstrVal = ::SysAllocStringLen(0, numChars);

+  if (!p->bstrVal)

+  {

+    p->vt = VT_ERROR;

+    p->scode = E_OUTOFMEMORY;

+    return E_OUTOFMEMORY;

+  }

+  p->vt = VT_BSTR;

+  return S_OK;

+}

+

+HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()

+{

+  UINT len = (UINT)strlen(s);

+  p->bstrVal = ::SysAllocStringLen(0, len);

+  if (!p->bstrVal)

+  {

+    p->vt = VT_ERROR;

+    p->scode = E_OUTOFMEMORY;

+    return E_OUTOFMEMORY;

+  }

+  p->vt = VT_BSTR;

+  BSTR dest = p->bstrVal;

+  for (UINT i = 0; i <= len; i++)

+    dest[i] = s[i];

+  return S_OK;

+}

+

 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)

 {

   vt = VT_EMPTY;

@@ -58,7 +88,7 @@
   vt = VT_BSTR;

   wReserved1 = 0;

   bstrVal = ::SysAllocString(lpszSrc);

-  if (bstrVal == NULL && lpszSrc != NULL)

+  if (!bstrVal && lpszSrc)

   {

     throw kMemException;

     // vt = VT_ERROR;

@@ -67,15 +97,14 @@
   return *this;

 }

 

-

 CPropVariant& CPropVariant::operator=(const char *s)

 {

   InternalClear();

   vt = VT_BSTR;

   wReserved1 = 0;

   UINT len = (UINT)strlen(s);

-  bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));

-  if (bstrVal == NULL)

+  bstrVal = ::SysAllocStringLen(0, len);

+  if (!bstrVal)

   {

     throw kMemException;

     // vt = VT_ERROR;

@@ -89,7 +118,7 @@
   return *this;

 }

 

-CPropVariant& CPropVariant::operator=(bool bSrc)

+CPropVariant& CPropVariant::operator=(bool bSrc) throw()

 {

   if (vt != VT_BOOL)

   {

@@ -100,22 +129,40 @@
   return *this;

 }

 

+BSTR CPropVariant::AllocBstr(unsigned numChars)

+{

+  if (vt != VT_EMPTY)

+    InternalClear();

+  vt = VT_BSTR;

+  wReserved1 = 0;

+  bstrVal = ::SysAllocStringLen(0, numChars);

+  if (!bstrVal)

+  {

+    throw kMemException;

+    // vt = VT_ERROR;

+    // scode = E_OUTOFMEMORY;

+  }

+  return bstrVal;

+}

+

 #define SET_PROP_FUNC(type, id, dest) \

-  CPropVariant& CPropVariant::operator=(type value) \

+  CPropVariant& CPropVariant::operator=(type value) throw() \

   { if (vt != id) { InternalClear(); vt = id; } \

     dest = value; return *this; }

 

 SET_PROP_FUNC(Byte, VT_UI1, bVal)

-SET_PROP_FUNC(Int16, VT_I2, iVal)

+// SET_PROP_FUNC(Int16, VT_I2, iVal)

 SET_PROP_FUNC(Int32, VT_I4, lVal)

 SET_PROP_FUNC(UInt32, VT_UI4, ulVal)

 SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)

+SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)

 SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)

 

-static HRESULT MyPropVariantClear(PROPVARIANT *prop)

+HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()

 {

-  switch(prop->vt)

+  switch (prop->vt)

   {

+    case VT_EMPTY:

     case VT_UI1:

     case VT_I1:

     case VT_I2:

@@ -134,17 +181,24 @@
     case VT_DATE:

       prop->vt = VT_EMPTY;

       prop->wReserved1 = 0;

+      prop->wReserved2 = 0;

+      prop->wReserved3 = 0;

+      prop->uhVal.QuadPart = 0;

       return S_OK;

   }

   return ::VariantClear((VARIANTARG *)prop);

+  // return ::PropVariantClear(prop);

+  // PropVariantClear can clear VT_BLOB.

 }

 

-HRESULT CPropVariant::Clear()

+HRESULT CPropVariant::Clear() throw()

 {

-  return MyPropVariantClear(this);

+  if (vt == VT_EMPTY)

+    return S_OK;

+  return PropVariant_Clear(this);

 }

 

-HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)

+HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()

 {

   ::VariantClear((tagVARIANT *)this);

   switch(pSrc->vt)

@@ -172,7 +226,7 @@
 }

 

 

-HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)

+HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()

 {

   HRESULT hr = Clear();

   if (FAILED(hr))

@@ -182,18 +236,23 @@
   return S_OK;

 }

 

-HRESULT CPropVariant::Detach(PROPVARIANT *pDest)

+HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()

 {

-  HRESULT hr = MyPropVariantClear(pDest);

-  if (FAILED(hr))

-    return hr;

+  if (pDest->vt != VT_EMPTY)

+  {

+    HRESULT hr = PropVariant_Clear(pDest);

+    if (FAILED(hr))

+      return hr;

+  }

   memcpy(pDest, this, sizeof(PROPVARIANT));

   vt = VT_EMPTY;

   return S_OK;

 }

 

-HRESULT CPropVariant::InternalClear()

+HRESULT CPropVariant::InternalClear() throw()

 {

+  if (vt == VT_EMPTY)

+    return S_OK;

   HRESULT hr = Clear();

   if (FAILED(hr))

   {

@@ -215,7 +274,7 @@
   }

 }

 

-int CPropVariant::Compare(const CPropVariant &a)

+int CPropVariant::Compare(const CPropVariant &a) throw()

 {

   if (vt != a.vt)

     return MyCompare(vt, a.vt);

@@ -233,9 +292,7 @@
     case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);

     case VT_BOOL: return -MyCompare(boolVal, a.boolVal);

     case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);

-    case VT_BSTR:

-      return 0; // Not implemented

-      // return MyCompare(aPropVarint.cVal);

+    case VT_BSTR: return 0; // Not implemented

     default: return 0;

   }

 }

diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
old mode 100755
new mode 100644
index 1605eec..4757705
--- a/CPP/Windows/PropVariant.h
+++ b/CPP/Windows/PropVariant.h
@@ -1,29 +1,73 @@
 // Windows/PropVariant.h

 

-#ifndef __WINDOWS_PROPVARIANT_H

-#define __WINDOWS_PROPVARIANT_H

+#ifndef __WINDOWS_PROP_VARIANT_H

+#define __WINDOWS_PROP_VARIANT_H

 

+#include "../Common/MyTypes.h"

 #include "../Common/MyWindows.h"

-#include "../Common/Types.h"

 

 namespace NWindows {

 namespace NCOM {

 

+HRESULT PropVariant_Clear(PROPVARIANT *p) throw();

+

+HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw();

+HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw();

+

+inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw()

+{

+  p->vt = VT_UI4;

+  p->ulVal = v;

+}

+

+inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw()

+{

+  p->vt = VT_UI8;

+  p->uhVal.QuadPart = v;

+}

+

+inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw()

+{

+  p->vt = VT_FILETIME;

+  p->filetime.dwLowDateTime = (DWORD)v;

+  p->filetime.dwHighDateTime = (DWORD)(v >> 32);

+}

+

+inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw()

+{

+  p->vt = VT_BOOL;

+  p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE);

+}

+

+

 class CPropVariant : public tagPROPVARIANT

 {

 public:

-  CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; }

-  ~CPropVariant() { Clear(); }

+  CPropVariant()

+  {

+    vt = VT_EMPTY;

+    wReserved1 = 0;

+    // wReserved2 = 0;

+    // wReserved3 = 0;

+    // uhVal.QuadPart = 0;

+    bstrVal = 0;

+  }

+  ~CPropVariant() throw() { Clear(); }

   CPropVariant(const PROPVARIANT &varSrc);

   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(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }

-  CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; }

-  CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; }

+

+private:

+  CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; }

+  CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; }

+

+public:

   CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }

   CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }

+  CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; }

   CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }

 

   CPropVariant& operator=(const CPropVariant &varSrc);

@@ -31,24 +75,31 @@
   CPropVariant& operator=(BSTR bstrSrc);

   CPropVariant& operator=(LPCOLESTR lpszSrc);

   CPropVariant& operator=(const char *s);

-  CPropVariant& operator=(bool bSrc);

-  CPropVariant& operator=(Byte value);

-  CPropVariant& operator=(Int16 value);

-  CPropVariant& operator=(Int32 value);

-  CPropVariant& operator=(UInt32 value);

-  CPropVariant& operator=(Int64 value);

-  CPropVariant& operator=(UInt64 value);

-  CPropVariant& operator=(const FILETIME &value);

+  

+  CPropVariant& operator=(bool bSrc) throw();

+  CPropVariant& operator=(Byte value) throw();

+  

+private:

+  CPropVariant& operator=(Int16 value) throw();

 

-  HRESULT Clear();

-  HRESULT Copy(const PROPVARIANT *pSrc);

-  HRESULT Attach(PROPVARIANT *pSrc);

-  HRESULT Detach(PROPVARIANT *pDest);

+public:

+  CPropVariant& operator=(Int32 value) throw();

+  CPropVariant& operator=(UInt32 value) throw();

+  CPropVariant& operator=(UInt64 value) throw();

+  CPropVariant& operator=(Int64 value) throw();

+  CPropVariant& operator=(const FILETIME &value) throw();

 

-  HRESULT InternalClear();

+  BSTR AllocBstr(unsigned numChars);

+

+  HRESULT Clear() throw();

+  HRESULT Copy(const PROPVARIANT *pSrc) throw();

+  HRESULT Attach(PROPVARIANT *pSrc) throw();

+  HRESULT Detach(PROPVARIANT *pDest) throw();

+

+  HRESULT InternalClear() throw();

   void InternalCopy(const PROPVARIANT *pSrc);

 

-  int Compare(const CPropVariant &a1);

+  int Compare(const CPropVariant &a) throw();

 };

 

 }}

diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
new file mode 100644
index 0000000..a9a0d97
--- /dev/null
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -0,0 +1,99 @@
+// PropVariantConvert.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/IntToString.h"

+

+#include "Defs.h"

+#include "PropVariantConv.h"

+

+#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }

+

+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) throw()

+{

+  SYSTEMTIME st;

+  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))

+  {

+    *s = 0;

+    return false;

+  }

+  unsigned val = st.wYear;

+  if (val >= 10000)

+  {

+    *s++ = (char)('0' + val / 10000);

+    val %= 10000;

+  }

+  {

+    s[3] = (char)('0' + val % 10); val /= 10;

+    s[2] = (char)('0' + val % 10); val /= 10;

+    s[1] = (char)('0' + val % 10);

+    s[0] = (char)('0' + val / 10);

+    s += 4;

+  }

+  UINT_TO_STR_2('-', st.wMonth);

+  UINT_TO_STR_2('-', st.wDay);

+  if (includeTime)

+  {

+    UINT_TO_STR_2(' ', st.wHour);

+    UINT_TO_STR_2(':', st.wMinute);

+    if (includeSeconds)

+      UINT_TO_STR_2(':', st.wSecond);

+  }

+  *s = 0;

+  return true;

+}

+

+void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) throw()

+{

+  char s[32];

+  ConvertFileTimeToString(ft, s, includeTime, includeSeconds);

+  for (unsigned i = 0;; i++)

+  {

+    unsigned char c = s[i];

+    dest[i] = c;

+    if (c == 0)

+      return;

+  }

+}

+

+void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()

+{

+  *dest = 0;

+  switch (prop.vt)

+  {

+    case VT_EMPTY: return;

+    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;

+    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;

+    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;

+    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;

+    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;

+    case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return;

+    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;

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

+    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);

+  }

+}

+

+void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()

+{

+  *dest = 0;

+  switch (prop.vt)

+  {

+    case VT_EMPTY: return;

+    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;

+    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;

+    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;

+    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;

+    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;

+    case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return;

+    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;

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

+    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);

+  }

+}

diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h
new file mode 100644
index 0000000..3e8297d
--- /dev/null
+++ b/CPP/Windows/PropVariantConv.h
@@ -0,0 +1,30 @@
+// Windows/PropVariantConv.h

+

+#ifndef __PROP_VARIANT_CONV_H

+#define __PROP_VARIANT_CONV_H

+

+#include "../Common/MyTypes.h"

+

+// provide at least 32 bytes for buffer including zero-end

+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw();

+void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw();

+

+// provide at least 32 bytes for buffer including zero-end

+// don't send VT_BSTR to these functions

+void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw();

+void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw();

+

+inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value)

+{

+  switch (prop.vt)

+  {

+    case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true;

+    case VT_UI4: value = prop.ulVal; return true;

+    case VT_UI2: value = prop.uiVal; return true;

+    case VT_UI1: value = prop.bVal; return true;

+    case VT_EMPTY: return false;

+    default: throw 151199;

+  }

+}

+

+#endif

diff --git a/CPP/Windows/PropVariantConversions.cpp b/CPP/Windows/PropVariantConversions.cpp
deleted file mode 100755
index 9d7c2a2..0000000
--- a/CPP/Windows/PropVariantConversions.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// PropVariantConversions.cpp

-

-#include "StdAfx.h"

-

-#include "Common/IntToString.h"

-#include "Common/StringConvert.h"

-

-#include "Windows/Defs.h"

-

-#include "PropVariantConversions.h"

-

-static UString ConvertUInt64ToString(UInt64 value)

-{

-  wchar_t buffer[32];

-  ConvertUInt64ToString(value, buffer);

-  return buffer;

-}

-

-static UString ConvertInt64ToString(Int64 value)

-{

-  wchar_t buffer[32];

-  ConvertInt64ToString(value, buffer);

-  return buffer;

-}

-

-static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos)

-{

-  if (c != 0)

-    *s++ = c;

-  char temp[16];

-  int pos = 0;

-  do

-  {

-    temp[pos++] = (char)('0' + value % 10);

-    value /= 10;

-  }

-  while (value != 0);

-  int i;

-  for (i = 0; i < numPos - pos; i++)

-    *s++ = '0';

-  do

-    *s++ = temp[--pos];

-  while (pos > 0);

-  *s = '\0';

-  return s;

-}

-

-bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds)

-{

-  s[0] = '\0';

-  SYSTEMTIME st;

-  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))

-    return false;

-  s = UIntToStringSpec(0, st.wYear, s, 4);

-  s = UIntToStringSpec('-', st.wMonth, s, 2);

-  s = UIntToStringSpec('-', st.wDay, s, 2);

-  if (includeTime)

-  {

-    s = UIntToStringSpec(' ', st.wHour, s, 2);

-    s = UIntToStringSpec(':', st.wMinute, s, 2);

-    if (includeSeconds)

-      UIntToStringSpec(':', st.wSecond, s, 2);

-  }

-  return true;

-}

-

-UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds)

-{

-  char s[32];

-  ConvertFileTimeToString(ft, s, includeTime, includeSeconds);

-  return GetUnicodeString(s);

-}

- 

-

-UString ConvertPropVariantToString(const PROPVARIANT &prop)

-{

-  switch (prop.vt)

-  {

-    case VT_EMPTY: return UString();

-    case VT_BSTR: return prop.bstrVal;

-    case VT_UI1: return ConvertUInt64ToString(prop.bVal);

-    case VT_UI2: return ConvertUInt64ToString(prop.uiVal);

-    case VT_UI4: return ConvertUInt64ToString(prop.ulVal);

-    case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart);

-    case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true);

-    // case VT_I1: return ConvertInt64ToString(prop.cVal);

-    case VT_I2: return ConvertInt64ToString(prop.iVal);

-    case VT_I4: return ConvertInt64ToString(prop.lVal);

-    case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart);

-    case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-";

-    default: throw 150245;

-  }

-}

-

-UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop)

-{

-  switch (prop.vt)

-  {

-    case VT_UI1: return prop.bVal;

-    case VT_UI2: return prop.uiVal;

-    case VT_UI4: return prop.ulVal;

-    case VT_UI8: return (UInt64)prop.uhVal.QuadPart;

-    default: throw 151199;

-  }

-}

diff --git a/CPP/Windows/PropVariantConversions.h b/CPP/Windows/PropVariantConversions.h
deleted file mode 100755
index 74139a4..0000000
--- a/CPP/Windows/PropVariantConversions.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Windows/PropVariantConversions.h

-

-#ifndef __PROP_VARIANT_CONVERSIONS_H

-#define __PROP_VARIANT_CONVERSIONS_H

-

-#include "Common/MyString.h"

-#include "Common/Types.h"

-

-bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true);

-UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true);

-UString ConvertPropVariantToString(const PROPVARIANT &prop);

-UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop);

-

-#endif

diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
old mode 100755
new mode 100644
index 3db00ea..8c3a751
--- a/CPP/Windows/Registry.cpp
+++ b/CPP/Windows/Registry.cpp
@@ -3,9 +3,9 @@
 #include "StdAfx.h"

 

 #ifndef _UNICODE

-#include "Common/StringConvert.h"

+#include "../Common/StringConvert.h"

 #endif

-#include "Windows/Registry.h"

+#include "Registry.h"

 

 #ifndef _UNICODE

 extern bool g_IsNT;

@@ -18,7 +18,7 @@
 

 LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,

     LPTSTR keyClass, DWORD options, REGSAM accessMask,

-    LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition)

+    LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw()

 {

   MYASSERT(parentKey != NULL);

   DWORD dispositionReal;

@@ -35,7 +35,7 @@
   return res;

 }

 

-LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask)

+LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw()

 {

   MYASSERT(parentKey != NULL);

   HKEY key = NULL;

@@ -49,7 +49,7 @@
   return res;

 }

 

-LONG CKey::Close()

+LONG CKey::Close() throw()

 {

   LONG res = ERROR_SUCCESS;

   if (_object != NULL)

@@ -62,13 +62,13 @@
 

 // win95, win98: deletes sunkey and all its subkeys

 // winNT to be deleted must not have subkeys

-LONG CKey::DeleteSubKey(LPCTSTR subKeyName)

+LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()

 {

   MYASSERT(_object != NULL);

   return RegDeleteKey(_object, subKeyName);

 }

 

-LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName)

+LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()

 {

   CKey key;

   LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);

@@ -97,7 +97,7 @@
 static inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }

 

 

-LONG CKey::DeleteValue(LPCTSTR name)

+LONG CKey::DeleteValue(LPCTSTR name) throw()

 {

   MYASSERT(_object != NULL);

   return ::RegDeleteValue(_object, name);

@@ -113,23 +113,23 @@
 }

 #endif

 

-LONG CKey::SetValue(LPCTSTR name, UInt32 value)

+LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw()

 {

   MYASSERT(_object != NULL);

-  return RegSetValueEx(_object, name, NULL, REG_DWORD,

+  return RegSetValueEx(_object, name, 0, REG_DWORD,

       (BYTE * const)&value, sizeof(UInt32));

 }

 

-LONG CKey::SetValue(LPCTSTR name, bool value)

+LONG CKey::SetValue(LPCTSTR name, bool value) throw()

 {

   return SetValue(name, BoolToUINT32(value));

 }

 

-LONG CKey::SetValue(LPCTSTR name, LPCTSTR value)

+LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw()

 {

   MYASSERT(value != NULL);

   MYASSERT(_object != NULL);

-  return RegSetValueEx(_object, name, NULL, REG_SZ,

+  return RegSetValueEx(_object, name, 0, REG_SZ,

       (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));

 }

 

@@ -139,7 +139,7 @@
   MYASSERT(value != NULL);

   MYASSERT(_object != NULL);

   return RegSetValueEx(_object, name, NULL, REG_SZ,

-      (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR));

+      (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR));

 }

 */

 

@@ -159,11 +159,11 @@
 #endif

 

 

-LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size)

+LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw()

 {

   MYASSERT(value != NULL);

   MYASSERT(_object != NULL);

-  return RegSetValueEx(_object, name, NULL, REG_BINARY,

+  return RegSetValueEx(_object, name, 0, REG_BINARY,

       (const BYTE *)value, size);

 }

 

@@ -177,7 +177,7 @@
   return res;

 }

 

-LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)

+LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw()

 {

   MYASSERT(value != NULL);

   CKey key;

@@ -187,18 +187,18 @@
   return res;

 }

 

-LONG CKey::QueryValue(LPCTSTR name, UInt32 &value)

+LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw()

 {

-  DWORD type = NULL;

+  DWORD type = 0;

   DWORD count = sizeof(DWORD);

   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,

     (LPBYTE)&value, &count);

-  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD));

-  MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32)));

+  MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD));

+  MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32)));

   return res;

 }

 

-LONG CKey::QueryValue(LPCTSTR name, bool &value)

+LONG CKey::QueryValue(LPCTSTR name, bool &value) throw()

 {

   UInt32 uintValue = BoolToUINT32(value);

   LONG res = QueryValue(name, uintValue);

@@ -206,7 +206,7 @@
   return res;

 }

 

-LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value)

+LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw()

 {

   UInt32 newVal;

   LONG res = QueryValue(name, newVal);

@@ -215,7 +215,7 @@
   return res;

 }

 

-LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value)

+LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()

 {

   bool newVal;

   LONG res = QueryValue(name, newVal);

@@ -224,19 +224,19 @@
   return res;

 }

 

-LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count)

+LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()

 {

   MYASSERT(count != NULL);

-  DWORD type = 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));

+  MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));

   return res;

 }

 

 LONG CKey::QueryValue(LPCTSTR name, CSysString &value)

 {

   value.Empty();

-  DWORD type = NULL;

+  DWORD type = 0;

   UInt32 currentSize = 0;

   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&currentSize);

   if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

@@ -250,15 +250,15 @@
 LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)

 {

   MYASSERT(count != NULL);

-  DWORD type = 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));

+  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 = NULL;

+  DWORD type = 0;

   UInt32 currentSize = 0;

 

   LONG res;

@@ -280,23 +280,23 @@
 }

 #endif

 

-LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count)

+LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()

 {

-  DWORD type = NULL;

+  DWORD type = 0;

   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

-  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY));

+  MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY));

   return res;

 }

 

 

 LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)

 {

-  DWORD type = NULL;

+  DWORD type = 0;

   dataSize = 0;

   LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);

   if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

     return res;

-  value.SetCapacity(dataSize);

+  value.Alloc(dataSize);

   return QueryValue(name, (BYTE *)value, dataSize);

 }

 

@@ -321,20 +321,19 @@
   return ERROR_SUCCESS;

 }

 

-LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)

+LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw()

 {

   UInt32 numChars = 0;

-  int i;

+  unsigned i;

   for (i = 0; i < strings.Size(); i++)

-    numChars += strings[i].Length() + 1;

-  CBuffer<wchar_t> buffer;

-  buffer.SetCapacity(numChars);

-  int pos = 0;

+    numChars += strings[i].Len() + 1;

+  CBuffer<wchar_t> buffer(numChars);

+  unsigned 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.Length() + 1;

+    pos += s.Len() + 1;

   }

   return SetValue(valueName, buffer, numChars * sizeof(wchar_t));

 }

@@ -350,9 +349,9 @@
   if (dataSize % sizeof(wchar_t) != 0)

     return E_FAIL;

   const wchar_t *data = (const wchar_t *)(const Byte  *)buffer;

-  int numChars = dataSize / sizeof(wchar_t);

+  unsigned numChars = dataSize / sizeof(wchar_t);

   UString s;

-  for (int i = 0; i < numChars; i++)

+  for (unsigned i = 0; i < numChars; i++)

   {

     wchar_t c = data[i];

     if (c == 0)

diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
old mode 100755
new mode 100644
index 8f4ede3..4ac6662
--- a/CPP/Windows/Registry.h
+++ b/CPP/Windows/Registry.h
@@ -3,9 +3,8 @@
 #ifndef __WINDOWS_REGISTRY_H

 #define __WINDOWS_REGISTRY_H

 

-#include "Common/Buffer.h"

-#include "Common/MyString.h"

-#include "Common/Types.h"

+#include "../Common/MyBuffer.h"

+#include "../Common/MyString.h"

 

 namespace NWindows {

 namespace NRegistry {

@@ -32,49 +31,49 @@
       LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE,

       REGSAM accessMask = KEY_ALL_ACCESS,

       LPSECURITY_ATTRIBUTES securityAttributes = NULL,

-      LPDWORD disposition = NULL);

-  LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS);

+      LPDWORD disposition = NULL) throw();

+  LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw();

 

-  LONG Close();

+  LONG Close() throw();

 

-  LONG DeleteSubKey(LPCTSTR subKeyName);

-  LONG RecurseDeleteKey(LPCTSTR subKeyName);

+  LONG DeleteSubKey(LPCTSTR subKeyName) throw();

+  LONG RecurseDeleteKey(LPCTSTR subKeyName) throw();

 

-  LONG DeleteValue(LPCTSTR name);

+  LONG DeleteValue(LPCTSTR name) throw();

   #ifndef _UNICODE

   LONG DeleteValue(LPCWSTR name);

   #endif

 

-  LONG SetValue(LPCTSTR valueName, UInt32 value);

-  LONG SetValue(LPCTSTR valueName, bool value);

-  LONG SetValue(LPCTSTR valueName, LPCTSTR value);

+  LONG SetValue(LPCTSTR valueName, UInt32 value) throw();

+  LONG SetValue(LPCTSTR valueName, bool value) throw();

+  LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw();

   // LONG SetValue(LPCTSTR valueName, const CSysString &value);

   #ifndef _UNICODE

   LONG SetValue(LPCWSTR name, LPCWSTR value);

   // LONG SetValue(LPCWSTR name, const UString &value);

   #endif

 

-  LONG SetValue(LPCTSTR name, const void *value, UInt32 size);

+  LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();

 

-  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);

+  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw();

   LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);

 

-  LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);

+  LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();

 

-  LONG QueryValue(LPCTSTR name, UInt32 &value);

-  LONG QueryValue(LPCTSTR name, bool &value);

-  LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize);

+  LONG QueryValue(LPCTSTR name, UInt32 &value) throw();

+  LONG QueryValue(LPCTSTR name, bool &value) throw();

+  LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw();

   LONG QueryValue(LPCTSTR name, CSysString &value);

 

-  LONG GetValue_IfOk(LPCTSTR name, UInt32 &value);

-  LONG GetValue_IfOk(LPCTSTR name, bool &value);

+  LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw();

+  LONG GetValue_IfOk(LPCTSTR name, bool &value) throw();

 

   #ifndef _UNICODE

   LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize);

   LONG QueryValue(LPCWSTR name, UString &value);

   #endif

 

-  LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize);

+  LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw();

   LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize);

 

   LONG EnumKeys(CSysStringVector &keyNames);

diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp
new file mode 100644
index 0000000..d20e713
--- /dev/null
+++ b/CPP/Windows/ResourceString.cpp
@@ -0,0 +1,103 @@
+// Windows/ResourceString.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "ResourceString.h"

+

+extern HINSTANCE g_hInstance;

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+

+#ifndef _UNICODE

+

+static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)

+{

+  CSysString s;

+  int size = 128;

+  int len;

+  do

+  {

+    size <<= 1;

+    len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size);

+  }

+  while (size - len <= 1);

+  s.ReleaseBuffer();

+  return s;

+}

+

+#endif

+

+static const int kStartSize = 256;

+

+static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)

+{

+  int size = kStartSize;

+  int len;

+  do

+  {

+    size <<= 1;

+    len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size);

+  }

+  while (size - len <= 1);

+  s.ReleaseBuffer();

+}

+

+// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.

+

+UString MyLoadString(UINT resourceID)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+    return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID));

+  else

+  #endif

+  {

+    {

+      wchar_t s[kStartSize];

+      s[0] = 0;

+      int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize);

+      if (kStartSize - len > 1)

+        return s;

+    }

+    UString dest;

+    MyLoadString2(g_hInstance, resourceID, dest);

+    return dest;

+  }

+}

+

+void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest)

+{

+  dest.Empty();

+  #ifndef _UNICODE

+  if (!g_IsNT)

+    MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID));

+  else

+  #endif

+  {

+    {

+      wchar_t s[kStartSize];

+      s[0] = 0;

+      int len = ::LoadStringW(hInstance, resourceID, s, kStartSize);

+      if (kStartSize - len > 1)

+      {

+        dest = s;

+        return;

+      }

+    }

+    MyLoadString2(hInstance, resourceID, dest);

+  }

+}

+

+void MyLoadString(UINT resourceID, UString &dest)

+{

+  MyLoadString(g_hInstance, resourceID, dest);

+}

+

+}

diff --git a/CPP/Windows/ResourceString.h b/CPP/Windows/ResourceString.h
new file mode 100644
index 0000000..cbaef4b
--- /dev/null
+++ b/CPP/Windows/ResourceString.h
@@ -0,0 +1,16 @@
+// Windows/ResourceString.h

+

+#ifndef __WINDOWS_RESOURCE_STRING_H

+#define __WINDOWS_RESOURCE_STRING_H

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+

+UString MyLoadString(UINT resourceID);

+void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest);

+void MyLoadString(UINT resourceID, UString &dest);

+

+}

+

+#endif

diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp
new file mode 100644
index 0000000..69ef32c
--- /dev/null
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -0,0 +1,179 @@
+// Windows/SecurityUtils.cpp

+

+#include "StdAfx.h"

+

+#include "SecurityUtils.h"

+

+namespace NWindows {

+namespace NSecurity {

+

+/*

+bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,

+  CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse)

+{

+  DWORD accountNameSize = 0, domainNameSize = 0;

+

+  if (!::LookupAccountSid(systemName, sid,

+      accountName.GetBuffer(0), &accountNameSize,

+      domainName.GetBuffer(0), &domainNameSize, sidNameUse))

+  {

+    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)

+      return false;

+  }

+  bool result = BOOLToBool(::LookupAccountSid(systemName, sid,

+      accountName.GetBuffer(accountNameSize), &accountNameSize,

+      domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));

+  accountName.ReleaseBuffer();

+  domainName.ReleaseBuffer();

+  return result;

+}

+*/

+  

+static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)

+{

+  int len = (int)wcslen(src);

+  dest->Length = (USHORT)(len * sizeof(WCHAR));

+  dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));

+  dest->Buffer = src;

+}

+

+/*

+static void MyLookupSids(CPolicy &policy, PSID ps)

+{

+  LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL;

+  LSA_TRANSLATED_NAME *names = NULL;

+  NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names);

+  int res = LsaNtStatusToWinError(nts);

+  LsaFreeMemory(referencedDomains);

+  LsaFreeMemory(names);

+}

+*/

+

+#ifndef _UNICODE

+typedef BOOL (WINAPI * LookupAccountNameWP)(

+    LPCWSTR lpSystemName,

+    LPCWSTR lpAccountName,

+    PSID Sid,

+    LPDWORD cbSid,

+    LPWSTR ReferencedDomainName,

+    LPDWORD cchReferencedDomainName,

+    PSID_NAME_USE peUse

+    );

+#endif

+

+static PSID GetSid(LPWSTR accountName)

+{

+  #ifndef _UNICODE

+  HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll"));

+  if (hModule == NULL)

+    return NULL;

+  LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW");

+  if (lookupAccountNameW == NULL)

+    return NULL;

+  #endif

+

+  DWORD sidLen = 0, domainLen = 0;

+  SID_NAME_USE sidNameUse;

+  if (!

+    #ifdef _UNICODE

+    ::LookupAccountNameW

+    #else

+    lookupAccountNameW

+    #endif

+    (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse))

+  {

+    if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)

+    {

+      PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen);

+      LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR));

+      BOOL res =

+        #ifdef _UNICODE

+        ::LookupAccountNameW

+        #else

+        lookupAccountNameW

+        #endif

+        (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse);

+      ::HeapFree(GetProcessHeap(), 0, domainName);

+      if (res)

+        return pSid;

+    }

+  }

+  return NULL;

+}

+

+#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege"

+

+bool AddLockMemoryPrivilege()

+{

+  CPolicy policy;

+  LSA_OBJECT_ATTRIBUTES attr;

+  attr.Length = sizeof(attr);

+  attr.RootDirectory = NULL;

+  attr.ObjectName  = NULL;

+  attr.Attributes = 0;

+  attr.SecurityDescriptor = NULL;

+  attr.SecurityQualityOfService  = NULL;

+  if (policy.Open(NULL, &attr,

+      // GENERIC_WRITE)

+      POLICY_ALL_ACCESS)

+      // STANDARD_RIGHTS_REQUIRED,

+      // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES)

+      != 0)

+    return false;

+  LSA_UNICODE_STRING userRights;

+  wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME;

+  SetLsaString(s, &userRights);

+  WCHAR userName[256 + 2];

+  DWORD size = 256;

+  if (!GetUserNameW(userName, &size))

+    return false;

+  PSID psid = GetSid(userName);

+  if (psid == NULL)

+    return false;

+  bool res = false;

+

+  /*

+  PLSA_UNICODE_STRING userRightsArray;

+  ULONG countOfRights;

+  NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights);

+  if (status != 0)

+    return false;

+  bool finded = false;

+  for (ULONG i = 0; i < countOfRights; i++)

+  {

+    LSA_UNICODE_STRING &ur = userRightsArray[i];

+    if (ur.Length != s.Length() * sizeof(WCHAR))

+      continue;

+    if (wcsncmp(ur.Buffer, s, s.Length()) != 0)

+      continue;

+    finded = true;

+    res = true;

+    break;

+  }

+  if (!finded)

+  */

+  {

+    /*

+    LSA_ENUMERATION_INFORMATION *enums;

+    ULONG countReturned;

+    NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned);

+    if (status == 0)

+    {

+      for (ULONG i = 0; i < countReturned; i++)

+        MyLookupSids(policy, enums[i].Sid);

+      if (enums)

+        ::LsaFreeMemory(enums);

+      res = true;

+    }

+    */

+    NTSTATUS status = policy.AddAccountRights(psid, &userRights);

+    if (status == 0)

+      res = true;

+    // ULONG res = LsaNtStatusToWinError(status);

+  }

+  HeapFree(GetProcessHeap(), 0, psid);

+  return res;

+}

+

+}}

+

diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h
new file mode 100644
index 0000000..16b6606
--- /dev/null
+++ b/CPP/Windows/SecurityUtils.h
@@ -0,0 +1,167 @@
+// Windows/SecurityUtils.h

+

+#ifndef __WINDOWS_SECURITY_UTILS_H

+#define __WINDOWS_SECURITY_UTILS_H

+

+#include <NTSecAPI.h>

+

+#include "Defs.h"

+

+namespace NWindows {

+namespace NSecurity {

+

+class CAccessToken

+{

+  HANDLE _handle;

+public:

+  CAccessToken(): _handle(NULL) {};

+  ~CAccessToken() { Close(); }

+  bool Close()

+  {

+    if (_handle == NULL)

+      return true;

+    bool res = BOOLToBool(::CloseHandle(_handle));

+    if (res)

+      _handle = NULL;

+    return res;

+  }

+

+  bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess)

+  {

+    Close();

+    return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle));

+  }

+

+  /*

+  bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf)

+  {

+    Close();

+    return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle));

+  }

+  */

+

+  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState,

+      DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength)

+    { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges),

+      newState, bufferLength, previousState, returnLength)); }

+  

+  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState)

+    { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); }

+  

+  bool AdjustPrivileges(PTOKEN_PRIVILEGES newState)

+    { return AdjustPrivileges(false, newState); }

+

+};

+

+#ifndef _UNICODE

+typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName,

+    PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle);

+typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle);

+typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle,

+    PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );

+#define MY_STATUS_NOT_IMPLEMENTED           ((NTSTATUS)0xC0000002L)

+#endif

+

+struct CPolicy

+{

+protected:

+  LSA_HANDLE _handle;

+  #ifndef _UNICODE

+  HMODULE hModule;

+  #endif

+public:

+  operator LSA_HANDLE() const { return _handle; }

+  CPolicy(): _handle(NULL)

+  {

+    #ifndef _UNICODE

+    hModule = GetModuleHandle(TEXT("Advapi32.dll"));

+    #endif

+  };

+  ~CPolicy() { Close(); }

+

+  NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes,

+      ACCESS_MASK desiredAccess)

+  {

+    #ifndef _UNICODE

+    if (hModule == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy");

+    if (lsaOpenPolicy == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    #endif

+

+    Close();

+    return

+      #ifdef _UNICODE

+      ::LsaOpenPolicy

+      #else

+      lsaOpenPolicy

+      #endif

+      (systemName, objectAttributes, desiredAccess, &_handle);

+  }

+  

+  NTSTATUS Close()

+  {

+    if (_handle == NULL)

+      return 0;

+

+    #ifndef _UNICODE

+    if (hModule == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose");

+    if (lsaClose == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    #endif

+

+    NTSTATUS res =

+      #ifdef _UNICODE

+      ::LsaClose

+      #else

+      lsaClose

+      #endif

+      (_handle);

+    _handle = NULL;

+    return res;

+  }

+  

+  NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights,

+      PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned)

+    { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); }

+

+  NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights)

+    { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); }

+

+  NTSTATUS LookupSids(ULONG count, PSID* sids,

+      PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names)

+    { return LsaLookupSids(_handle, count, sids, referencedDomains, names); }

+

+  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights)

+  {

+    #ifndef _UNICODE

+    if (hModule == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights");

+    if (lsaAddAccountRights == NULL)

+      return MY_STATUS_NOT_IMPLEMENTED;

+    #endif

+

+    return

+      #ifdef _UNICODE

+      ::LsaAddAccountRights

+      #else

+      lsaAddAccountRights

+      #endif

+      (_handle, accountSid, userRights, countOfRights);

+  }

+  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights)

+    { return AddAccountRights(accountSid, userRights, 1); }

+

+  NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights)

+    { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); }

+};

+

+bool AddLockMemoryPrivilege();

+

+}}

+

+#endif

diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
new file mode 100644
index 0000000..d5d61a9
--- /dev/null
+++ b/CPP/Windows/Shell.cpp
@@ -0,0 +1,334 @@
+// Windows/Shell.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/MyCom.h"

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "COM.h"

+#include "Shell.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NShell {

+

+#ifndef UNDER_CE

+

+// SHGetMalloc is unsupported in Windows Mobile?

+

+void CItemIDList::Free()

+{

+  if (m_Object == NULL)

+    return;

+  CMyComPtr<IMalloc> shellMalloc;

+  if (::SHGetMalloc(&shellMalloc) != NOERROR)

+    throw 41099;

+  shellMalloc->Free(m_Object);

+  m_Object = NULL;

+}

+

+/*

+CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)

+  {  *this = itemIDList; }

+CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)

+  {  *this = itemIDList; }

+

+CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)

+{

+  Free();

+  if (object != 0)

+  {

+    UINT32 size = GetSize(object);

+    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);

+    if (m_Object != NULL)

+      MoveMemory(m_Object, object, size);

+  }

+  return *this;

+}

+

+CItemIDList& CItemIDList::operator=(const CItemIDList &object)

+{

+  Free();

+  if (object.m_Object != NULL)

+  {

+    UINT32 size = GetSize(object.m_Object);

+    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);

+    if (m_Object != NULL)

+      MoveMemory(m_Object, object.m_Object, size);

+  }

+  return *this;

+}

+*/

+

+/////////////////////////////

+// CDrop

+

+void CDrop::Attach(HDROP object)

+{

+  Free();

+  m_Object = object;

+  m_Assigned = true;

+}

+

+void CDrop::Free()

+{

+  if (m_MustBeFinished && m_Assigned)

+    Finish();

+  m_Assigned = false;

+}

+

+UINT CDrop::QueryCountOfFiles()

+{

+  return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);

+}

+

+UString CDrop::QueryFileName(UINT fileIndex)

+{

+  UString fileName;

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    AString fileNameA;

+    UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);

+    QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);

+    fileNameA.ReleaseBuffer();

+    fileName = GetUnicodeString(fileNameA);

+  }

+  else

+  #endif

+  {

+    UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);

+    QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);

+    fileName.ReleaseBuffer();

+  }

+  return fileName;

+}

+

+void CDrop::QueryFileNames(UStringVector &fileNames)

+{

+  UINT numFiles = QueryCountOfFiles();

+  fileNames.ClearAndReserve(numFiles);

+  for (UINT i = 0; i < numFiles; i++)

+    fileNames.AddInReserved(QueryFileName(i));

+}

+

+

+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)

+{

+  bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));

+  path.ReleaseBuffer();

+  return result;

+}

+

+#endif

+

+#ifdef UNDER_CE

+

+bool BrowseForFolder(LPBROWSEINFO, CSysString)

+{

+  return false;

+}

+

+bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)

+{

+  return false;

+}

+

+bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,

+    LPCTSTR /* initialFolder */, CSysString & /* resultPath */)

+{

+  /*

+  // SHBrowseForFolder doesn't work before CE 6.0 ?

+  if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)

+    MessageBoxW(0, L"no", L"", 0);

+  else

+    MessageBoxW(0, L"yes", L"", 0);

+  */

+  /*

+  UString s = L"all files";

+  s += L" (*.*)";

+  return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);

+  */

+  return false;

+}

+

+#else

+

+bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)

+{

+  NWindows::NCOM::CComInitializer comInitializer;

+  LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);

+  if (itemIDList == NULL)

+    return false;

+  CItemIDList itemIDListHolder;

+  itemIDListHolder.Attach(itemIDList);

+  return GetPathFromIDList(itemIDList, resultPath);

+}

+

+

+int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)

+{

+  #ifndef UNDER_CE

+  switch(uMsg)

+  {

+    case BFFM_INITIALIZED:

+    {

+      SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);

+      break;

+    }

+    /*

+    case BFFM_SELCHANGED:

+    {

+      TCHAR dir[MAX_PATH];

+      if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))

+        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);

+      else

+        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));

+      break;

+    }

+    */

+    default:

+      break;

+  }

+  #endif

+  return 0;

+}

+

+

+bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,

+    LPCTSTR initialFolder, CSysString &resultPath)

+{

+  CSysString displayName;

+  BROWSEINFO browseInfo;

+  browseInfo.hwndOwner = owner;

+  browseInfo.pidlRoot = NULL;

+

+  // there are Unicode/astring problems in WinCE SDK!!!

+  #ifdef UNDER_CE

+  browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);

+  browseInfo.lpszTitle = (LPCSTR)title;

+  #else

+  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);

+  browseInfo.lpszTitle = title;

+  #endif

+  browseInfo.ulFlags = ulFlags;

+  browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;

+  browseInfo.lParam = (LPARAM)initialFolder;

+  return BrowseForFolder(&browseInfo, resultPath);

+}

+

+bool BrowseForFolder(HWND owner, LPCTSTR title,

+    LPCTSTR initialFolder, CSysString &resultPath)

+{

+  return BrowseForFolder(owner, title,

+      #ifndef UNDER_CE

+      BIF_NEWDIALOGSTYLE |

+      #endif

+      BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);

+  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)

+}

+

+#ifndef _UNICODE

+

+typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);

+

+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)

+{

+  path.Empty();

+  SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)

+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");

+  if (shGetPathFromIDListW == 0)

+    return false;

+  bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));

+  path.ReleaseBuffer();

+  return result;

+}

+

+typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);

+

+bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)

+{

+  NWindows::NCOM::CComInitializer comInitializer;

+  SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)

+    ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");

+  if (shBrowseForFolderW == 0)

+    return false;

+  LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);

+  if (itemIDList == NULL)

+    return false;

+  CItemIDList itemIDListHolder;

+  itemIDListHolder.Attach(itemIDList);

+  return GetPathFromIDList(itemIDList, resultPath);

+}

+

+

+int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)

+{

+  switch(uMsg)

+  {

+    case BFFM_INITIALIZED:

+    {

+      SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);

+      break;

+    }

+    /*

+    case BFFM_SELCHANGED:

+    {

+      wchar_t dir[MAX_PATH * 2];

+

+      if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))

+        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);

+      else

+        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");

+      break;

+    }

+    */

+    default:

+      break;

+  }

+  return 0;

+}

+

+

+static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,

+    LPCWSTR initialFolder, UString &resultPath)

+{

+  UString displayName;

+  BROWSEINFOW browseInfo;

+  browseInfo.hwndOwner = owner;

+  browseInfo.pidlRoot = NULL;

+  browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);

+  browseInfo.lpszTitle = title;

+  browseInfo.ulFlags = ulFlags;

+  browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;

+  browseInfo.lParam = (LPARAM)initialFolder;

+  return BrowseForFolder(&browseInfo, resultPath);

+}

+

+bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)

+{

+  if (g_IsNT)

+    return BrowseForFolder(owner, title,

+      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS

+      //  | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.

+      , initialFolder, resultPath);

+  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)

+  CSysString s;

+  bool res = BrowseForFolder(owner, GetSystemString(title),

+      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS

+      // | BIF_STATUSTEXT  // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.

+      , GetSystemString(initialFolder), s);

+  resultPath = GetUnicodeString(s);

+  return res;

+}

+

+#endif

+

+#endif

+

+}}

diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h
new file mode 100644
index 0000000..9068040
--- /dev/null
+++ b/CPP/Windows/Shell.h
@@ -0,0 +1,94 @@
+// Windows/Shell.h

+

+#ifndef __WINDOWS_SHELL_H

+#define __WINDOWS_SHELL_H

+

+#include <windows.h>

+#include <shlobj.h>

+

+#include "../Common/MyString.h"

+

+#include "Defs.h"

+

+namespace NWindows{

+namespace NShell{

+

+/////////////////////////

+// CItemIDList

+#ifndef UNDER_CE

+

+class CItemIDList

+{

+  LPITEMIDLIST m_Object;

+public:

+  CItemIDList(): m_Object(NULL) {}

+  // CItemIDList(LPCITEMIDLIST itemIDList);

+  // CItemIDList(const CItemIDList& itemIDList);

+  ~CItemIDList() { Free(); }

+  void Free();

+  void Attach(LPITEMIDLIST object)

+  {

+    Free();

+    m_Object = object;

+  }

+  LPITEMIDLIST Detach()

+  {

+    LPITEMIDLIST object = m_Object;

+    m_Object = NULL;

+    return object;

+  }

+  operator LPITEMIDLIST() { return m_Object;}

+  operator LPCITEMIDLIST() const { return m_Object;}

+  LPITEMIDLIST* operator&() { return &m_Object; }

+  LPITEMIDLIST operator->() { return m_Object; }

+

+  // CItemIDList& operator=(LPCITEMIDLIST object);

+  // CItemIDList& operator=(const CItemIDList &object);

+};

+

+/////////////////////////////

+// CDrop

+

+class CDrop

+{

+  HDROP m_Object;

+  bool m_MustBeFinished;

+  bool m_Assigned;

+  void Free();

+public:

+  CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {}

+  ~CDrop() { Free(); }

+

+  void Attach(HDROP object);

+  operator HDROP() { return m_Object;}

+  bool QueryPoint(LPPOINT point)

+    { return BOOLToBool(::DragQueryPoint(m_Object, point)); }

+  void Finish() {  ::DragFinish(m_Object); }

+  UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT fileNameSize)

+    { return ::DragQueryFile(m_Object, fileIndex, fileName, fileNameSize); }

+  #ifndef _UNICODE

+  UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT fileNameSize)

+    { return ::DragQueryFileW(m_Object, fileIndex, fileName, fileNameSize); }

+  #endif

+  UINT QueryCountOfFiles();

+  UString QueryFileName(UINT fileIndex);

+  void QueryFileNames(UStringVector &fileNames);

+};

+

+#endif

+

+/////////////////////////////

+// Functions

+

+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path);

+bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath);

+bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath);

+

+#ifndef _UNICODE

+bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path);

+bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath);

+bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath);

+#endif

+}}

+

+#endif

diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h
old mode 100755
new mode 100644
index 5308d63..47a4895
--- a/CPP/Windows/StdAfx.h
+++ b/CPP/Windows/StdAfx.h
@@ -3,7 +3,6 @@
 #ifndef __STDAFX_H

 #define __STDAFX_H

 

-#include "../Common/MyWindows.h"

-#include "../Common/NewHandler.h"

+#include "../Common/Common.h"

 

 #endif

diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp
old mode 100755
new mode 100644
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
old mode 100755
new mode 100644
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
old mode 100755
new mode 100644
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
old mode 100755
new mode 100644
index 49a4fe7..78a5e1d
--- a/CPP/Windows/System.h
+++ b/CPP/Windows/System.h
@@ -3,7 +3,7 @@
 #ifndef __WINDOWS_SYSTEM_H

 #define __WINDOWS_SYSTEM_H

 

-#include "../Common/Types.h"

+#include "../Common/MyTypes.h"

 

 namespace NWindows {

 namespace NSystem {

diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h
old mode 100755
new mode 100644
diff --git a/CPP/Windows/Time.h b/CPP/Windows/Time.h
deleted file mode 100755
index 7ecb204..0000000
--- a/CPP/Windows/Time.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Windows/Time.h

-

-#ifndef __WINDOWS_TIME_H

-#define __WINDOWS_TIME_H

-

-#include "Common/Types.h"

-

-namespace NWindows {

-namespace NTime {

-

-bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime);

-bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime);

-void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime);

-bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime);

-bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,

-  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds);

-void GetCurUtcFileTime(FILETIME &ft);

-

-}}

-

-#endif

diff --git a/CPP/Windows/Time.cpp b/CPP/Windows/TimeUtils.cpp
old mode 100755
new mode 100644
similarity index 69%
rename from CPP/Windows/Time.cpp
rename to CPP/Windows/TimeUtils.cpp
index 0504cdf..32f3108
--- a/CPP/Windows/Time.cpp
+++ b/CPP/Windows/TimeUtils.cpp
@@ -1,10 +1,9 @@
-// Windows/Time.cpp

+// Windows/TimeUtils.cpp

 

 #include "StdAfx.h"

 

-#include "Windows/Defs.h"

-

-#include "Time.h"

+#include "Defs.h"

+#include "TimeUtils.h"

 

 namespace NWindows {

 namespace NTime {

@@ -13,10 +12,11 @@
 static const UInt32 kFileTimeStartYear = 1601;

 static const UInt32 kDosTimeStartYear = 1980;

 static const UInt32 kUnixTimeStartYear = 1970;

-static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) *

-    60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));

+static const UInt64 kUnixTimeOffset =

+    (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));

+static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;

 

-bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft)

+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw()

 {

   #if defined(_WIN32) && !defined(UNDER_CE)

   return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));

@@ -41,7 +41,7 @@
 #define PERIOD_100 (PERIOD_4 * 25 - 1)

 #define PERIOD_400 (PERIOD_100 * 4 + 1)

 

-bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime)

+bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()

 {

   #if defined(_WIN32) && !defined(UNDER_CE)

 

@@ -115,22 +115,48 @@
   return true;

 }

 

-void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft)

+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw()

 {

-  UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond;

+  UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;

   ft.dwLowDateTime = (DWORD)v;

   ft.dwHighDateTime = (DWORD)(v >> 32);

 }

 

-bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime)

+bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()

+{

+  if (unixTime > kNumSecondsInFileTime - kUnixTimeOffset)

+  {

+    ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1;

+    return false;

+  }

+  Int64 v = (Int64)kUnixTimeOffset + unixTime;

+  if (v < 0)

+  {

+    ft.dwLowDateTime = ft.dwHighDateTime = 0;

+    return false;

+  }

+  UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond;

+  ft.dwLowDateTime = (DWORD)v2;

+  ft.dwHighDateTime = (DWORD)(v2 >> 32);

+  return true;

+}

+

+Int64 FileTimeToUnixTime64(const FILETIME &ft) throw()

 {

   UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;

-  if (winTime < kUnixTimeStartValue)

+  return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset;

+}

+

+bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw()

+{

+  UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;

+  winTime /= kNumTimeQuantumsInSecond;

+  if (winTime < kUnixTimeOffset)

   {

     unixTime = 0;

     return false;

   }

-  winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond;

+  winTime -= kUnixTimeOffset;

   if (winTime > 0xFFFFFFFF)

   {

     unixTime = 0xFFFFFFFF;

@@ -141,7 +167,7 @@
 }

 

 bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,

-  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds)

+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw()

 {

   resSeconds = 0;

   if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||

@@ -160,11 +186,18 @@
   return true;

 }

 

-void GetCurUtcFileTime(FILETIME &ft)

+void GetCurUtcFileTime(FILETIME &ft) throw()

 {

+  // Both variants provide same low resolution on WinXP: about 15 ms.

+  // But GetSystemTimeAsFileTime is much faster.

+

+  #ifdef UNDER_CE

   SYSTEMTIME st;

   GetSystemTime(&st);

   SystemTimeToFileTime(&st, &ft);

+  #else

+  GetSystemTimeAsFileTime(&ft);

+  #endif

 }

 

 }}

diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
new file mode 100644
index 0000000..0b1f11f
--- /dev/null
+++ b/CPP/Windows/TimeUtils.h
@@ -0,0 +1,23 @@
+// Windows/TimeUtils.h

+

+#ifndef __WINDOWS_TIME_UTILS_H

+#define __WINDOWS_TIME_UTILS_H

+

+#include "../Common/MyTypes.h"

+

+namespace NWindows {

+namespace NTime {

+

+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw();

+bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw();

+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw();

+bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw();

+bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw();

+Int64 FileTimeToUnixTime64(const FILETIME &ft) throw();

+bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,

+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw();

+void GetCurUtcFileTime(FILETIME &ft) throw();

+

+}}

+

+#endif

diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp
new file mode 100644
index 0000000..98b0630
--- /dev/null
+++ b/CPP/Windows/Window.cpp
@@ -0,0 +1,169 @@
+// Windows/Window.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+#include "Window.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+

+#ifndef _UNICODE

+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass)

+{

+  if (g_IsNT)

+    return RegisterClassW(wndClass);

+  WNDCLASSA wndClassA;

+  wndClassA.style = wndClass->style;

+  wndClassA.lpfnWndProc = wndClass->lpfnWndProc;

+  wndClassA.cbClsExtra = wndClass->cbClsExtra;

+  wndClassA.cbWndExtra = wndClass->cbWndExtra;

+  wndClassA.hInstance = wndClass->hInstance;

+  wndClassA.hIcon = wndClass->hIcon;

+  wndClassA.hCursor = wndClass->hCursor;

+  wndClassA.hbrBackground = wndClass->hbrBackground;

+  AString menuName;

+  AString className;

+  if (IS_INTRESOURCE(wndClass->lpszMenuName))

+    wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName;

+  else

+  {

+    menuName = GetSystemString(wndClass->lpszMenuName);

+    wndClassA.lpszMenuName = menuName;

+  }

+  if (IS_INTRESOURCE(wndClass->lpszClassName))

+    wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName;

+  else

+  {

+    className = GetSystemString(wndClass->lpszClassName);

+    wndClassA.lpszClassName = className;

+  }

+  return RegisterClassA(&wndClassA);

+}

+

+bool CWindow::Create(LPCWSTR className,

+      LPCWSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam)

+{

+  if (g_IsNT)

+  {

+    _window = ::CreateWindowW(className, windowName,

+        style, x, y, width, height, parentWindow,

+        idOrHMenu, instance, createParam);

+     return (_window != NULL);

+  }

+  return Create(GetSystemString(className), GetSystemString(windowName),

+        style, x, y, width, height, parentWindow,

+        idOrHMenu, instance, createParam);

+}

+

+bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className,

+      LPCWSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam)

+{

+  if (g_IsNT)

+  {

+    _window = ::CreateWindowExW(exStyle, className, windowName,

+      style, x, y, width, height, parentWindow,

+      idOrHMenu, instance, createParam);

+     return (_window != NULL);

+  }

+  AString classNameA;

+  LPCSTR classNameP;

+  if (IS_INTRESOURCE(className))

+    classNameP = (LPCSTR)className;

+  else

+  {

+    classNameA = GetSystemString(className);

+    classNameP = classNameA;

+  }

+  AString windowNameA;

+  LPCSTR windowNameP;

+  if (IS_INTRESOURCE(windowName))

+    windowNameP = (LPCSTR)windowName;

+  else

+  {

+    windowNameA = GetSystemString(windowName);

+    windowNameP = windowNameA;

+  }

+  return CreateEx(exStyle, classNameP, windowNameP,

+      style, x, y, width, height, parentWindow,

+      idOrHMenu, instance, createParam);

+}

+

+#endif

+

+#ifndef _UNICODE

+bool MySetWindowText(HWND wnd, LPCWSTR s)

+{

+  if (g_IsNT)

+    return BOOLToBool(::SetWindowTextW(wnd, s));

+  return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s)));

+}

+#endif

+

+bool CWindow::GetText(CSysString &s)

+{

+  s.Empty();

+  int length = GetTextLength();

+  if (length == 0)

+    return (::GetLastError() == ERROR_SUCCESS);

+  length = GetText(s.GetBuffer(length), length + 1);

+  s.ReleaseBuffer();

+  if (length == 0)

+    return (::GetLastError() != ERROR_SUCCESS);

+  return true;

+}

+

+#ifndef _UNICODE

+bool CWindow::GetText(UString &s)

+{

+  if (g_IsNT)

+  {

+    s.Empty();

+    int length = GetWindowTextLengthW(_window);

+    if (length == 0)

+      return (::GetLastError() == ERROR_SUCCESS);

+    length = GetWindowTextW(_window, s.GetBuffer(length), length + 1);

+    s.ReleaseBuffer();

+    if (length == 0)

+      return (::GetLastError() == ERROR_SUCCESS);

+    return true;

+  }

+  CSysString sysString;

+  bool result = GetText(sysString);

+  s = GetUnicodeString(sysString);

+  return result;

+}

+#endif

+

+ 

+/*

+bool CWindow::ModifyStyleBase(int styleOffset,

+  DWORD remove, DWORD add, UINT flags)

+{

+  DWORD style = GetWindowLong(styleOffset);

+  DWORD newStyle = (style & ~remove) | add;

+  if (style == newStyle)

+    return false; // it is not good

+

+  SetWindowLong(styleOffset, newStyle);

+  if (flags != 0)

+  {

+    ::SetWindowPos(_window, NULL, 0, 0, 0, 0,

+      SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags);

+  }

+  return TRUE;

+}

+*/

+

+}

diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h
new file mode 100644
index 0000000..3db239d
--- /dev/null
+++ b/CPP/Windows/Window.h
@@ -0,0 +1,283 @@
+// Windows/Window.h

+

+#ifndef __WINDOWS_WINDOW_H

+#define __WINDOWS_WINDOW_H

+

+#include "../Common/MyString.h"

+

+#include "Defs.h"

+

+#ifndef UNDER_CE

+

+#define MY__WM_CHANGEUISTATE  0x0127

+#define MY__WM_UPDATEUISTATE  0x0128

+#define MY__WM_QUERYUISTATE   0x0129

+

+// LOWORD(wParam) values in WM_*UISTATE

+#define MY__UIS_SET         1

+#define MY__UIS_CLEAR       2

+#define MY__UIS_INITIALIZE  3

+

+// HIWORD(wParam) values in WM_*UISTATE

+#define MY__UISF_HIDEFOCUS  0x1

+#define MY__UISF_HIDEACCEL  0x2

+#define MY__UISF_ACTIVE     0x4

+

+#endif

+

+namespace NWindows {

+

+inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass)

+  { return ::RegisterClass(wndClass); }

+

+#ifndef _UNICODE

+ATOM MyRegisterClass(CONST WNDCLASSW *wndClass);

+#endif

+

+#ifdef _UNICODE

+inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); }

+#else

+bool MySetWindowText(HWND wnd, LPCWSTR s);

+#endif

+

+

+#ifdef UNDER_CE

+#define GWLP_USERDATA GWL_USERDATA

+#define GWLP_WNDPROC GWL_WNDPROC

+#define BTNS_BUTTON TBSTYLE_BUTTON

+#define WC_COMBOBOXW L"ComboBox"

+#define DWLP_MSGRESULT DWL_MSGRESULT

+#endif

+

+class CWindow

+{

+private:

+   // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags);

+protected:

+  HWND _window;

+public:

+  CWindow(HWND newWindow = NULL): _window(newWindow){};

+  CWindow& operator=(HWND newWindow)

+  {

+    _window = newWindow;

+    return *this;

+  }

+  operator HWND() const { return _window; }

+  void Attach(HWND newWindow) { _window = newWindow; }

+  HWND Detach()

+  {

+    HWND window = _window;

+    _window = NULL;

+    return window;

+  }

+

+  bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); }

+  

+  HWND GetParent() const { return ::GetParent(_window); }

+  bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); }

+  #ifndef UNDER_CE

+  bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); }

+  #endif

+  bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); }

+  bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); }

+

+  bool CreateEx(DWORD exStyle, LPCTSTR className,

+      LPCTSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam)

+  {

+    _window = ::CreateWindowEx(exStyle, className, windowName,

+      style, x, y, width, height, parentWindow,

+      idOrHMenu, instance, createParam);

+    return (_window != NULL);

+  }

+

+  bool Create(LPCTSTR className,

+      LPCTSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam)

+  {

+    _window = ::CreateWindow(className, windowName,

+      style, x, y, width, height, parentWindow,

+      idOrHMenu, instance, createParam);

+    return (_window != NULL);

+  }

+

+  #ifndef _UNICODE

+  bool Create(LPCWSTR className,

+      LPCWSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam);

+  bool CreateEx(DWORD exStyle, LPCWSTR className,

+      LPCWSTR windowName, DWORD style,

+      int x, int y, int width, int height,

+      HWND parentWindow, HMENU idOrHMenu,

+      HINSTANCE instance, LPVOID createParam);

+  #endif

+

+

+  bool Destroy()

+  {

+    if (_window == NULL)

+      return true;

+    bool result = BOOLToBool(::DestroyWindow(_window));

+    if (result)

+      _window = NULL;

+    return result;

+  }

+  bool IsWindow() {  return BOOLToBool(::IsWindow(_window)); }

+  bool Move(int x, int y, int width, int height, bool repaint = true)

+    { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); }

+

+  bool ChangeSubWindowSizeX(HWND hwnd, int xSize)

+  {

+    RECT rect;

+    ::GetWindowRect(hwnd, &rect);

+    POINT p1;

+    p1.x = rect.left;

+    p1.y = rect.top;

+    ScreenToClient(&p1);

+    return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE));

+  }

+

+  void ScreenToClient(RECT *rect)

+  {

+    POINT p1, p2;

+    p1.x = rect->left;

+    p1.y = rect->top;

+    p2.x = rect->right;

+    p2.y = rect->bottom;

+    ScreenToClient(&p1);

+    ScreenToClient(&p2);

+

+    rect->left = p1.x;

+    rect->top = p1.y;

+    rect->right = p2.x;

+    rect->bottom = p2.y;

+  }

+

+  bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); }

+  bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); }

+  bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); }

+

+  #ifndef UNDER_CE

+  bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); }

+  bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); }

+  #endif

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

+

+  LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }

+  LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }

+  // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); }

+

+  LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); }

+  LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); }

+  LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); }

+  LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); }

+

+

+  #ifdef UNDER_CE

+

+  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); }

+  LONG_PTR GetLongPtr(int index) const { return GetLong(index); }

+

+  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); }

+  LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); }

+  

+  #else

+  

+  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr)

+    { return ::SetWindowLongPtr(_window, index,

+          #ifndef _WIN64

+          (LONG)

+          #endif

+          newLongPtr); }

+  #ifndef _UNICODE

+  LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr)

+    { return ::SetWindowLongPtrW(_window, index,

+          #ifndef _WIN64

+          (LONG)

+          #endif

+          newLongPtr); }

+  #endif

+

+  LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); }

+  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); }

+  LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); }

+  

+  #endif

+  

+  /*

+  bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)

+    {  return ModifyStyleBase(GWL_STYLE, remove, add, flags); }

+  bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)

+    { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); }

+  */

+ 

+  HWND SetFocus() { return ::SetFocus(_window); }

+

+  LRESULT SendMessage(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) ;}

+  #endif

+

+  bool PostMessage(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) ;}

+  #endif

+

+  bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); }

+  #ifndef _UNICODE

+  bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); }

+  #endif

+

+  int GetTextLength() const

+    { return GetWindowTextLength(_window); }

+  UINT GetText(LPTSTR string, int maxCount) const

+    { return GetWindowText(_window, string, maxCount); }

+  bool GetText(CSysString &s);

+  #ifndef _UNICODE

+  /*

+  UINT GetText(LPWSTR string, int maxCount) const

+    { return GetWindowTextW(_window, string, maxCount); }

+  */

+  bool GetText(UString &s);

+  #endif

+

+  bool Enable(bool enable)

+    { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); }

+  

+  bool IsEnabled()

+    { return BOOLToBool(::IsWindowEnabled(_window)); }

+  

+  #ifndef UNDER_CE

+  HMENU GetSystemMenu(bool revert)

+    { return ::GetSystemMenu(_window, BoolToBOOL(revert)); }

+  #endif

+

+  UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = 0)

+    { return ::SetTimer(_window, idEvent, elapse, timerFunc); }

+  bool KillTimer(UINT_PTR idEvent)

+    {return BOOLToBool(::KillTimer(_window, idEvent)); }

+

+  HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMessage(WM_SETICON, sizeType, (LPARAM)icon); }

+};

+

+#define RECT_SIZE_X(r) ((r).right - (r).left)

+#define RECT_SIZE_Y(r) ((r).bottom - (r).top)

+

+inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; }

+

+}

+

+#endif

diff --git a/CS/7zip/Common/CRC.cs b/CS/7zip/Common/CRC.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Common/CommandLineParser.cs b/CS/7zip/Common/CommandLineParser.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Common/InBuffer.cs b/CS/7zip/Common/InBuffer.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Common/OutBuffer.cs b/CS/7zip/Common/OutBuffer.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZ/IMatchFinder.cs b/CS/7zip/Compress/LZ/IMatchFinder.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZ/LzBinTree.cs b/CS/7zip/Compress/LZ/LzBinTree.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZ/LzInWindow.cs b/CS/7zip/Compress/LZ/LzInWindow.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZ/LzOutWindow.cs b/CS/7zip/Compress/LZ/LzOutWindow.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZMA/LzmaBase.cs b/CS/7zip/Compress/LZMA/LzmaBase.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZMA/LzmaDecoder.cs b/CS/7zip/Compress/LZMA/LzmaDecoder.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LZMA/LzmaEncoder.cs b/CS/7zip/Compress/LZMA/LzmaEncoder.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs b/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj b/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln b/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/LzmaBench.cs b/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs b/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs b/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs b/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/RangeCoder/RangeCoder.cs b/CS/7zip/Compress/RangeCoder/RangeCoder.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs b/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
old mode 100755
new mode 100644
diff --git a/CS/7zip/ICoder.cs b/CS/7zip/ICoder.cs
old mode 100755
new mode 100644
diff --git a/7zC.txt b/DOC/7zC.txt
old mode 100755
new mode 100644
similarity index 93%
rename from 7zC.txt
rename to DOC/7zC.txt
index 4ff6325..4927678
--- a/7zC.txt
+++ b/DOC/7zC.txt
@@ -1,4 +1,4 @@
-7z ANSI-C Decoder 4.62

+7z ANSI-C Decoder 9.35

 ----------------------

 

 7z ANSI-C provides 7z/LZMA decoding.

@@ -29,11 +29,9 @@
 How To Use

 ----------

 

-You must download 7-Zip program from www.7-zip.org.

+You can create .7z archive with 7z.exe, 7za.exe or 7zr.exe:

 

-You can create .7z archive with 7z.exe or 7za.exe:

-

-  7za.exe a archive.7z *.htm -r -mx -m0fb=255

+  7z.exe a archive.7z *.htm -r -mx -m0fb=255

 

 If you have big number of files in archive, and you need fast extracting, 

 you can use partly-solid archives:

@@ -112,14 +110,9 @@
 

   Listing code:

   ~~~~~~~~~~~~~

-    {

-      UInt32 i;

-      for (i = 0; i < db.db.NumFiles; i++)

-      {

-        CFileItem *f = db.db.Files + i;

-        printf("%10d  %s\n", (int)f->Size, f->Name);

-      }

-    }

+

+    Use SzArEx_GetFileNameUtf16 function. Look example code in C\Util\7z\7zMain.c file. 

+    

 

   Extracting code:

   ~~~~~~~~~~~~~~~~

diff --git a/7zFormat.txt b/DOC/7zFormat.txt
old mode 100755
new mode 100644
similarity index 84%
rename from 7zFormat.txt
rename to DOC/7zFormat.txt
index f084c05..6b8678f
--- a/7zFormat.txt
+++ b/DOC/7zFormat.txt
@@ -1,5 +1,5 @@
-7z Format description (2.30 Beta 25)

------------------------------------

+7z Format description (4.59)

+----------------------------

 

 This file contains description of 7z archive format. 

 7z archive can contain files compressed with any method.

@@ -126,40 +126,43 @@
 Property IDs

 ------------

 

-0x00 = kEnd,

+0x00 = kEnd

 

-0x01 = kHeader,

+0x01 = kHeader

 

-0x02 = kArchiveProperties,

+0x02 = kArchiveProperties

     

-0x03 = kAdditionalStreamsInfo,

-0x04 = kMainStreamsInfo,

-0x05 = kFilesInfo,

+0x03 = kAdditionalStreamsInfo

+0x04 = kMainStreamsInfo

+0x05 = kFilesInfo

     

-0x06 = kPackInfo,

-0x07 = kUnPackInfo,

-0x08 = kSubStreamsInfo,

+0x06 = kPackInfo

+0x07 = kUnPackInfo

+0x08 = kSubStreamsInfo

 

-0x09 = kSize,

-0x0A = kCRC,

+0x09 = kSize

+0x0A = kCRC

 

-0x0B = kFolder,

+0x0B = kFolder

 

-0x0C = kCodersUnPackSize,

-0x0D = kNumUnPackStream,

+0x0C = kCodersUnPackSize

+0x0D = kNumUnPackStream

 

-0x0E = kEmptyStream,

-0x0F = kEmptyFile,

-0x10 = kAnti,

+0x0E = kEmptyStream

+0x0F = kEmptyFile

+0x10 = kAnti

 

-0x11 = kName,

-0x12 = kCreationTime,

-0x13 = kLastAccessTime,

-0x14 = kLastWriteTime,

-0x15 = kWinAttributes,

-0x16 = kComment,

+0x11 = kName

+0x12 = kCTime

+0x13 = kATime

+0x14 = kMTime

+0x15 = kWinAttributes

+0x16 = kComment

 

-0x17 = kEncodedHeader,

+0x17 = kEncodedHeader

+

+0x18 = kStartPos

+0x19 = kDummy

 

 

 7z format headers

@@ -238,24 +241,19 @@
   {

     BYTE 

     {

-      0:3 DecompressionMethod.IDSize

-      4:

-        0 - IsSimple

-        1 - Is not simple

-      5:

-        0 - No Attributes

-        1 - There Are Attributes

-      7:

-        0 - Last Method in Alternative_Method_List

-        1 - There are more alternative methods

+      0:3 CodecIdSize

+      4:  Is Complex Coder

+      5:  There Are Attributes

+      6:  Reserved

+      7:  There are more alternative methods. (Not used anymore, must be 0).

     } 

-    BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]

-    if (!IsSimple)

+    BYTE CodecId[CodecIdSize]

+    if (Is Complex Coder)

     {

       UINT64 NumInStreams;

       UINT64 NumOutStreams;

     }

-    if (DecompressionMethod[0] != 0)

+    if (There Are Attributes)

     {

       UINT64 PropertiesSize

       BYTE Properties[PropertiesSize]

@@ -387,9 +385,9 @@
         for(EmptyStreams)

           BIT IsAntiFile

       

-      case kCreationTime:   (0x12)

-      case kLastAccessTime: (0x13)

-      case kLastWriteTime:  (0x14)

+      case kCTime: (0x12)

+      case kATime: (0x13)

+      case kMTime: (0x14)

         BYTE AllAreDefined

         if (AllAreDefined == 0)

         {

@@ -401,7 +399,7 @@
           UINT64 DataIndex

         []

         for(Definded Items)

-          UINT32 Time

+          UINT64 Time

         []

       

       kNames:     (0x11)

diff --git a/Methods.txt b/DOC/Methods.txt
old mode 100755
new mode 100644
similarity index 78%
rename from Methods.txt
rename to DOC/Methods.txt
index 4c3ec68..a300d77
--- a/Methods.txt
+++ b/DOC/Methods.txt
@@ -1,4 +1,4 @@
-7-Zip method IDs (9.18)

+7-Zip method IDs (9.24)

 -----------------------

 

 Each compression or crypto method in 7z has unique binary value (ID).

@@ -103,24 +103,22 @@
 

 

 06.. - Crypto 

-   00 - 

-   01 - AES

-      0x - AES-128

-      4x - AES-192

-      8x - AES-256

-      Cx - AES

 

-      x0 - ECB

-      x1 - CBC

-      x2 - CFB

-      x3 - OFB

+   F0 - Ciphers without hashing algo

 

-   07 - Reserved

-   0F - Reserved

+      01 - AES

+         0x - AES-128

+         4x - AES-192

+         8x - AES-256

+         Cx - AES

 

-   F0 - Misc Ciphers (Real Ciphers without hashing algo)

+         x0 - ECB

+         x1 - CBC

+         x2 - CFB

+         x3 - OFB

+         x4 - CTR

 

-   F1 - Misc Ciphers (Combine)

+   F1 - Combine Ciphers

       01 - Zip

          01 - Main Zip crypto algo

       03 - RAR

@@ -129,24 +127,6 @@
       07 - 7z

          01 - AES-256 + SHA-256

 

-07.. - Hash (subject to change)

-   00 - 

-   01 - CRC

-   02 - SHA-1

-   03 - SHA-256

-   04 - SHA-384

-   05 - SHA-512

-

-   F0 - Misc Hash

-

-   F1 - Misc

-      03 - RAR

-         03 - Rar29 Password Hashing (modified SHA1)

-      07 - 7z 

-         01 - SHA-256 Password Hashing

-    

-   

-

 

 ---

 End of document

diff --git a/DOC/installer.txt b/DOC/installer.txt
new file mode 100644
index 0000000..70ad7dc
--- /dev/null
+++ b/DOC/installer.txt
@@ -0,0 +1,166 @@
+7-Zip for installers 9.38

+-------------------------

+

+7-Zip is a file archiver for Windows NT/2000/2003/2008/XP/Vista/7/8/10. 

+

+7-Zip for installers is part of LZMA SDK.

+LZMA SDK is written and placed in the public domain by Igor Pavlov.

+

+It's allowed to join 7-Zip SFX module with another software.

+It's allowed to change resources of 7-Zip's SFX modules.

+

+

+HOW to use

+-----------

+

+7zr.exe is reduced version of 7za.exe of 7-Zip.

+7zr.exe supports only format with these codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, Copy.

+

+Example of compressing command for installation packages:

+

+7zr a archive.7z files

+

+7zSD.sfx is SFX module for installers. 7zSD.sfx uses msvcrt.dll.

+

+SFX modules for installers allow to create installation program. 

+Such module extracts archive to temp folder and then runs specified program and removes 

+temp files after program finishing. Self-extract archive for installers must be created 

+as joining 3 files: SFX_Module, Installer_Config, 7z_Archive. 

+Installer_Config is optional file. You can use the following command to create installer 

+self-extract archive:

+

+copy /b 7zSD.sfx + config.txt + archive.7z archive.exe

+

+The smallest installation package size can be achieved, if installation files was 

+uncompressed before including to 7z archive.

+

+-y switch for installer module (at runtime) specifies quiet mode for extracting.

+

+Installer Config file format

+~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+Config file contains commands for Installer. File begins from string 

+;!@Install@!UTF-8! and ends with ;!@InstallEnd@!. File must be written 

+in UTF-8 encoding. File contains string pairs: 

+

+ID_String="Value"

+

+ID_String          Description 

+

+Title              Title for messages 

+BeginPrompt        Begin Prompt message 

+Progress           Value can be "yes" or "no". Default value is "yes". 

+RunProgram         Command for executing. Default value is "setup.exe". 

+                   Substring %%T will be replaced with path to temporary 

+                   folder, where files were extracted 

+Directory          Directory prefix for "RunProgram". Default value is ".\\" 

+ExecuteFile        Name of file for executing 

+ExecuteParameters  Parameters for "ExecuteFile" 

+

+

+You can omit any string pair.

+

+There are two ways to run program: RunProgram and ExecuteFile. 

+Use RunProgram, if you want to run some program from .7z archive. 

+Use ExecuteFile, if you want to open some document from .7z archive or 

+if you want to execute some command from Windows.

+

+If you use RunProgram and if you specify empty directory prefix: Directory="", 

+the system searches for the executable file in the following sequence:

+

+1. The directory from which the application (installer) loaded. 

+2. The temporary folder, where files were extracted. 

+3. The Windows system directory. 

+

+

+Config file Examples

+~~~~~~~~~~~~~~~~~~~~

+

+;!@Install@!UTF-8!

+Title="7-Zip 4.00"

+BeginPrompt="Do you want to install the 7-Zip 4.00?"

+RunProgram="setup.exe"

+;!@InstallEnd@!

+

+

+

+;!@Install@!UTF-8!

+Title="7-Zip 4.00"

+BeginPrompt="Do you want to install the 7-Zip 4.00?"

+ExecuteFile="7zip.msi"

+;!@InstallEnd@!

+

+

+

+;!@Install@!UTF-8!

+Title="7-Zip 4.01 Update"

+BeginPrompt="Do you want to install the 7-Zip 4.01 Update?"

+ExecuteFile="msiexec.exe"

+ExecuteParameters="/i 7zip.msi REINSTALL=ALL REINSTALLMODE=vomus"

+;!@InstallEnd@!

+

+

+

+Small SFX modules for installers

+--------------------------------

+

+7zS2.sfx     - small SFX module (GUI version)

+7zS2con.sfx  - small SFX module (Console version)

+

+Small SFX modules support this codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, COPY

+

+Small SFX module is similar to common SFX module for installers.

+The difference (what's new in small version):

+ - Smaller size (30 KB vs 100 KB)

+ - C source code instead of Ñ++

+ - No installer Configuration file

+ - No extracting progress window

+ - It decompresses solid 7z blocks (it can be whole 7z archive) to RAM.

+   So user that calls SFX installer must have free RAM of size of largest 

+   solid 7z block (size of 7z archive at simplest case).

+

+How to use

+----------

+

+copy /b 7zS2.sfx + archive.7z sfx.exe

+

+When you run installer sfx module (sfx.exe)

+1) It creates "7zNNNNNNNN" temp folder in system temp folder.

+2) It extracts .7z archive to that folder

+3) It executes one file from "7zNNNNNNNN" temp folder. 

+4) It removes "7zNNNNNNNN" temp folder

+

+You can send parameters to installer, and installer will transfer them to extracted .exe file.

+

+Small SFX uses 3 levels of priorities to select file to execute:

+

+  1) Files in root folder have higher priority than files in subfolders.

+  2) File extension priorities (from high to low priority order): 

+       bat, cmd, exe, inf, msi, cab (under Windows CE), html, htm

+  3) File name priorities (from high to low priority order): 

+       setup, install, run, start

+

+Windows CE (ARM) version of 7zS2.sfx is included to 7-Zip for Windows Mobile package.

+

+

+Examples

+--------

+

+1) To create compressed console 7-Zip:

+

+7zr a c.7z 7z.exe 7z.dll -mx

+copy /b 7zS2con.sfx + c.7z 7zCompr.exe

+7zCompr.exe b -md22

+

+

+2) To create compressed GUI 7-Zip:

+

+7zr a g.7z 7zg.exe 7z.dll -mx

+copy /b 7zS2.sfx + g.7z 7zgCompr.exe

+7zgCompr.exe b -md22

+

+

+3) To open some file:

+

+7zr a h.7z readme.txt -mx

+copy /b 7zS2.sfx + h.7z 7zTxt.exe 

+7zTxt.exe

diff --git a/history.txt b/DOC/lzma-history.txt
old mode 100755
new mode 100644
similarity index 84%
rename from history.txt
rename to DOC/lzma-history.txt
index 50ff40f..6e98358
--- a/history.txt
+++ b/DOC/lzma-history.txt
@@ -1,6 +1,41 @@
 HISTORY of the LZMA SDK

 -----------------------

 

+9.38 beta      2015-01-03

+-------------------------	

+- The BUG in 9.30-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.

+

+

+9.36 beta      2014-12-26

+-------------------------	

+- The BUG in command line version was fixed:

+  7-Zip created temporary archive in current folder during update archive

+  operation, if -w{Path} switch was not specified. 

+  The fixed 7-Zip creates temporary archive in folder that contains updated archive.

+- The BUG in 9.33-9.35 was fixed:

+  7-Zip silently ignored file reading errors during 7z or gz archive creation,

+  and the created archive contained only part of file that was read before error.

+  The fixed 7-Zip stops archive creation and it reports about error.

+

+

+9.35 beta      2014-12-07

+-------------------------	

+- 7zr.exe now support AES encryption.

+- SFX mudules were added to LZMA SDK

+- Some bugs were fixed.

+

+

+9.21 beta      2011-04-11

+-------------------------	

+- New class FString for file names at file systems.

+- Speed optimization in CRC code for big-endian CPUs.

+- The BUG in Lzma2Dec.c was fixed:

+    Lzma2Decode function didn't work.

+

+

 9.18 beta      2010-11-02

 -------------------------	

 - New small SFX module for installers (SfxSetup).

diff --git a/DOC/lzma-sdk.txt b/DOC/lzma-sdk.txt
new file mode 100644
index 0000000..86923a4
--- /dev/null
+++ b/DOC/lzma-sdk.txt
@@ -0,0 +1,356 @@
+LZMA SDK 9.38

+-------------

+

+LZMA SDK provides the documentation, samples, header files,

+libraries, and tools you need to develop applications that 

+use 7z / LZMA / LZMA2 / XZ compression.

+

+LZMA is an improved version of famous LZ77 compression algorithm. 

+It was improved in way of maximum increasing of compression ratio,

+keeping high decompression speed and low memory requirements for 

+decompressing.

+

+LZMA2 is a LZMA based compression method. LZMA2 provides better 

+multithreading support for compression than LZMA and some other improvements.

+

+7z is a file format for data compression and file archiving.

+7z is a main file format for 7-Zip compression program (www.7-zip.org).

+7z format supports different compression methods: LZMA, LZMA2 and others.

+7z also supports AES-256 based encryption.

+

+XZ is a file format for data compression that uses LZMA2 compression.

+XZ format provides additional features: SHA/CRC check, filters for 

+improved compression ratio, splitting to blocks and streams,

+

+

+

+LICENSE

+-------

+

+LZMA SDK is written and placed in the public domain by Igor Pavlov.

+

+Some code in LZMA SDK is based on public domain code from another developers:

+  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.

+

+LZMA SDK code is compatible with open source licenses, for example, you can 

+include it to GNU GPL or GNU LGPL code.

+

+

+LZMA SDK Contents

+-----------------

+

+  Source code:

+

+    - C / C++ / C# / Java   - LZMA compression and decompression

+    - C / C++               - LZMA2 compression and decompression

+    - C / C++               - XZ compression and decompression

+    - C                     - 7z decompression

+    -     C++               - 7z compression and decompression

+    - C                     - small SFXs for installers (7z decompression)

+    -     C++               - SFXs and SFXs for installers (7z decompression)

+

+  Precomiled binaries:

+

+    - console programs for lzma / 7z / xz compression and decompression

+    - SFX modules for installers.

+

+

+UNIX/Linux version 

+------------------

+To compile C++ version of file->file LZMA encoding, go to directory

+CPP/7zip/Bundles/LzmaCon

+and call make to recompile it:

+  make -f makefile.gcc clean all

+

+In some UNIX/Linux versions you must compile LZMA with static libraries.

+To compile with static libraries, you can use 

+LIB = -lm -static

+

+Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux):

+  

+  http://p7zip.sourceforge.net/

+

+

+Files

+-----

+

+DOC/7zC.txt          - 7z ANSI-C Decoder description

+DOC/7zFormat.txt     - 7z Format description

+DOC/installer.txt    - information about 7-Zip for installers

+DOC/lzma.txt         - LZMA compression description

+DOC/lzma-sdk.txt     - LZMA SDK description (this file)

+DOC/lzma-history.txt - history of LZMA SDK

+DOC/lzma-specification.txt - Specification of LZMA

+DOC/Methods.txt      - Compression method IDs for .7z

+

+bin/installer/   - example script to create installer that uses SFX module,

+

+bin/7zdec.exe    - simplified 7z archive decoder

+bin/7zr.exe      - 7-Zip console program (reduced version)

+bin/x64/7zr.exe  - 7-Zip console program (reduced version) (x64 version)

+bin/lzma.exe     - file->file LZMA encoder/decoder for Windows

+bin/7zS2.sfx     - small SFX module for installers (GUI version)

+bin/7zS2con.sfx  - small SFX module for installers (Console version)

+bin/7zSD.sfx     - SFX module for installers.

+

+

+7zDec.exe

+---------

+7zDec.exe is simplified 7z archive decoder.

+It supports only LZMA, LZMA2, and PPMd methods.

+7zDec decodes whole solid block from 7z archive to RAM.

+The RAM consumption can be high.

+

+

+

+

+Source code structure

+---------------------

+

+

+Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption)

+

+C/  - C files (compression / decompression and other)

+  Util/

+    7z       - 7z decoder program (decoding 7z files)

+    Lzma     - LZMA program (file->file LZMA encoder/decoder).

+    LzmaLib  - LZMA library (.DLL for Windows)

+    SfxSetup - small SFX module for installers 

+

+CPP/ -- CPP files

+

+  Common  - common files for C++ projects

+  Windows - common files for Windows related code

+

+  7zip    - files related to 7-Zip

+

+    Archive - files related to archiving

+

+      Common   - common files for archive handling

+      7z       - 7z C++ Encoder/Decoder

+

+    Bundles  - Modules that are bundles of other modules (files)

+  

+      Alone7z       - 7zr.exe: Standalone 7-Zip console program (reduced version)

+      Format7zExtractR  - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2.

+      Format7zR         - 7zr.dll:  Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2

+      LzmaCon       - lzma.exe: LZMA compression/decompression

+      LzmaSpec      - example code for LZMA Specification

+      SFXCon        - 7zCon.sfx: Console 7z SFX module

+      SFXSetup      - 7zS.sfx: 7z SFX module for installers

+      SFXWin        - 7z.sfx: GUI 7z SFX module

+

+    Common   - common files for 7-Zip

+

+    Compress - files for compression/decompression

+

+    Crypto   - files for encryption / decompression

+

+    UI       - User Interface files

+         

+      Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll

+      Common   - Common UI files

+      Console  - Code for console program (7z.exe)

+      Explorer    - Some code from 7-Zip Shell extension

+      FileManager - Some GUI code from 7-Zip File Manager

+      GUI         - Some GUI code from 7-Zip

+

+

+CS/ - C# files

+  7zip

+    Common   - some common files for 7-Zip

+    Compress - files related to compression/decompression

+      LZ     - files related to LZ (Lempel-Ziv) compression algorithm

+      LZMA         - LZMA compression/decompression

+      LzmaAlone    - file->file LZMA compression/decompression

+      RangeCoder   - Range Coder (special code of compression/decompression)

+

+Java/  - Java files

+  SevenZip

+    Compression    - files related to compression/decompression

+      LZ           - files related to LZ (Lempel-Ziv) compression algorithm

+      LZMA         - LZMA compression/decompression

+      RangeCoder   - Range Coder (special code of compression/decompression)

+

+

+Note: 

+  Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code.

+  7-Zip's source code can be downloaded from 7-Zip's SourceForge page:

+

+  http://sourceforge.net/projects/sevenzip/

+

+

+

+LZMA features

+-------------

+  - Variable dictionary size (up to 1 GB)

+  - Estimated compressing speed: about 2 MB/s on 2 GHz CPU

+  - Estimated decompressing speed: 

+      - 20-30 MB/s on modern 2 GHz cpu

+      - 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC)

+  - Small memory requirements for decompressing (16 KB + DictionarySize)

+  - Small code size for decompressing: 5-8 KB

+

+LZMA decoder uses only integer operations and can be 

+implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).

+

+Some critical operations that affect the speed of LZMA decompression:

+  1) 32*16 bit integer multiply

+  2) Mispredicted branches (penalty mostly depends from pipeline length)

+  3) 32-bit shift and arithmetic operations

+

+The speed of LZMA decompressing mostly depends from CPU speed.

+Memory speed has no big meaning. But if your CPU has small data cache, 

+overall weight of memory speed will slightly increase.

+

+

+How To Use

+----------

+

+Using LZMA encoder/decoder executable

+--------------------------------------

+

+Usage:  LZMA <e|d> inputFile outputFile [<switches>...]

+

+  e: encode file

+

+  d: decode file

+

+  b: Benchmark. There are two tests: compressing and decompressing 

+     with LZMA method. Benchmark shows rating in MIPS (million 

+     instructions per second). Rating value is calculated from 

+     measured speed and it is normalized with Intel's Core 2 results.

+     Also Benchmark checks possible hardware errors (RAM 

+     errors in most cases). Benchmark uses these settings:

+     (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. 

+     Also you can change the number of iterations. Example for 30 iterations:

+       LZMA b 30

+     Default number of iterations is 10.

+

+<Switches>

+  

+

+  -a{N}:  set compression mode 0 = fast, 1 = normal

+          default: 1 (normal)

+

+  d{N}:   Sets Dictionary size - [0, 30], default: 23 (8MB)

+          The maximum value for dictionary size is 1 GB = 2^30 bytes.

+          Dictionary size is calculated as DictionarySize = 2^N bytes. 

+          For decompressing file compressed by LZMA method with dictionary 

+          size D = 2^N you need about D bytes of memory (RAM).

+

+  -fb{N}: set number of fast bytes - [5, 273], default: 128

+          Usually big number gives a little bit better compression ratio 

+          and slower compression process.

+

+  -lc{N}: set number of literal context bits - [0, 8], default: 3

+          Sometimes lc=4 gives gain for big files.

+

+  -lp{N}: set number of literal pos bits - [0, 4], default: 0

+          lp switch is intended for periodical data when period is 

+          equal 2^N. For example, for 32-bit (4 bytes) 

+          periodical data you can use lp=2. Often it's better to set lc0, 

+          if you change lp switch.

+

+  -pb{N}: set number of pos bits - [0, 4], default: 2

+          pb switch is intended for periodical data 

+          when period is equal 2^N.

+

+  -mf{MF_ID}: set Match Finder. Default: bt4. 

+              Algorithms from hc* group doesn't provide good compression 

+              ratio, but they often works pretty fast in combination with 

+              fast mode (-a0).

+

+              Memory requirements depend from dictionary size 

+              (parameter "d" in table below). 

+

+               MF_ID     Memory                   Description

+

+                bt2    d *  9.5 + 4MB  Binary Tree with 2 bytes hashing.

+                bt3    d * 11.5 + 4MB  Binary Tree with 3 bytes hashing.

+                bt4    d * 11.5 + 4MB  Binary Tree with 4 bytes hashing.

+                hc4    d *  7.5 + 4MB  Hash Chain with 4 bytes hashing.

+

+  -eos:   write End Of Stream marker. By default LZMA doesn't write 

+          eos marker, since LZMA decoder knows uncompressed size 

+          stored in .lzma file header.

+

+  -si:    Read data from stdin (it will write End Of Stream marker).

+  -so:    Write data to stdout

+

+

+Examples:

+

+1) LZMA e file.bin file.lzma -d16 -lc0 

+

+compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)  

+and 0 literal context bits. -lc0 allows to reduce memory requirements 

+for decompression.

+

+

+2) LZMA e file.bin file.lzma -lc0 -lp2

+

+compresses file.bin to file.lzma with settings suitable 

+for 32-bit periodical data (for example, ARM or MIPS code).

+

+3) LZMA d file.lzma file.bin

+

+decompresses file.lzma to file.bin.

+

+

+Compression ratio hints

+-----------------------

+

+Recommendations

+---------------

+

+To increase the compression ratio for LZMA compressing it's desirable 

+to have aligned data (if it's possible) and also it's desirable to locate

+data in such order, where code is grouped in one place and data is 

+grouped in other place (it's better than such mixing: code, data, code,

+data, ...).

+

+

+Filters

+-------

+You can increase the compression ratio for some data types, using

+special filters before compressing. For example, it's possible to 

+increase the compression ratio on 5-10% for code for those CPU ISAs: 

+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.

+

+You can find C source code of such filters in C/Bra*.* files

+

+You can check the compression ratio gain of these filters with such 

+7-Zip commands (example for ARM code):

+No filter:

+  7z a a1.7z a.bin -m0=lzma

+

+With filter for little-endian ARM code:

+  7z a a2.7z a.bin -m0=arm -m1=lzma        

+

+It works in such manner:

+Compressing    = Filter_encoding + LZMA_encoding

+Decompressing  = LZMA_decoding + Filter_decoding

+

+Compressing and decompressing speed of such filters is very high,

+so it will not increase decompressing time too much.

+Moreover, it reduces decompression time for LZMA_decoding, 

+since compression ratio with filtering is higher.

+

+These filters convert CALL (calling procedure) instructions 

+from relative offsets to absolute addresses, so such data becomes more 

+compressible.

+

+For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.

+

+

+

+---

+

+http://www.7-zip.org

+http://www.7-zip.org/sdk.html

+http://www.7-zip.org/support.html

diff --git a/DOC/lzma-specification.txt b/DOC/lzma-specification.txt
new file mode 100644
index 0000000..2e3b874
--- /dev/null
+++ b/DOC/lzma-specification.txt
@@ -0,0 +1,1175 @@
+LZMA specification (DRAFT version)

+----------------------------------

+

+Author: Igor Pavlov

+Date: 2013-07-28

+

+This specification defines the format of LZMA compressed data and lzma file format.

+

+Notation 

+--------

+

+We use the syntax of C++ programming language.

+We use the following types in C++ code:

+  unsigned - unsigned integer, at least 16 bits in size

+  int      - signed integer, at least 16 bits in size

+  UInt64   - 64-bit unsigned integer

+  UInt32   - 32-bit unsigned integer

+  UInt16   - 16-bit unsigned integer

+  Byte     - 8-bit unsigned integer

+  bool     - boolean type with two possible values: false, true

+

+

+lzma file format

+================

+

+The lzma file contains the raw LZMA stream and the header with related properties.

+

+The files in that format use ".lzma" extension.

+

+The lzma file format layout:

+

+Offset Size Description

+

+  0     1   LZMA model properties (lc, lp, pb) in encoded form

+  1     4   Dictionary size (32-bit unsigned integer, little-endian)

+  5     8   Uncompressed size (64-bit unsigned integer, little-endian)

+ 13         Compressed data (LZMA stream)

+

+LZMA properties:

+

+    name  Range          Description

+

+      lc  [0, 8]         the number of "literal context" bits

+      lp  [0, 4]         the number of "literal pos" bits

+      pb  [0, 4]         the number of "pos" bits

+dictSize  [0, 2^32 - 1]  the dictionary size 

+

+The following code encodes LZMA properties:

+

+void EncodeProperties(Byte *properties)

+{

+  properties[0] = (Byte)((pb * 5 + lp) * 9 + lc);

+  Set_UInt32_LittleEndian(properties + 1, dictSize);

+}

+

+If the value of dictionary size in properties is smaller than (1 << 12),

+the LZMA decoder must set the dictionary size variable to (1 << 12).

+

+#define LZMA_DIC_MIN (1 << 12)

+

+  unsigned lc, pb, lp;

+  UInt32 dictSize;

+  UInt32 dictSizeInProperties;

+

+  void DecodeProperties(const Byte *properties)

+  {

+    unsigned d = properties[0];

+    if (d >= (9 * 5 * 5))

+      throw "Incorrect LZMA properties";

+    lc = d % 9;

+    d /= 9;

+    pb = d / 5;

+    lp = d % 5;

+    dictSizeInProperties = 0;

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

+      dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);

+    dictSize = dictSizeInProperties;

+    if (dictSize < LZMA_DIC_MIN)

+      dictSize = LZMA_DIC_MIN;

+  }

+

+If "Uncompressed size" field contains ones in all 64 bits, it means that

+uncompressed size is unknown and there is the "end marker" in stream,

+that indicates the end of decoding point.

+In opposite case, if the value from "Uncompressed size" field is not

+equal to ((2^64) - 1), the LZMA stream decoding must be finished after

+specified number of bytes (Uncompressed size) is decoded. And if there 

+is the "end marker", the LZMA decoder must read that marker also.

+

+

+The new scheme to encode LZMA properties

+----------------------------------------

+

+If LZMA compression is used for some another format, it's recommended to

+use a new improved scheme to encode LZMA properties. That new scheme was

+used in xz format that uses the LZMA2 compression algorithm.

+The LZMA2 is a new compression algorithm that is based on the LZMA algorithm.

+

+The dictionary size in LZMA2 is encoded with just one byte and LZMA2 supports

+only reduced set of dictionary sizes:

+  (2 << 11), (3 << 11),

+  (2 << 12), (3 << 12),

+  ...

+  (2 << 30), (3 << 30),

+  (2 << 31) - 1

+

+The dictionary size can be extracted from encoded value with the following code:

+

+  dictSize = (p == 40) ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));

+

+Also there is additional limitation (lc + lp <= 4) in LZMA2 for values of 

+"lc" and "lp" properties:

+

+  if (lc + lp > 4)

+    throw "Unsupported properties: (lc + lp) > 4";

+

+There are some advantages for LZMA decoder with such (lc + lp) value

+limitation. It reduces the maximum size of tables allocated by decoder.

+And it reduces the complexity of initialization procedure, that can be 

+important to keep high speed of decoding of big number of small LZMA streams.

+

+It's recommended to use that limitation (lc + lp <= 4) for any new format

+that uses LZMA compression. Note that the combinations of "lc" and "lp" 

+parameters, where (lc + lp > 4), can provide significant improvement in 

+compression ratio only in some rare cases.

+

+The LZMA properties can be encoded into two bytes in new scheme:

+

+Offset Size Description

+

+  0     1   The dictionary size encoded with LZMA2 scheme

+  1     1   LZMA model properties (lc, lp, pb) in encoded form

+

+

+The RAM usage 

+=============

+

+The RAM usage for LZMA decoder is determined by the following parts:

+

+1) The Sliding Window (from 4 KiB to 4 GiB).

+2) The probability model counter arrays (arrays of 16-bit variables).

+3) Some additional state variables (about 10 variables of 32-bit integers).

+

+

+The RAM usage for Sliding Window

+--------------------------------

+

+There are two main scenarios of decoding:

+

+1) The decoding of full stream to one RAM buffer.

+

+  If we decode full LZMA stream to one output buffer in RAM, the decoder 

+  can use that output buffer as sliding window. So the decoder doesn't 

+  need additional buffer allocated for sliding window.

+

+2) The decoding to some external storage.

+

+  If we decode LZMA stream to external storage, the decoder must allocate

+  the buffer for sliding window. The size of that buffer must be equal 

+  or larger than the value of dictionary size from properties of LZMA stream.

+

+In this specification we describe the code for decoding to some external

+storage. The optimized version of code for decoding of full stream to one

+output RAM buffer can require some minor changes in code.

+

+

+The RAM usage for the probability model counters

+------------------------------------------------

+

+The size of the probability model counter arrays is calculated with the 

+following formula:

+

+size_of_prob_arrays = 1846 + 768 * (1 << (lp + lc))

+

+Each probability model counter is 11-bit unsigned integer.

+If we use 16-bit integer variables (2-byte integers) for these probability 

+model counters, the RAM usage required by probability model counter arrays 

+can be estimated with the following formula:

+

+  RAM = 4 KiB + 1.5 KiB * (1 << (lp + lc))

+

+For example, for default LZMA parameters (lp = 0 and lc = 3), the RAM usage is

+

+  RAM_lc3_lp0 = 4 KiB + 1.5 KiB * 8 = 16 KiB

+

+The maximum RAM state usage is required for decoding the stream with lp = 4 

+and lc = 8:

+

+  RAM_lc8_lp4 = 4 KiB + 1.5 KiB * 4096 = 6148 KiB

+

+If the decoder uses LZMA2's limited property condition 

+(lc + lp <= 4), the RAM usage will be not larger than

+

+  RAM_lc_lp_4 = 4 KiB + 1.5 KiB * 16 = 28 KiB

+

+

+The RAM usage for encoder

+-------------------------

+

+There are many variants for LZMA encoding code.

+These variants have different values for memory consumption.

+Note that memory consumption for LZMA Encoder can not be 

+smaller than memory consumption of LZMA Decoder for same stream.

+

+The RAM usage required by modern effective implementation of 

+LZMA Encoder can be estimated with the following formula:

+

+  Encoder_RAM_Usage = 4 MiB + 11 * dictionarySize.

+

+But there are some modes of the encoder that require less memory.

+

+

+LZMA Decoding

+=============

+

+The LZMA compression algorithm uses LZ-based compression with Sliding Window

+and Range Encoding as entropy coding method.

+

+

+Sliding Window

+--------------

+

+LZMA uses Sliding Window compression similar to LZ77 algorithm.

+

+LZMA stream must be decoded to the sequence that consists

+of MATCHES and LITERALS:

+  

+  - a LITERAL is a 8-bit character (one byte).

+    The decoder just puts that LITERAL to the uncompressed stream.

+  

+  - a MATCH is a pair of two numbers (DISTANCE-LENGTH pair).

+    The decoder takes one byte exactly "DISTANCE" characters behind

+    current position in the uncompressed stream and puts it to 

+    uncompressed stream. The decoder must repeat it "LENGTH" times.

+

+The "DISTANCE" can not be larger than dictionary size.

+And the "DISTANCE" can not be larger than the number of bytes in

+the uncompressed stream that were decoded before that match.

+

+In this specification we use cyclic buffer to implement Sliding Window

+for LZMA decoder:

+

+class COutWindow

+{

+  Byte *Buf;

+  UInt32 Pos;

+  UInt32 Size;

+  bool IsFull;

+

+public:

+  unsigned TotalPos;

+  COutStream OutStream;

+

+  COutWindow(): Buf(NULL) {}

+  ~COutWindow() { delete []Buf; }

+ 

+  void Create(UInt32 dictSize)

+  {

+    Buf = new Byte[dictSize];

+    Pos = 0;

+    Size = dictSize;

+    IsFull = false;

+    TotalPos = 0;

+  }

+

+  void PutByte(Byte b)

+  {

+    TotalPos++;

+    Buf[Pos++] = b;

+    if (Pos == Size)

+    {

+      Pos = 0;

+      IsFull = true;

+    }

+    OutStream.WriteByte(b);

+  }

+

+  Byte GetByte(UInt32 dist) const

+  {

+    return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];

+  }

+

+  void CopyMatch(UInt32 dist, unsigned len)

+  {

+    for (; len > 0; len--)

+      PutByte(GetByte(dist));

+  }

+

+  bool CheckDistance(UInt32 dist) const

+  {

+    return dist <= Pos || IsFull;

+  }

+

+  bool IsEmpty() const

+  {

+    return Pos == 0 && !IsFull;

+  }

+};

+

+

+In another implementation it's possible to use one buffer that contains 

+Sliding Window and the whole data stream after uncompressing.

+

+

+Range Decoder

+-------------

+

+LZMA algorithm uses Range Encoding (1) as entropy coding method.

+

+LZMA stream contains just one very big number in big-endian encoding.

+LZMA decoder uses the Range Decoder to extract a sequence of binary

+symbols from that big number.

+

+The state of the Range Decoder:

+

+struct CRangeDecoder

+{

+  UInt32 Range; 

+  UInt32 Code;

+  InputStream *InStream;

+

+  bool Corrupted;

+}

+

+The notes about UInt32 type for the "Range" and "Code" variables:

+

+  It's possible to use 64-bit (unsigned or signed) integer type

+  for the "Range" and the "Code" variables instead of 32-bit unsigned,

+  but some additional code must be used to truncate the values to 

+  low 32-bits after some operations.

+

+  If the programming language does not support 32-bit unsigned integer type 

+  (like in case of JAVA language), it's possible to use 32-bit signed integer, 

+  but some code must be changed. For example, it's required to change the code

+  that uses comparison operations for UInt32 variables in this specification.

+

+The Range Decoder can be in some states that can be treated as 

+"Corruption" in LZMA stream. The Range Decoder uses the variable "Corrupted":

+

+  (Corrupted == false), if the Range Decoder has not detected any corruption.

+  (Corrupted == true), if the Range Decoder has detected some corruption.

+

+The reference LZMA Decoder ignores the value of the "Corrupted" variable.

+So it continues to decode the stream, even if the corruption can be detected

+in the Range Decoder. To provide the full compatibility with output of the 

+reference LZMA Decoder, another LZMA Decoder implementations must also 

+ignore the value of the "Corrupted" variable.

+

+The LZMA Encoder is required to create only such LZMA streams, that will not 

+lead the Range Decoder to states, where the "Corrupted" variable is set to true.

+

+The Range Decoder reads first 5 bytes from input stream to initialize

+the state:

+

+void CRangeDecoder::Init()

+{

+  Corrupted = false;

+  

+  if (InStream->ReadByte() != 0)

+    Corrupted = true;

+  

+  Range = 0xFFFFFFFF;

+  Code = 0;

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

+    Code = (Code << 8) | InStream->ReadByte();

+  

+  if (Code == Range)

+    Corrupted = true;

+}

+

+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.

+

+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 

+calling the IsFinishedOK() function:

+

+  bool IsFinishedOK() const { return Code == 0; }

+

+If there is corruption in data stream, there is big probability that

+the "Code" value will be not equal to 0 in the Finish() function. So that

+check in the IsFinishedOK() function provides very good feature for 

+corruption detection.

+

+The value of the "Range" variable before each bit decoding can not be smaller 

+than ((UInt32)1 << 24). The Normalize() function keeps the "Range" value in 

+described range.

+

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

+

+void CRangeDecoder::Normalize()

+{

+  if (Range < kTopValue)

+  {

+    Range <<= 8;

+    Code = (Code << 8) | InStream->ReadByte();

+  }

+}

+

+Notes: if the size of the "Code" variable is larger than 32 bits, it's

+required to keep only low 32 bits of the "Code" variable after the change

+in Normalize() function.

+

+If the LZMA Stream is not corrupted, the value of the "Code" variable is

+always smaller than value of the "Range" variable.

+But the Range Decoder ignores some types of corruptions, so the value of

+the "Code" variable can be equal or larger than value of the "Range" variable

+for some "Corrupted" archives.

+

+

+LZMA uses Range Encoding only with binary symbols of two types:

+  1) binary symbols with fixed and equal probabilities (direct bits)

+  2) binary symbols with predicted probabilities

+

+The DecodeDirectBits() function decodes the sequence of direct bits:

+

+UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)

+{

+  UInt32 res = 0;

+  do

+  {

+    Range >>= 1;

+    Code -= Range;

+    UInt32 t = 0 - ((UInt32)Code >> 31);

+    Code += Range & t;

+    

+    if (Code == Range)

+      Corrupted = true;

+    

+    Normalize();

+    res <<= 1;

+    res += t + 1;

+  }

+  while (--numBits);

+  return res;

+}

+

+

+The Bit Decoding with Probability Model

+---------------------------------------

+

+The task of Bit Probability Model is to estimate probabilities of binary

+symbols. And then it provides the Range Decoder with that information.

+The better prediction provides better compression ratio.

+The Bit Probability Model uses statistical data of previous decoded

+symbols.

+

+That estimated probability is presented as 11-bit unsigned integer value

+that represents the probability of symbol "0".

+

+#define kNumBitModelTotalBits 11

+

+Mathematical probabilities can be presented with the following formulas:

+     probability(symbol_0) = prob / 2048.

+     probability(symbol_1) =  1 - Probability(symbol_0) =  

+                           =  1 - prob / 2048 =  

+                           =  (2048 - prob) / 2048

+where the "prob" variable contains 11-bit integer probability counter.

+

+It's recommended to use 16-bit unsigned integer type, to store these 11-bit

+probability values:

+

+typedef UInt16 CProb;

+

+Each probability value must be initialized with value ((1 << 11) / 2),

+that represents the state, where probabilities of symbols 0 and 1 

+are equal to 0.5:

+

+#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)

+

+The INIT_PROBS macro is used to initialize the array of CProb variables:

+

+#define INIT_PROBS(p) \

+ { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }

+

+

+The DecodeBit() function decodes one bit.

+The LZMA decoder provides the pointer to CProb variable that contains 

+information about estimated probability for symbol 0 and the Range Decoder 

+updates that CProb variable after decoding. The Range Decoder increases 

+estimated probability of the symbol that was decoded:

+

+#define kNumMoveBits 5

+

+unsigned CRangeDecoder::DecodeBit(CProb *prob)

+{

+  unsigned v = *prob;

+  UInt32 bound = (Range >> kNumBitModelTotalBits) * v;

+  unsigned symbol;

+  if (Code < bound)

+  {

+    v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;

+    Range = bound;

+    symbol = 0;

+  }

+  else

+  {

+    v -= v >> kNumMoveBits;

+    Code -= bound;

+    Range -= bound;

+    symbol = 1;

+  }

+  *prob = (CProb)v;

+  Normalize();

+  return symbol;

+}

+

+

+The Binary Tree of bit model counters

+-------------------------------------

+

+LZMA uses a tree of Bit model variables to decode symbol that needs

+several bits for storing. There are two versions of such trees in LZMA:

+  1) the tree that decodes bits from high bit to low bit (the normal scheme).

+  2) the tree that decodes bits from low bit to high bit (the reverse scheme).

+

+Each binary tree structure supports different size of decoded symbol

+(the size of binary sequence that contains value of symbol).

+If that size of decoded symbol is "NumBits" bits, the tree structure 

+uses the array of (2 << NumBits) counters of CProb type. 

+But only ((2 << NumBits) - 1) items are used by encoder and decoder.

+The first item (the item with index equal to 0) in array is unused.

+That scheme with unused array's item allows to simplify the code.

+

+unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)

+{

+  unsigned m = 1;

+  unsigned symbol = 0;

+  for (unsigned i = 0; i < numBits; i++)

+  {

+    unsigned bit = rc->DecodeBit(&probs[m]);

+    m <<= 1;

+    m += bit;

+    symbol |= (bit << i);

+  }

+  return symbol;

+}

+

+template <unsigned NumBits>

+class CBitTreeDecoder

+{

+  CProb Probs[(unsigned)1 << NumBits];

+

+public:

+

+  void Init()

+  {

+    INIT_PROBS(Probs);

+  }

+

+  unsigned Decode(CRangeDecoder *rc)

+  {

+    unsigned m = 1;

+    for (unsigned i = 0; i < NumBits; i++)

+      m = (m << 1) + rc->DecodeBit(&Probs[m]);

+    return m - ((unsigned)1 << NumBits);

+  }

+

+  unsigned ReverseDecode(CRangeDecoder *rc)

+  {

+    return BitTreeReverseDecode(Probs, NumBits, rc);

+  }

+};

+

+

+LZ part of LZMA 

+---------------

+

+LZ part of LZMA describes details about the decoding of MATCHES and LITERALS.

+

+

+The Literal Decoding

+--------------------

+

+The LZMA Decoder uses (1 << (lc + lp)) tables with CProb values, where 

+each table contains 0x300 CProb values:

+

+  CProb *LitProbs;

+

+  void CreateLiterals()

+  {

+    LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];

+  }

+  

+  void InitLiterals()

+  {

+    UInt32 num = (UInt32)0x300 << (lc + lp);

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

+      LitProbs[i] = PROB_INIT_VAL;

+  }

+

+To select the table for decoding it uses the context that consists of

+(lc) high bits from previous literal and (lp) low bits from value that

+represents current position in outputStream.

+

+If (State > 7), the Literal Decoder also uses "matchByte" that represents 

+the byte in OutputStream at position the is the DISTANCE bytes before 

+current position, where the DISTANCE is the distance in DISTANCE-LENGTH pair

+of latest decoded match.

+

+The following code decodes one literal and puts it to Sliding Window buffer:

+

+  void DecodeLiteral(unsigned state, UInt32 rep0)

+  {

+    unsigned prevByte = 0;

+    if (!OutWindow.IsEmpty())

+      prevByte = OutWindow.GetByte(1);

+    

+    unsigned symbol = 1;

+    unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));

+    CProb *probs = &LitProbs[(UInt32)0x300 * litState];

+    

+    if (state >= 7)

+    {

+      unsigned matchByte = OutWindow.GetByte(rep0 + 1);

+      do

+      {

+        unsigned matchBit = (matchByte >> 7) & 1;

+        matchByte <<= 1;

+        unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);

+        symbol = (symbol << 1) | bit;

+        if (matchBit != bit)

+          break;

+      }

+      while (symbol < 0x100);

+    }

+    while (symbol < 0x100)

+      symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);

+    OutWindow.PutByte((Byte)(symbol - 0x100));

+  }

+

+

+The match length decoding

+-------------------------

+

+The match length decoder returns normalized (zero-based value) 

+length of match. That value can be converted to real length of the match 

+with the following code:

+

+#define kMatchMinLen 2

+

+    matchLen = len + kMatchMinLen;

+

+The match length decoder can return the values from 0 to 271.

+And the corresponded real match length values can be in the range 

+from 2 to 273.

+

+The following scheme is used for the match length encoding:

+

+  Binary encoding    Binary Tree structure    Zero-based match length 

+  sequence                                    (binary + decimal):

+

+  0 xxx              LowCoder[posState]       xxx

+  1 0 yyy            MidCoder[posState]       yyy + 8

+  1 1 zzzzzzzz       HighCoder                zzzzzzzz + 16

+

+LZMA uses bit model variable "Choice" to decode the first selection bit.

+

+If the first selection bit is equal to 0, the decoder uses binary tree 

+  LowCoder[posState] to decode 3-bit zero-based match length (xxx).

+

+If the first selection bit is equal to 1, the decoder uses bit model 

+  variable "Choice2" to decode the second selection bit.

+

+  If the second selection bit is equal to 0, the decoder uses binary tree 

+    MidCoder[posState] to decode 3-bit "yyy" value, and zero-based match

+    length is equal to (yyy + 8).

+

+  If the second selection bit is equal to 1, the decoder uses binary tree 

+    HighCoder to decode 8-bit "zzzzzzzz" value, and zero-based 

+    match length is equal to (zzzzzzzz + 16).

+

+LZMA uses "posState" value as context to select the binary tree 

+from LowCoder and MidCoder binary tree arrays:

+

+    unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);

+

+The full code of the length decoder:

+

+class CLenDecoder

+{

+  CProb Choice;

+  CProb Choice2;

+  CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];

+  CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];

+  CBitTreeDecoder<8> HighCoder;

+

+public:

+

+  void Init()

+  {

+    Choice = PROB_INIT_VAL;

+    Choice2 = PROB_INIT_VAL;

+    HighCoder.Init();

+    for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)

+    {

+      LowCoder[i].Init();

+      MidCoder[i].Init();

+    }

+  }

+

+  unsigned Decode(CRangeDecoder *rc, unsigned posState)

+  {

+    if (rc->DecodeBit(&Choice) == 0)

+      return LowCoder[posState].Decode(rc);

+    if (rc->DecodeBit(&Choice2) == 0)

+      return 8 + MidCoder[posState].Decode(rc);

+    return 16 + HighCoder.Decode(rc);

+  }

+};

+

+The LZMA decoder uses two instances of CLenDecoder class.

+The first instance is for the matches of "Simple Match" type,

+and the second instance is for the matches of "Rep Match" type:

+

+  CLenDecoder LenDecoder;

+  CLenDecoder RepLenDecoder;

+

+

+The match distance decoding

+---------------------------

+

+LZMA supports dictionary sizes up to 4 GiB minus 1.

+The value of match distance (decoded by distance decoder) can be 

+from 1 to 2^32. But the distance value that is equal to 2^32 is used to

+indicate the "End of stream" marker. So real largest match distance 

+that is used for LZ-window match is (2^32 - 1).

+

+LZMA uses normalized match length (zero-based length) 

+to calculate the context state "lenState" do decode the distance value:

+

+#define kNumLenToPosStates 4

+

+    unsigned lenState = len;

+    if (lenState > kNumLenToPosStates - 1)

+      lenState = kNumLenToPosStates - 1;

+

+The distance decoder returns the "dist" value that is zero-based value 

+of match distance. The real match distance can be calculated with the

+following code:

+  

+  matchDistance = dist + 1; 

+

+The state of the distance decoder and the initialization code: 

+

+  #define kEndPosModelIndex 14

+  #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))

+  #define kNumAlignBits 4

+

+  CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];

+  CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];

+  CBitTreeDecoder<kNumAlignBits> AlignDecoder;

+

+  void InitDist()

+  {

+    for (unsigned i = 0; i < kNumLenToPosStates; i++)

+      PosSlotDecoder[i].Init();

+    AlignDecoder.Init();

+    INIT_PROBS(PosDecoders);

+  }

+

+At first stage the distance decoder decodes 6-bit "posSlot" value with bit

+tree decoder from PosSlotDecoder array. It's possible to get 2^6=64 different 

+"posSlot" values.

+

+    unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);

+

+The encoding scheme for distance value is shown in the following table:

+

+posSlot (decimal) /

+      zero-based distance (binary)

+ 0    0

+ 1    1

+ 2    10

+ 3    11

+

+ 4    10 x

+ 5    11 x

+ 6    10 xx

+ 7    11 xx

+ 8    10 xxx

+ 9    11 xxx

+10    10 xxxx

+11    11 xxxx

+12    10 xxxxx

+13    11 xxxxx

+

+14    10 yy zzzz

+15    11 yy zzzz

+16    10 yyy zzzz

+17    11 yyy zzzz

+...

+62    10 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz

+63    11 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz

+

+where 

+  "x ... x" means the sequence of binary symbols encoded with binary tree and 

+      "Reverse" scheme. It uses separated binary tree for each posSlot from 4 to 13.

+  "y" means direct bit encoded with range coder.

+  "zzzz" means the sequence of four binary symbols encoded with binary

+      tree with "Reverse" scheme, where one common binary tree "AlignDecoder"

+      is used for all posSlot values.

+

+If (posSlot < 4), the "dist" value is equal to posSlot value.

+

+If (posSlot >= 4), the decoder uses "posSlot" value to calculate the value of

+  the high bits of "dist" value and the number of the low bits.

+

+  If (4 <= posSlot < kEndPosModelIndex), the decoder uses bit tree decoders.

+    (one separated bit tree decoder per one posSlot value) and "Reverse" scheme.

+    In this implementation we use one CProb array "PosDecoders" that contains 

+    all CProb variables for all these bit decoders.

+  

+  if (posSlot >= kEndPosModelIndex), the middle bits are decoded as direct 

+    bits from RangeDecoder and the low 4 bits are decoded with a bit tree 

+    decoder "AlignDecoder" with "Reverse" scheme.

+

+The code to decode zero-based match distance:

+  

+  unsigned DecodeDistance(unsigned len)

+  {

+    unsigned lenState = len;

+    if (lenState > kNumLenToPosStates - 1)

+      lenState = kNumLenToPosStates - 1;

+    

+    unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);

+    if (posSlot < 4)

+      return posSlot;

+    

+    unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);

+    UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);

+    if (posSlot < kEndPosModelIndex)

+      dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);

+    else

+    {

+      dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;

+      dist += AlignDecoder.ReverseDecode(&RangeDec);

+    }

+    return dist;

+  }

+

+

+

+LZMA Decoding modes

+-------------------

+

+There are 2 types of LZMA streams:

+

+1) The stream with "End of stream" marker.

+2) The stream without "End of stream" marker.

+

+And the LZMA Decoder supports 3 modes of decoding:

+

+1) The unpack size is undefined. The LZMA decoder stops decoding after 

+   getting "End of stream" marker. 

+   The input variables for that case:

+    

+      markerIsMandatory = true

+      unpackSizeDefined = false

+      unpackSize contains any value

+

+2) The unpack size is defined and LZMA decoder supports both variants, 

+   where the stream can contain "End of stream" marker or the stream is

+   finished without "End of stream" marker. The LZMA decoder must detect 

+   any of these situations.

+   The input variables for that case:

+    

+      markerIsMandatory = false

+      unpackSizeDefined = true

+      unpackSize contains unpack size

+

+3) The unpack size is defined and the LZMA stream must contain 

+   "End of stream" marker

+   The input variables for that case:

+    

+      markerIsMandatory = true

+      unpackSizeDefined = true

+      unpackSize contains unpack size

+

+

+The main loop of decoder

+------------------------

+

+The main loop of LZMA decoder:

+

+Initialize the LZMA state.

+loop

+{

+  // begin of loop

+  Check "end of stream" conditions.

+  Decode Type of MATCH / LITERAL. 

+    If it's LITERAL, decode LITERAL value and put the LITERAL to Window.

+    If it's MATCH, decode the length of match and the match distance. 

+        Check error conditions, check end of stream conditions and copy

+        the sequence of match bytes from sliding window to current position

+        in window.

+  Go to begin of loop

+}

+

+The reference implementation of LZMA decoder uses "unpackSize" variable

+to keep the number of remaining bytes in output stream. So it reduces 

+"unpackSize" value after each decoded LITERAL or MATCH.

+

+The following code contains the "end of stream" condition check at the start

+of the loop:

+

+    if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)

+      if (RangeDec.IsFinishedOK())

+        return LZMA_RES_FINISHED_WITHOUT_MARKER;

+

+LZMA uses three types of matches:

+

+1) "Simple Match" -     the match with distance value encoded with bit models.

+

+2) "Rep Match" -        the match that uses the distance from distance

+                        history table.

+

+3) "Short Rep Match" -  the match of single byte length, that uses the latest 

+                        distance from distance history table.

+

+The LZMA decoder keeps the history of latest 4 match distances that were used 

+by decoder. That set of 4 variables contains zero-based match distances and 

+these variables are initialized with zero values:

+

+  UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;

+

+The LZMA decoder uses binary model variables to select type of MATCH or LITERAL:

+

+#define kNumStates 12

+#define kNumPosBitsMax 4

+

+  CProb IsMatch[kNumStates << kNumPosBitsMax];

+  CProb IsRep[kNumStates];

+  CProb IsRepG0[kNumStates];

+  CProb IsRepG1[kNumStates];

+  CProb IsRepG2[kNumStates];

+  CProb IsRep0Long[kNumStates << kNumPosBitsMax];

+

+The decoder uses "state" variable value to select exact variable 

+from "IsRep", "IsRepG0", "IsRepG1" and "IsRepG2" arrays.

+The "state" variable can get the value from 0 to 11.

+Initial value for "state" variable is zero:

+

+  unsigned state = 0;

+

+The "state" variable is updated after each LITERAL or MATCH with one of the

+following functions:

+

+unsigned UpdateState_Literal(unsigned state)

+{

+  if (state < 4) return 0;

+  else if (state < 10) return state - 3;

+  else return state - 6;

+}

+unsigned UpdateState_Match   (unsigned state) { return state < 7 ? 7 : 10; }

+unsigned UpdateState_Rep     (unsigned state) { return state < 7 ? 8 : 11; }

+unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }

+

+The decoder calculates "state2" variable value to select exact variable from 

+"IsMatch" and "IsRep0Long" arrays:

+

+unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);

+unsigned state2 = (state << kNumPosBitsMax) + posState;

+

+The decoder uses the following code flow scheme to select exact 

+type of LITERAL or MATCH:

+

+IsMatch[state2] decode

+  0 - the Literal

+  1 - the Match

+    IsRep[state] decode

+      0 - Simple Match

+      1 - Rep Match

+        IsRepG0[state] decode

+          0 - the distance is rep0

+            IsRep0Long[state2] decode

+              0 - Short Rep Match

+              1 - Rep Match 0

+          1 - 

+            IsRepG1[state] decode

+              0 - Rep Match 1

+              1 - 

+                IsRepG2[state] decode

+                  0 - Rep Match 2

+                  1 - Rep Match 3

+

+

+LITERAL symbol

+--------------

+If the value "0" was decoded with IsMatch[state2] decoding, we have "LITERAL" type.

+

+At first the LZMA decoder must check that it doesn't exceed 

+specified uncompressed size:

+

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+

+Then it decodes literal value and puts it to sliding window:

+

+      DecodeLiteral(state, rep0);

+

+Then the decoder must update the "state" value and "unpackSize" value;

+

+      state = UpdateState_Literal(state);

+      unpackSize--;

+

+Then the decoder must go to the begin of main loop to decode next Match or Literal.

+

+

+Simple Match

+------------

+

+If the value "1" was decoded with IsMatch[state2] decoding,

+we have the "Simple Match" type.

+

+The distance history table is updated with the following scheme:

+    

+      rep3 = rep2;

+      rep2 = rep1;

+      rep1 = rep0;

+

+The zero-based length is decoded with "LenDecoder":

+

+      len = LenDecoder.Decode(&RangeDec, posState);

+

+The state is update with UpdateState_Match function:

+

+      state = UpdateState_Match(state);

+

+and the new "rep0" value is decoded with DecodeDistance:

+

+      rep0 = DecodeDistance(len);

+

+That "rep0" will be used as zero-based distance for current match.

+

+If the value of "rep0" is equal to 0xFFFFFFFF, it means that we have 

+"End of stream" marker, so we can stop decoding and check finishing 

+condition in Range Decoder:

+

+      if (rep0 == 0xFFFFFFFF)

+        return RangeDec.IsFinishedOK() ?

+            LZMA_RES_FINISHED_WITH_MARKER :

+            LZMA_RES_ERROR;

+

+If uncompressed size is defined, LZMA decoder must check that it doesn't 

+exceed that specified uncompressed size:

+

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+

+Also the decoder must check that "rep0" value is not larger than dictionary size

+and is not larger than the number of already decoded bytes:

+

+      if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))

+        return LZMA_RES_ERROR;

+

+Then the decoder must copy match bytes as described in 

+"The match symbols copying" section.

+

+

+Rep Match

+---------

+

+If the LZMA decoder has decoded the value "1" with IsRep[state] variable,

+we have "Rep Match" type.

+

+At first the LZMA decoder must check that it doesn't exceed 

+specified uncompressed size:

+

+      if (unpackSizeDefined && unpackSize == 0)

+        return LZMA_RES_ERROR;

+

+Also the decoder must return error, if the LZ window is empty:

+

+      if (OutWindow.IsEmpty())

+        return LZMA_RES_ERROR;

+

+If the match type is "Rep Match", the decoder uses one of the 4 variables of

+distance history table to get the value of distance for current match.

+And there are 4 corresponding ways of decoding flow. 

+

+The decoder updates the distance history with the following scheme 

+depending from type of match:

+

+- "Rep Match 0" or "Short Rep Match":

+      ; LZMA doesn't update the distance history    

+

+- "Rep Match 1":

+      UInt32 dist = rep1;

+      rep1 = rep0;

+      rep0 = dist;

+

+- "Rep Match 2":

+      UInt32 dist = rep2;

+      rep2 = rep1;

+      rep1 = rep0;

+      rep0 = dist;

+

+- "Rep Match 3":

+      UInt32 dist = rep3;

+      rep3 = rep2;

+      rep2 = rep1;

+      rep1 = rep0;

+      rep0 = dist;

+

+Then the decoder decodes exact subtype of "Rep Match" using "IsRepG0", "IsRep0Long",

+"IsRepG1", "IsRepG2".

+

+If the subtype is "Short Rep Match", the decoder updates the state, puts 

+the one byte from window to current position in window and goes to next 

+MATCH/LITERAL symbol (the begin of main loop):

+

+          state = UpdateState_ShortRep(state);

+          OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));

+          unpackSize--;

+          continue;

+

+In other cases (Rep Match 0/1/2/3), it decodes the zero-based 

+length of match with "RepLenDecoder" decoder:

+

+      len = RepLenDecoder.Decode(&RangeDec, posState);

+

+Then it updates the state:

+

+      state = UpdateState_Rep(state);

+

+Then the decoder must copy match bytes as described in 

+"The Match symbols copying" section.

+

+

+The match symbols copying

+-------------------------

+

+If we have the match (Simple Match or Rep Match 0/1/2/3), the decoder must

+copy the sequence of bytes with calculated match distance and match length.

+If uncompressed size is defined, LZMA decoder must check that it doesn't 

+exceed that specified uncompressed size:

+

+    len += kMatchMinLen;

+    bool isError = false;

+    if (unpackSizeDefined && unpackSize < len)

+    {

+      len = (unsigned)unpackSize;

+      isError = true;

+    }

+    OutWindow.CopyMatch(rep0 + 1, len);

+    unpackSize -= len;

+    if (isError)

+      return LZMA_RES_ERROR;

+

+Then the decoder must go to the begin of main loop to decode next MATCH or LITERAL.

+

+

+

+NOTES

+-----

+

+This specification doesn't describe the variant of decoder implementation 

+that supports partial decoding. Such partial decoding case can require some 

+changes in "end of stream" condition checks code. Also such code 

+can use additional status codes, returned by decoder.

+

+This specification uses C++ code with templates to simplify describing.

+The optimized version of LZMA decoder doesn't need templates.

+Such optimized version can use just two arrays of CProb variables:

+  1) The dynamic array of CProb variables allocated for the Literal Decoder.

+  2) The one common array that contains all other CProb variables.

+

+

+References:      

+

+1. G. N. N. Martin, Range encoding: an algorithm for removing redundancy 

+   from a digitized message, Video & Data Recording Conference, 

+   Southampton, UK, July 24-27, 1979.

diff --git a/DOC/lzma.txt b/DOC/lzma.txt
new file mode 100644
index 0000000..f9a80ae
--- /dev/null
+++ b/DOC/lzma.txt
@@ -0,0 +1,328 @@
+LZMA compression

+----------------

+Version: 9.35

+

+This file describes LZMA encoding and decoding functions written in C language.

+

+LZMA is an improved version of famous LZ77 compression algorithm. 

+It was improved in way of maximum increasing of compression ratio,

+keeping high decompression speed and low memory requirements for 

+decompressing.

+

+Note: you can read also LZMA Specification (lzma-specification.txt from LZMA SDK)

+

+Also you can look source code for LZMA encoding and decoding:

+  C/Util/Lzma/LzmaUtil.c

+

+

+LZMA compressed file format

+---------------------------

+Offset Size Description

+  0     1   Special LZMA properties (lc,lp, pb in encoded form)

+  1     4   Dictionary size (little endian)

+  5     8   Uncompressed size (little endian). -1 means unknown size

+ 13         Compressed data

+

+

+

+ANSI-C LZMA Decoder

+~~~~~~~~~~~~~~~~~~~

+

+Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.

+If you want to use old interfaces you can download previous version of LZMA SDK

+from sourceforge.net site.

+

+To use ANSI-C LZMA Decoder you need the following files:

+1) LzmaDec.h + LzmaDec.c + Types.h

+

+Look example code:

+  C/Util/Lzma/LzmaUtil.c

+

+

+Memory requirements for LZMA decoding

+-------------------------------------

+

+Stack usage of LZMA decoding function for local variables is not 

+larger than 200-400 bytes.

+

+LZMA Decoder uses dictionary buffer and internal state structure.

+Internal state structure consumes

+  state_size = (4 + (1.5 << (lc + lp))) KB

+by default (lc=3, lp=0), state_size = 16 KB.

+

+

+How To decompress data

+----------------------

+

+LZMA Decoder (ANSI-C version) now supports 2 interfaces:

+1) Single-call Decompressing

+2) Multi-call State Decompressing (zlib-like interface)

+

+You must use external allocator:

+Example:

+void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }

+void SzFree(void *p, void *address) { p = p; free(address); }

+ISzAlloc alloc = { SzAlloc, SzFree };

+

+You can use p = p; operator to disable compiler warnings.

+

+

+Single-call Decompressing

+-------------------------

+When to use: RAM->RAM decompressing

+Compile files: LzmaDec.h + LzmaDec.c + Types.h

+Compile defines: no defines

+Memory Requirements:

+  - Input buffer: compressed size

+  - Output buffer: uncompressed size

+  - LZMA Internal Structures: state_size (16 KB for default settings) 

+

+Interface:

+  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 

+      ELzmaStatus *status, ISzAlloc *alloc);

+  In: 

+    dest     - output data

+    destLen  - output data size

+    src      - input data

+    srcLen   - input data size

+    propData - LZMA properties  (5 bytes)

+    propSize - size of propData buffer (5 bytes)

+    finishMode - It has meaning only if the decoding reaches output limit (*destLen).

+         LZMA_FINISH_ANY - Decode just destLen bytes.

+         LZMA_FINISH_END - Stream must be finished after (*destLen).

+                           You can use LZMA_FINISH_END, when you know that 

+                           current output buffer covers last bytes of stream. 

+    alloc    - Memory allocator.

+

+  Out: 

+    destLen  - processed output size 

+    srcLen   - processed input size 

+

+  Output:

+    SZ_OK

+      status:

+        LZMA_STATUS_FINISHED_WITH_MARK

+        LZMA_STATUS_NOT_FINISHED 

+        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

+    SZ_ERROR_DATA - Data error

+    SZ_ERROR_MEM  - Memory allocation error

+    SZ_ERROR_UNSUPPORTED - Unsupported properties

+    SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+

+  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,

+  and output value of destLen will be less than output buffer size limit.

+

+  You can use multiple checks to test data integrity after full decompression:

+    1) Check Result and "status" variable.

+    2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.

+    3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 

+       You must use correct finish mode in that case. */ 

+

+

+Multi-call State Decompressing (zlib-like interface)

+----------------------------------------------------

+

+When to use: file->file decompressing 

+Compile files: LzmaDec.h + LzmaDec.c + Types.h

+

+Memory Requirements:

+ - Buffer for input stream: any size (for example, 16 KB)

+ - Buffer for output stream: any size (for example, 16 KB)

+ - LZMA Internal Structures: state_size (16 KB for default settings) 

+ - LZMA dictionary (dictionary size is encoded in LZMA properties header)

+

+1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:

+   unsigned char header[LZMA_PROPS_SIZE + 8];

+   ReadFile(inFile, header, sizeof(header)

+

+2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties

+

+  CLzmaDec state;

+  LzmaDec_Constr(&state);

+  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);

+  if (res != SZ_OK)

+    return res;

+

+3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop

+

+  LzmaDec_Init(&state);

+  for (;;)

+  {

+    ... 

+    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 

+        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);

+    ...

+  }

+

+

+4) Free all allocated structures

+  LzmaDec_Free(&state, &g_Alloc);

+

+Look example code:

+  C/Util/Lzma/LzmaUtil.c

+

+

+How To compress data

+--------------------

+

+Compile files: 

+  Types.h

+  Threads.h	

+  LzmaEnc.h

+  LzmaEnc.c

+  LzFind.h

+  LzFind.c

+  LzFindMt.h

+  LzFindMt.c

+  LzHash.h

+

+Memory Requirements:

+  - (dictSize * 11.5 + 6 MB) + state_size

+

+Lzma Encoder can use two memory allocators:

+1) alloc - for small arrays.

+2) allocBig - for big arrays.

+

+For example, you can use Large RAM Pages (2 MB) in allocBig allocator for 

+better compression speed. Note that Windows has bad implementation for 

+Large RAM Pages. 

+It's OK to use same allocator for alloc and allocBig.

+

+

+Single-call Compression with callbacks

+--------------------------------------

+

+Look example code:

+  C/Util/Lzma/LzmaUtil.c

+

+When to use: file->file compressing 

+

+1) you must implement callback structures for interfaces:

+ISeqInStream

+ISeqOutStream

+ICompressProgress

+ISzAlloc

+

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

+

+  CFileSeqInStream inStream;

+  CFileSeqOutStream outStream;

+

+  inStream.funcTable.Read = MyRead;

+  inStream.file = inFile;

+  outStream.funcTable.Write = MyWrite;

+  outStream.file = outFile;

+

+

+2) Create CLzmaEncHandle object;

+

+  CLzmaEncHandle enc;

+

+  enc = LzmaEnc_Create(&g_Alloc);

+  if (enc == 0)

+    return SZ_ERROR_MEM;

+

+

+3) initialize CLzmaEncProps properties;

+

+  LzmaEncProps_Init(&props);

+

+  Then you can change some properties in that structure.

+

+4) Send LZMA properties to LZMA Encoder

+

+  res = LzmaEnc_SetProps(enc, &props);

+

+5) Write encoded properties to header

+

+    Byte header[LZMA_PROPS_SIZE + 8];

+    size_t headerSize = LZMA_PROPS_SIZE;

+    UInt64 fileSize;

+    int i;

+

+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);

+    fileSize = MyGetFileLength(inFile);

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

+      header[headerSize++] = (Byte)(fileSize >> (8 * i));

+    MyWriteFileAndCheck(outFile, header, headerSize)

+

+6) Call encoding function:

+      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, 

+        NULL, &g_Alloc, &g_Alloc);

+

+7) Destroy LZMA Encoder Object

+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);

+

+

+If callback function return some error code, LzmaEnc_Encode also returns that code

+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.

+

+

+Single-call RAM->RAM Compression

+--------------------------------

+

+Single-call RAM->RAM Compression is similar to Compression with callbacks,

+but you provide pointers to buffers instead of pointers to stream callbacks:

+

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

+

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error 

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+

+

+

+Defines

+-------

+

+_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.

+

+_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for 

+                 some structures will be doubled in that case.

+

+_LZMA_UINT32_IS_ULONG  - Define it if int is 16-bit on your compiler and long is 32-bit.

+

+_LZMA_NO_SYSTEM_SIZE_T  - Define it if you don't want to use size_t type.

+

+

+_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.

+

+

+C++ LZMA Encoder/Decoder 

+~~~~~~~~~~~~~~~~~~~~~~~~

+C++ LZMA code use COM-like interfaces. So if you want to use it, 

+you can study basics of COM/OLE.

+C++ LZMA code is just wrapper over ANSI-C code.

+

+

+C++ Notes

+~~~~~~~~~~~~~~~~~~~~~~~~

+If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),

+you must check that you correctly work with "new" operator.

+7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.

+So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:

+operator new(size_t size)

+{

+  void *p = ::malloc(size);

+  if (p == 0)

+    throw CNewException();

+  return p;

+}

+If you use MSCV that throws exception for "new" operator, you can compile without 

+"NewHandler.cpp". So standard exception will be used. Actually some code of 

+7-Zip catches any exception in internal code and converts it to HRESULT code.

+So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.

+

+---

+

+http://www.7-zip.org

+http://www.7-zip.org/sdk.html

+http://www.7-zip.org/support.html

diff --git a/Java/SevenZip/CRC.java b/Java/SevenZip/CRC.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZ/BinTree.java b/Java/SevenZip/Compression/LZ/BinTree.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZ/InWindow.java b/Java/SevenZip/Compression/LZ/InWindow.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZ/OutWindow.java b/Java/SevenZip/Compression/LZ/OutWindow.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZMA/Base.java b/Java/SevenZip/Compression/LZMA/Base.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZMA/Decoder.java b/Java/SevenZip/Compression/LZMA/Decoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/LZMA/Encoder.java b/Java/SevenZip/Compression/LZMA/Encoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java b/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java b/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/RangeCoder/Decoder.java b/Java/SevenZip/Compression/RangeCoder/Decoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/Compression/RangeCoder/Encoder.java b/Java/SevenZip/Compression/RangeCoder/Encoder.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/ICodeProgress.java b/Java/SevenZip/ICodeProgress.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/LzmaAlone.java b/Java/SevenZip/LzmaAlone.java
old mode 100755
new mode 100644
diff --git a/Java/SevenZip/LzmaBench.java b/Java/SevenZip/LzmaBench.java
old mode 100755
new mode 100644
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..8677bf6
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,11 @@
+LZMA SDK is written and placed in the public domain by Igor Pavlov.
+
+Some code in LZMA SDK is based on public domain code from another developers:
+  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.
+
+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/lzma.txt b/lzma.txt
deleted file mode 100755
index 579f2cc..0000000
--- a/lzma.txt
+++ /dev/null
@@ -1,598 +0,0 @@
-LZMA SDK 9.20

--------------

-

-LZMA SDK provides the documentation, samples, header files, libraries, 

-and tools you need to develop applications that use LZMA compression.

-

-LZMA is default and general compression method of 7z format

-in 7-Zip compression program (www.7-zip.org). LZMA provides high 

-compression ratio and very fast decompression.

-

-LZMA is an improved version of famous LZ77 compression algorithm. 

-It was improved in way of maximum increasing of compression ratio,

-keeping high decompression speed and low memory requirements for 

-decompressing.

-

-

-

-LICENSE

--------

-

-LZMA SDK is written and placed in the public domain by Igor Pavlov.

-

-Some code in LZMA SDK is based on public domain code from another developers:

-  1) PPMd var.H (2001): Dmitry Shkarin

-  2) SHA-256: Wei Dai (Crypto++ library)

-

-

-LZMA SDK Contents

------------------

-

-LZMA SDK includes:

-

-  - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing

-  - Compiled file->file LZMA compressing/decompressing program for Windows system

-

-

-UNIX/Linux version 

-------------------

-To compile C++ version of file->file LZMA encoding, go to directory

-CPP/7zip/Bundles/LzmaCon

-and call make to recompile it:

-  make -f makefile.gcc clean all

-

-In some UNIX/Linux versions you must compile LZMA with static libraries.

-To compile with static libraries, you can use 

-LIB = -lm -static

-

-

-Files

----------------------

-lzma.txt     - LZMA SDK description (this file)

-7zFormat.txt - 7z Format description

-7zC.txt      - 7z ANSI-C Decoder description

-methods.txt  - Compression method IDs for .7z

-lzma.exe     - Compiled file->file LZMA encoder/decoder for Windows

-7zr.exe      - 7-Zip with 7z/lzma/xz support.

-history.txt  - history of the LZMA SDK

-

-

-Source code structure

----------------------

-

-C/  - C files

-        7zCrc*.*   - CRC code

-        Alloc.*    - Memory allocation functions

-        Bra*.*     - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code

-        LzFind.*   - Match finder for LZ (LZMA) encoders 

-        LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding

-        LzHash.h   - Additional file for LZ match finder

-        LzmaDec.*  - LZMA decoding

-        LzmaEnc.*  - LZMA encoding

-        LzmaLib.*  - LZMA Library for DLL calling

-        Types.h    - Basic types for another .c files

-        Threads.*  - The code for multithreading.

-

-    LzmaLib  - LZMA Library (.DLL for Windows)

-    

-    LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).

-

-    Archive - files related to archiving

-      7z     - 7z ANSI-C Decoder

-

-CPP/ -- CPP files

-

-  Common  - common files for C++ projects

-  Windows - common files for Windows related code

-

-  7zip    - files related to 7-Zip Project

-

-    Common   - common files for 7-Zip

-

-    Compress - files related to compression/decompression

-

-    Archive - files related to archiving

-

-      Common   - common files for archive handling

-      7z       - 7z C++ Encoder/Decoder

-

-    Bundles    - Modules that are bundles of other modules

-  

-      Alone7z           - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2

-      LzmaCon           - lzma.exe: LZMA compression/decompression

-      Format7zR         - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2

-      Format7zExtractR  - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.

-

-    UI        - User Interface files

-         

-      Client7z - Test application for 7za.dll,  7zr.dll, 7zxr.dll

-      Common   - Common UI files

-      Console  - Code for console archiver

-

-

-

-CS/ - C# files

-  7zip

-    Common   - some common files for 7-Zip

-    Compress - files related to compression/decompression

-      LZ     - files related to LZ (Lempel-Ziv) compression algorithm

-      LZMA         - LZMA compression/decompression

-      LzmaAlone    - file->file LZMA compression/decompression

-      RangeCoder   - Range Coder (special code of compression/decompression)

-

-Java/  - Java files

-  SevenZip

-    Compression    - files related to compression/decompression

-      LZ           - files related to LZ (Lempel-Ziv) compression algorithm

-      LZMA         - LZMA compression/decompression

-      RangeCoder   - Range Coder (special code of compression/decompression)

-

-

-C/C++ source code of LZMA SDK is part of 7-Zip project.

-7-Zip source code can be downloaded from 7-Zip's SourceForge page:

-

-  http://sourceforge.net/projects/sevenzip/

-

-

-

-LZMA features

--------------

-  - Variable dictionary size (up to 1 GB)

-  - Estimated compressing speed: about 2 MB/s on 2 GHz CPU

-  - Estimated decompressing speed: 

-      - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64

-      - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC

-  - Small memory requirements for decompressing (16 KB + DictionarySize)

-  - Small code size for decompressing: 5-8 KB

-

-LZMA decoder uses only integer operations and can be 

-implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).

-

-Some critical operations that affect the speed of LZMA decompression:

-  1) 32*16 bit integer multiply

-  2) Misspredicted branches (penalty mostly depends from pipeline length)

-  3) 32-bit shift and arithmetic operations

-

-The speed of LZMA decompressing mostly depends from CPU speed.

-Memory speed has no big meaning. But if your CPU has small data cache, 

-overall weight of memory speed will slightly increase.

-

-

-How To Use

-----------

-

-Using LZMA encoder/decoder executable

---------------------------------------

-

-Usage:  LZMA <e|d> inputFile outputFile [<switches>...]

-

-  e: encode file

-

-  d: decode file

-

-  b: Benchmark. There are two tests: compressing and decompressing 

-     with LZMA method. Benchmark shows rating in MIPS (million 

-     instructions per second). Rating value is calculated from 

-     measured speed and it is normalized with Intel's Core 2 results.

-     Also Benchmark checks possible hardware errors (RAM 

-     errors in most cases). Benchmark uses these settings:

-     (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. 

-     Also you can change the number of iterations. Example for 30 iterations:

-       LZMA b 30

-     Default number of iterations is 10.

-

-<Switches>

-  

-

-  -a{N}:  set compression mode 0 = fast, 1 = normal

-          default: 1 (normal)

-

-  d{N}:   Sets Dictionary size - [0, 30], default: 23 (8MB)

-          The maximum value for dictionary size is 1 GB = 2^30 bytes.

-          Dictionary size is calculated as DictionarySize = 2^N bytes. 

-          For decompressing file compressed by LZMA method with dictionary 

-          size D = 2^N you need about D bytes of memory (RAM).

-

-  -fb{N}: set number of fast bytes - [5, 273], default: 128

-          Usually big number gives a little bit better compression ratio 

-          and slower compression process.

-

-  -lc{N}: set number of literal context bits - [0, 8], default: 3

-          Sometimes lc=4 gives gain for big files.

-

-  -lp{N}: set number of literal pos bits - [0, 4], default: 0

-          lp switch is intended for periodical data when period is 

-          equal 2^N. For example, for 32-bit (4 bytes) 

-          periodical data you can use lp=2. Often it's better to set lc0, 

-          if you change lp switch.

-

-  -pb{N}: set number of pos bits - [0, 4], default: 2

-          pb switch is intended for periodical data 

-          when period is equal 2^N.

-

-  -mf{MF_ID}: set Match Finder. Default: bt4. 

-              Algorithms from hc* group doesn't provide good compression 

-              ratio, but they often works pretty fast in combination with 

-              fast mode (-a0).

-

-              Memory requirements depend from dictionary size 

-              (parameter "d" in table below). 

-

-               MF_ID     Memory                   Description

-

-                bt2    d *  9.5 + 4MB  Binary Tree with 2 bytes hashing.

-                bt3    d * 11.5 + 4MB  Binary Tree with 3 bytes hashing.

-                bt4    d * 11.5 + 4MB  Binary Tree with 4 bytes hashing.

-                hc4    d *  7.5 + 4MB  Hash Chain with 4 bytes hashing.

-

-  -eos:   write End Of Stream marker. By default LZMA doesn't write 

-          eos marker, since LZMA decoder knows uncompressed size 

-          stored in .lzma file header.

-

-  -si:    Read data from stdin (it will write End Of Stream marker).

-  -so:    Write data to stdout

-

-

-Examples:

-

-1) LZMA e file.bin file.lzma -d16 -lc0 

-

-compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)  

-and 0 literal context bits. -lc0 allows to reduce memory requirements 

-for decompression.

-

-

-2) LZMA e file.bin file.lzma -lc0 -lp2

-

-compresses file.bin to file.lzma with settings suitable 

-for 32-bit periodical data (for example, ARM or MIPS code).

-

-3) LZMA d file.lzma file.bin

-

-decompresses file.lzma to file.bin.

-

-

-Compression ratio hints

------------------------

-

-Recommendations

----------------

-

-To increase the compression ratio for LZMA compressing it's desirable 

-to have aligned data (if it's possible) and also it's desirable to locate

-data in such order, where code is grouped in one place and data is 

-grouped in other place (it's better than such mixing: code, data, code,

-data, ...).

-

-

-Filters

--------

-You can increase the compression ratio for some data types, using

-special filters before compressing. For example, it's possible to 

-increase the compression ratio on 5-10% for code for those CPU ISAs: 

-x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.

-

-You can find C source code of such filters in C/Bra*.* files

-

-You can check the compression ratio gain of these filters with such 

-7-Zip commands (example for ARM code):

-No filter:

-  7z a a1.7z a.bin -m0=lzma

-

-With filter for little-endian ARM code:

-  7z a a2.7z a.bin -m0=arm -m1=lzma        

-

-It works in such manner:

-Compressing    = Filter_encoding + LZMA_encoding

-Decompressing  = LZMA_decoding + Filter_decoding

-

-Compressing and decompressing speed of such filters is very high,

-so it will not increase decompressing time too much.

-Moreover, it reduces decompression time for LZMA_decoding, 

-since compression ratio with filtering is higher.

-

-These filters convert CALL (calling procedure) instructions 

-from relative offsets to absolute addresses, so such data becomes more 

-compressible.

-

-For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.

-

-

-LZMA compressed file format

----------------------------

-Offset Size Description

-  0     1   Special LZMA properties (lc,lp, pb in encoded form)

-  1     4   Dictionary size (little endian)

-  5     8   Uncompressed size (little endian). -1 means unknown size

- 13         Compressed data

-

-

-ANSI-C LZMA Decoder

-~~~~~~~~~~~~~~~~~~~

-

-Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.

-If you want to use old interfaces you can download previous version of LZMA SDK

-from sourceforge.net site.

-

-To use ANSI-C LZMA Decoder you need the following files:

-1) LzmaDec.h + LzmaDec.c + Types.h

-LzmaUtil/LzmaUtil.c is example application that uses these files.

-

-

-Memory requirements for LZMA decoding

--------------------------------------

-

-Stack usage of LZMA decoding function for local variables is not 

-larger than 200-400 bytes.

-

-LZMA Decoder uses dictionary buffer and internal state structure.

-Internal state structure consumes

-  state_size = (4 + (1.5 << (lc + lp))) KB

-by default (lc=3, lp=0), state_size = 16 KB.

-

-

-How To decompress data

-----------------------

-

-LZMA Decoder (ANSI-C version) now supports 2 interfaces:

-1) Single-call Decompressing

-2) Multi-call State Decompressing (zlib-like interface)

-

-You must use external allocator:

-Example:

-void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }

-void SzFree(void *p, void *address) { p = p; free(address); }

-ISzAlloc alloc = { SzAlloc, SzFree };

-

-You can use p = p; operator to disable compiler warnings.

-

-

-Single-call Decompressing

--------------------------

-When to use: RAM->RAM decompressing

-Compile files: LzmaDec.h + LzmaDec.c + Types.h

-Compile defines: no defines

-Memory Requirements:

-  - Input buffer: compressed size

-  - Output buffer: uncompressed size

-  - LZMA Internal Structures: state_size (16 KB for default settings) 

-

-Interface:

-  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

-      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 

-      ELzmaStatus *status, ISzAlloc *alloc);

-  In: 

-    dest     - output data

-    destLen  - output data size

-    src      - input data

-    srcLen   - input data size

-    propData - LZMA properties  (5 bytes)

-    propSize - size of propData buffer (5 bytes)

-    finishMode - It has meaning only if the decoding reaches output limit (*destLen).

-         LZMA_FINISH_ANY - Decode just destLen bytes.

-         LZMA_FINISH_END - Stream must be finished after (*destLen).

-                           You can use LZMA_FINISH_END, when you know that 

-                           current output buffer covers last bytes of stream. 

-    alloc    - Memory allocator.

-

-  Out: 

-    destLen  - processed output size 

-    srcLen   - processed input size 

-

-  Output:

-    SZ_OK

-      status:

-        LZMA_STATUS_FINISHED_WITH_MARK

-        LZMA_STATUS_NOT_FINISHED 

-        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

-    SZ_ERROR_DATA - Data error

-    SZ_ERROR_MEM  - Memory allocation error

-    SZ_ERROR_UNSUPPORTED - Unsupported properties

-    SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

-

-  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,

-  and output value of destLen will be less than output buffer size limit.

-

-  You can use multiple checks to test data integrity after full decompression:

-    1) Check Result and "status" variable.

-    2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.

-    3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 

-       You must use correct finish mode in that case. */ 

-

-

-Multi-call State Decompressing (zlib-like interface)

-----------------------------------------------------

-

-When to use: file->file decompressing 

-Compile files: LzmaDec.h + LzmaDec.c + Types.h

-

-Memory Requirements:

- - Buffer for input stream: any size (for example, 16 KB)

- - Buffer for output stream: any size (for example, 16 KB)

- - LZMA Internal Structures: state_size (16 KB for default settings) 

- - LZMA dictionary (dictionary size is encoded in LZMA properties header)

-

-1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:

-   unsigned char header[LZMA_PROPS_SIZE + 8];

-   ReadFile(inFile, header, sizeof(header)

-

-2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties

-

-  CLzmaDec state;

-  LzmaDec_Constr(&state);

-  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);

-  if (res != SZ_OK)

-    return res;

-

-3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop

-

-  LzmaDec_Init(&state);

-  for (;;)

-  {

-    ... 

-    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 

-        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);

-    ...

-  }

-

-

-4) Free all allocated structures

-  LzmaDec_Free(&state, &g_Alloc);

-

-For full code example, look at C/LzmaUtil/LzmaUtil.c code.

-

-

-How To compress data

---------------------

-

-Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +

-LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h

-

-Memory Requirements:

-  - (dictSize * 11.5 + 6 MB) + state_size

-

-Lzma Encoder can use two memory allocators:

-1) alloc - for small arrays.

-2) allocBig - for big arrays.

-

-For example, you can use Large RAM Pages (2 MB) in allocBig allocator for 

-better compression speed. Note that Windows has bad implementation for 

-Large RAM Pages. 

-It's OK to use same allocator for alloc and allocBig.

-

-

-Single-call Compression with callbacks

---------------------------------------

-

-Check C/LzmaUtil/LzmaUtil.c as example, 

-

-When to use: file->file decompressing 

-

-1) you must implement callback structures for interfaces:

-ISeqInStream

-ISeqOutStream

-ICompressProgress

-ISzAlloc

-

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

-

-  CFileSeqInStream inStream;

-  CFileSeqOutStream outStream;

-

-  inStream.funcTable.Read = MyRead;

-  inStream.file = inFile;

-  outStream.funcTable.Write = MyWrite;

-  outStream.file = outFile;

-

-

-2) Create CLzmaEncHandle object;

-

-  CLzmaEncHandle enc;

-

-  enc = LzmaEnc_Create(&g_Alloc);

-  if (enc == 0)

-    return SZ_ERROR_MEM;

-

-

-3) initialize CLzmaEncProps properties;

-

-  LzmaEncProps_Init(&props);

-

-  Then you can change some properties in that structure.

-

-4) Send LZMA properties to LZMA Encoder

-

-  res = LzmaEnc_SetProps(enc, &props);

-

-5) Write encoded properties to header

-

-    Byte header[LZMA_PROPS_SIZE + 8];

-    size_t headerSize = LZMA_PROPS_SIZE;

-    UInt64 fileSize;

-    int i;

-

-    res = LzmaEnc_WriteProperties(enc, header, &headerSize);

-    fileSize = MyGetFileLength(inFile);

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

-      header[headerSize++] = (Byte)(fileSize >> (8 * i));

-    MyWriteFileAndCheck(outFile, header, headerSize)

-

-6) Call encoding function:

-      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, 

-        NULL, &g_Alloc, &g_Alloc);

-

-7) Destroy LZMA Encoder Object

-  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);

-

-

-If callback function return some error code, LzmaEnc_Encode also returns that code

-or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.

-

-

-Single-call RAM->RAM Compression

---------------------------------

-

-Single-call RAM->RAM Compression is similar to Compression with callbacks,

-but you provide pointers to buffers instead of pointers to stream callbacks:

-

-HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

-    CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 

-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

-

-Return code:

-  SZ_OK               - OK

-  SZ_ERROR_MEM        - Memory allocation error 

-  SZ_ERROR_PARAM      - Incorrect paramater

-  SZ_ERROR_OUTPUT_EOF - output buffer overflow

-  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

-

-

-

-Defines

--------

-

-_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.

-

-_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for 

-                 some structures will be doubled in that case.

-

-_LZMA_UINT32_IS_ULONG  - Define it if int is 16-bit on your compiler and long is 32-bit.

-

-_LZMA_NO_SYSTEM_SIZE_T  - Define it if you don't want to use size_t type.

-

-

-_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.

-

-

-C++ LZMA Encoder/Decoder 

-~~~~~~~~~~~~~~~~~~~~~~~~

-C++ LZMA code use COM-like interfaces. So if you want to use it, 

-you can study basics of COM/OLE.

-C++ LZMA code is just wrapper over ANSI-C code.

-

-

-C++ Notes

-~~~~~~~~~~~~~~~~~~~~~~~~

-If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),

-you must check that you correctly work with "new" operator.

-7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.

-So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:

-operator new(size_t size)

-{

-  void *p = ::malloc(size);

-  if (p == 0)

-    throw CNewException();

-  return p;

-}

-If you use MSCV that throws exception for "new" operator, you can compile without 

-"NewHandler.cpp". So standard exception will be used. Actually some code of 

-7-Zip catches any exception in internal code and converts it to HRESULT code.

-So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.

-

----

-

-http://www.7-zip.org

-http://www.7-zip.org/sdk.html

-http://www.7-zip.org/support.html