Compare commits

..

12 Commits
15.06 ... 16.03

Author SHA1 Message Date
Igor Pavlov
232ce79574 16.03 2016-12-08 12:12:54 +00:00
Igor Pavlov
1eddf527ca 16.02 2016-05-28 00:17:00 +01:00
Igor Pavlov
bec3b479dc 16.01 2016-05-28 00:16:59 +01:00
Igor Pavlov
66ac98bb02 16.00 2016-05-28 00:16:59 +01:00
Igor Pavlov
c20d013055 15.14 2016-05-28 00:16:58 +01:00
Igor Pavlov
9608215ad8 15.13 2016-05-28 00:16:58 +01:00
Igor Pavlov
5de23c1deb 15.12 2016-05-28 00:16:58 +01:00
Igor Pavlov
e24f7fba53 15.11 2016-05-28 00:16:57 +01:00
Igor Pavlov
7c8a265a15 15.10 2016-05-28 00:16:57 +01:00
Igor Pavlov
a663a6deb7 15.09 2016-05-28 00:16:56 +01:00
Igor Pavlov
6543c28020 15.08 2016-05-28 00:16:56 +01:00
Igor Pavlov
f6444c3256 15.07 2016-05-28 00:16:55 +01:00
408 changed files with 19779 additions and 6786 deletions

82
C/7z.h
View File

@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2014-02-08 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
@@ -48,21 +48,10 @@ typedef struct
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
UInt64 CodersUnpackSizes[SZ_NUM_CODERS_IN_FOLDER_MAX];
} CSzFolder; } CSzFolder;
/*
typedef struct
{
size_t CodersDataOffset;
size_t UnpackSizeDataOffset;
// UInt32 StartCoderUnpackSizesIndex;
UInt32 StartPackStreamIndex;
// UInt32 IndexOfMainOutStream;
} CSzFolder2;
*/
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes); SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
typedef struct typedef struct
{ {
@@ -92,47 +81,25 @@ typedef struct
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 NumFolders; UInt32 NumFolders;
UInt64 *PackPositions; // NumPackStreams + 1 UInt64 *PackPositions; // NumPackStreams + 1
CSzBitUi32s FolderCRCs; CSzBitUi32s FolderCRCs; // NumFolders
size_t *FoCodersOffsets; size_t *FoCodersOffsets; // NumFolders + 1
size_t *FoSizesOffsets; UInt32 *FoStartPackStreamIndex; // NumFolders + 1
// UInt32 StartCoderUnpackSizesIndex; UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
UInt32 *FoStartPackStreamIndex; Byte *FoToMainUnpackSizeIndex; // NumFolders
UInt64 *CoderUnpackSizes; // for all coders in all folders
// CSzFolder2 *Folders; // +1 item for sum values
Byte *CodersData; Byte *CodersData;
Byte *UnpackSizesData;
size_t UnpackSizesDataSize;
// UInt64 *CoderUnpackSizes;
} CSzAr; } CSzAr;
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, Byte *outBuffer, size_t outSize,
ISzAlloc *allocMain); ISzAlloc *allocMain);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
@@ -142,7 +109,7 @@ typedef struct
UInt32 NumFiles; UInt32 NumFiles;
UInt64 *UnpackPositions; UInt64 *UnpackPositions; // NumFiles + 1
// Byte *IsEmptyFiles; // Byte *IsEmptyFiles;
Byte *IsDirs; Byte *IsDirs;
CSzBitUi32s CRCs; CSzBitUi32s CRCs;
@@ -152,9 +119,8 @@ typedef struct
CSzBitUi64s MTime; CSzBitUi64s MTime;
CSzBitUi64s CTime; CSzBitUi64s CTime;
// UInt32 *FolderStartPackStreamIndex; UInt32 *FolderToFile; // NumFolders + 1
UInt32 *FolderStartFileIndex; // + 1 UInt32 *FileToFolder; // NumFiles
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */ size_t *FileNameOffsets; /* in 2-byte steps */
Byte *FileNames; /* UTF-16-LE */ Byte *FileNames; /* UTF-16-LE */
@@ -182,6 +148,28 @@ size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
*/ */
/*
SzArEx_Extract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzArEx_Extract( SRes SzArEx_Extract(
const CSzArEx *db, const CSzArEx *db,
ILookInStream *inStream, ILookInStream *inStream,

View File

@@ -1,5 +1,5 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2015-02-21 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -26,7 +26,7 @@ void *SzAlloc(void *p, size_t size)
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount);
g_allocCount++; g_allocCount++;
#endif #endif
return malloc(size); return malloc(size);
@@ -51,7 +51,7 @@ void *SzAllocTemp(void *p, size_t size)
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp);
g_allocCountTemp++; g_allocCountTemp++;
#ifdef _WIN32 #ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size); return HeapAlloc(GetProcessHeap(), 0, size);

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2015-08-01 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -8,6 +8,7 @@
/* #define _7ZIP_PPMD_SUPPPORT */ /* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h" #include "7z.h"
#include "7zCrc.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
@@ -160,14 +161,23 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.dicBufSize != outSize || lookahead != 0 || if (outSize != state.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
break;
if (inProcessed == 0 && dicPos == state.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -213,13 +223,20 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.decoder.dicBufSize != outSize || lookahead != 0 || if (outSize != state.decoder.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -537,33 +554,38 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
SRes res; SRes res;
CSzFolder folder; CSzFolder folder;
CSzData sd; CSzData sd;
CSzData sdSizes;
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
sd.Data = data; sd.Data = data;
sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; res = SzGetNextFolderItem(&folder, &sd);
sdSizes.Size =
p->FoSizesOffsets[folderIndex + 1] -
p->FoSizesOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd, &sdSizes);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.UnpackStream]) if (sd.Size != 0
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
{ {
unsigned i; unsigned i;
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
res = SzFolder_Decode2(&folder, data,
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
p->PackPositions + p->FoStartPackStreamIndex[folderIndex], p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
inStream, startPos, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); IAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
res = SZ_ERROR_CRC;
return res; return res;
} }
} }

View File

@@ -1,14 +1,14 @@
#define MY_VER_MAJOR 15 #define MY_VER_MAJOR 16
#define MY_VER_MINOR 06 #define MY_VER_MINOR 03
#define MY_VER_BUILD 00 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "15.06" #define MY_VERSION_NUMBERS "16.03"
#define MY_VERSION "15.06 beta" #define MY_VERSION "16.03"
#define MY_DATE "2015-08-09" #define MY_DATE "2016-09-28"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov" #define MY_COPYRIGHT_CR "Copyright (c) 1999-2016 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR #ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR

10
C/Aes.c
View File

@@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2015-02-23 : Igor Pavlov : Public domain */ 2016-05-21 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -167,10 +167,10 @@ void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
{ {
UInt32 r = w[i]; UInt32 r = w[i];
w[i] = w[i] =
D[ Sbox[gb0(r)]] ^ D[ (unsigned)Sbox[gb0(r)]] ^
D[0x100 + Sbox[gb1(r)]] ^ D[0x100 + (unsigned)Sbox[gb1(r)]] ^
D[0x200 + Sbox[gb2(r)]] ^ D[0x200 + (unsigned)Sbox[gb2(r)]] ^
D[0x300 + Sbox[gb3(r)]]; D[0x300 + (unsigned)Sbox[gb3(r)]];
} }
} }

View File

@@ -513,4 +513,3 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
#endif #endif
return Groups[0]; return Groups[0];
} }

View File

@@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2015-03-25: Igor Pavlov : Public domain */ 2016-02-25: Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -45,7 +45,8 @@ static UInt32 CheckFlag(UInt32 flag)
"push %%EDX\n\t" "push %%EDX\n\t"
"popf\n\t" "popf\n\t"
"andl %%EAX, %0\n\t": "andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag)); "=c" (flag) : "c" (flag) :
"%eax", "%edx");
#endif #endif
return flag; return flag;
} }
@@ -79,7 +80,13 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
#if defined(MY_CPU_X86) && defined(__PIC__) #if defined(MY_CPU_AMD64) && defined(__PIC__)
"mov %%rbx, %%rdi;"
"cpuid;"
"xchg %%rbx, %%rdi;"
: "=a" (*a) ,
"=D" (*b) ,
#elif defined(MY_CPU_X86) && defined(__PIC__)
"mov %%ebx, %%edi;" "mov %%ebx, %%edi;"
"cpuid;" "cpuid;"
"xchgl %%ebx, %%edi;" "xchgl %%ebx, %%edi;"

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2015-08-02: Igor Pavlov : Public domain */ 2016-06-09: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -10,14 +10,18 @@ EXTERN_C_BEGIN
/* /*
MY_CPU_LE means that CPU is LITTLE ENDIAN. MY_CPU_LE means that CPU is LITTLE ENDIAN.
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). MY_CPU_BE means that CPU is BIG ENDIAN.
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/ */
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) #if defined(_M_X64) \
#define MY_CPU_AMD64 || defined(_M_AMD64) \
|| defined(__x86_64__) \
|| defined(__AMD64__) \
|| defined(__amd64__)
#define MY_CPU_AMD64
#endif #endif
#if defined(MY_CPU_AMD64) \ #if defined(MY_CPU_AMD64) \
@@ -52,10 +56,6 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_IA64_LE #define MY_CPU_IA64_LE
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN
#endif
#if defined(MY_CPU_X86_OR_AMD64) \ #if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM_LE) \
|| defined(MY_CPU_IA64_LE) \ || defined(MY_CPU_IA64_LE) \
@@ -65,7 +65,9 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
|| defined(__AARCH64EL__) \ || defined(__AARCH64EL__) \
|| defined(__MIPSEL__) \ || defined(__MIPSEL__) \
|| defined(__MIPSEL) \ || defined(__MIPSEL) \
|| defined(_MIPSEL) || defined(_MIPSEL) \
|| defined(__BFIN__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#define MY_CPU_LE #define MY_CPU_LE
#endif #endif
@@ -76,7 +78,11 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
|| defined(__MIPSEB__) \ || defined(__MIPSEB__) \
|| defined(__MIPSEB) \ || defined(__MIPSEB) \
|| defined(_MIPSEB) \ || defined(_MIPSEB) \
|| defined(__m68k__) || defined(__m68k__) \
|| defined(__s390__) \
|| defined(__s390x__) \
|| defined(__zarch__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define MY_CPU_BE #define MY_CPU_BE
#endif #endif
@@ -85,6 +91,14 @@ Stop_Compiling_Bad_Endian
#endif #endif
#ifdef MY_CPU_LE
#if defined(MY_CPU_X86_OR_AMD64) \
/* || defined(__AARCH64EL__) */
#define MY_CPU_LE_UNALIGN
#endif
#endif
#ifdef MY_CPU_LE_UNALIGN #ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) #define GetUi16(p) (*(const UInt16 *)(const void *)(p))
@@ -128,6 +142,8 @@ Stop_Compiling_Bad_Endian
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
#include <stdlib.h> #include <stdlib.h>
#pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_ulong)
@@ -137,6 +153,13 @@ Stop_Compiling_Bad_Endian
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
#elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
#else #else
#define GetBe32(p) ( \ #define GetBe32(p) ( \

87
C/DllSecur.c Normal file
View File

@@ -0,0 +1,87 @@
/* DllSecur.c -- DLL loading security
2016-09-15 : Igor Pavlov : Public domain */
#include "Precomp.h"
#ifdef _WIN32
#include <windows.h>
#include "DllSecur.h"
#ifndef UNDER_CE
typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400
#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
static const char * const g_Dlls =
#ifndef _CONSOLE
"UXTHEME\0"
#endif
"USERENV\0"
"SETUPAPI\0"
"APPHELP\0"
"PROPSYS\0"
"DWMAPI\0"
"CRYPTBASE\0"
"OLEACC\0"
"CLBCATQ\0"
;
#endif
void LoadSecurityDlls()
{
#ifndef UNDER_CE
wchar_t buf[MAX_PATH + 100];
{
// at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMajorVersion != 0)
{
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
if (setDllDirs)
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
return;
}
}
{
unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2);
if (len == 0 || len > MAX_PATH)
return;
}
{
const char *dll;
unsigned pos = (unsigned)lstrlenW(buf);
if (buf[pos - 1] != '\\')
buf[pos++] = '\\';
for (dll = g_Dlls; dll[0] != 0;)
{
unsigned k = 0;
for (;;)
{
char c = *dll++;
buf[pos + k] = c;
k++;
if (c == 0)
break;
}
lstrcatW(buf, L".dll");
LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
#endif
}
#endif

19
C/DllSecur.h Normal file
View File

@@ -0,0 +1,19 @@
/* DllSecur.h -- DLL loading for security
2016-06-08 : Igor Pavlov : Public domain */
#ifndef __DLL_SECUR_H
#define __DLL_SECUR_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#ifdef _WIN32
void LoadSecurityDlls();
#endif
EXTERN_C_END
#endif

View File

@@ -1,5 +1,5 @@
/* HuffEnc.c -- functions for Huffman encoding /* HuffEnc.c -- functions for Huffman encoding
2009-09-02 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -121,8 +121,8 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
i = 0; i = 0;
for (len = maxLen; len != 0; len--) for (len = maxLen; len != 0; len--)
{ {
UInt32 num; UInt32 k;
for (num = lenCounters[len]; num != 0; num--) for (k = lenCounters[len]; k != 0; k--)
lens[p[i++] & MASK] = (Byte)len; lens[p[i++] & MASK] = (Byte)len;
} }
} }
@@ -138,9 +138,9 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
/* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
{ {
UInt32 i; UInt32 k;
for (i = 0; i < numSymbols; i++) for (k = 0; k < numSymbols; k++)
p[i] = nextCodes[lens[i]]++; p[k] = nextCodes[lens[k]]++;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2015-05-15 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -11,7 +11,7 @@
#define kEmptyHashValue 0 #define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)7 << 29) #define kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3 #define kStartMaxLen 3
@@ -60,9 +60,11 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
if (p->streamEndWasReached || p->result != SZ_OK) if (p->streamEndWasReached || p->result != SZ_OK)
return; return;
/* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
if (p->directInput) if (p->directInput)
{ {
UInt32 curSize = 0xFFFFFFFF - p->streamPos; UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
if (curSize > p->directInputRem) if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem; curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize; p->directInputRem -= curSize;
@@ -97,7 +99,7 @@ void MatchFinder_MoveBlock(CMatchFinder *p)
{ {
memmove(p->bufferBase, memmove(p->bufferBase,
p->buffer - p->keepSizeBefore, p->buffer - p->keepSizeBefore,
(size_t)(p->streamPos - p->pos + p->keepSizeBefore)); (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
p->buffer = p->bufferBase + p->keepSizeBefore; p->buffer = p->bufferBase + p->keepSizeBefore;
} }
@@ -290,7 +292,7 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit; p->posLimit = p->pos + limit;
} }
void MatchFinder_Init(CMatchFinder *p) void MatchFinder_Init_2(CMatchFinder *p, int readData)
{ {
UInt32 i; UInt32 i;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
@@ -303,10 +305,18 @@ void MatchFinder_Init(CMatchFinder *p)
p->pos = p->streamPos = p->cyclicBufferSize; p->pos = p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK; p->result = SZ_OK;
p->streamEndWasReached = 0; p->streamEndWasReached = 0;
MatchFinder_ReadBlock(p);
if (readData)
MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
void MatchFinder_Init(CMatchFinder *p)
{
MatchFinder_Init_2(p, True);
}
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{ {
return (p->pos - p->historySize - 1) & kNormalizeMask; return (p->pos - p->historySize - 1) & kNormalizeMask;

View File

@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2015-05-01 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H #ifndef __LZ_FIND_H
#define __LZ_FIND_H #define __LZ_FIND_H
@@ -53,6 +53,11 @@ typedef struct _CMatchFinder
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
#define Inline_MatchFinder_IsFinishedOK(p) \
((p)->streamEndWasReached \
&& (p)->streamPos == (p)->pos \
&& (!(p)->directInput || (p)->directInputRem == 0))
int MatchFinder_NeedMove(CMatchFinder *p); int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p);
@@ -98,9 +103,12 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init_2(CMatchFinder *p, int readData);
void MatchFinder_Init(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

View File

@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2015-05-03 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -173,12 +173,12 @@ static void HashThreadFunc(CMatchFinderMt *mt)
CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs); CriticalSection_Enter(&mt->hashSync.cs);
{ {
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
const Byte *afterPtr; ptrdiff_t offset;
MatchFinder_MoveBlock(mf); MatchFinder_MoveBlock(mf);
afterPtr = MatchFinder_GetPointerToCurrentPos(mf); offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
mt->pointerToCurPos -= beforePtr - afterPtr; mt->pointerToCurPos -= offset;
mt->buffer -= beforePtr - afterPtr; mt->buffer -= offset;
} }
CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs); CriticalSection_Leave(&mt->hashSync.cs);
@@ -501,8 +501,11 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0; p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0;
MatchFinder_Init(mf);
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); /* Init without data reading. We don't want to read data in this thread */
MatchFinder_Init_2(mf, False);
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0; p->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;

View File

@@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2014-10-29 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
@@ -103,8 +103,8 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{ {
case LZMA2_STATE_CONTROL: case LZMA2_STATE_CONTROL:
p->control = b; p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos)); PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
PRF(printf(" %2X", b)); PRF(printf(" %2X", (unsigned)b));
if (p->control == 0) if (p->control == 0)
return LZMA2_STATE_FINISHED; return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
@@ -124,7 +124,7 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_UNPACK1: case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b; p->unpackSize |= (UInt32)b;
p->unpackSize++; p->unpackSize++;
PRF(printf(" %8d", p->unpackSize)); PRF(printf(" %8u", (unsigned)p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0: case LZMA2_STATE_PACK0:
@@ -134,7 +134,7 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_PACK1: case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b; p->packSize |= (UInt32)b;
p->packSize++; p->packSize++;
PRF(printf(" %8d", p->packSize)); PRF(printf(" %8u", (unsigned)p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2012-06-19 : Igor Pavlov : Public domain */ 2015-10-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -109,6 +109,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
{ {
size_t destPos = 0; size_t destPos = 0;
PRF(printf("################# COPY ")); PRF(printf("################# COPY "));
while (unpackSize > 0) while (unpackSize > 0)
{ {
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
@@ -121,6 +122,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
unpackSize -= u; unpackSize -= u;
destPos += u; destPos += u;
p->srcPos += u; p->srcPos += u;
if (outStream) if (outStream)
{ {
*packSizeRes += destPos; *packSizeRes += destPos;
@@ -132,9 +134,11 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
*packSizeRes = destPos; *packSizeRes = destPos;
/* needInitState = True; */ /* needInitState = True; */
} }
LzmaEnc_RestoreState(p->enc); LzmaEnc_RestoreState(p->enc);
return SZ_OK; return SZ_OK;
} }
{ {
size_t destPos = 0; size_t destPos = 0;
UInt32 u = unpackSize - 1; UInt32 u = unpackSize - 1;
@@ -160,11 +164,13 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
if (outStream) if (outStream)
if (outStream->Write(outStream, outBuf, destPos) != destPos) if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
*packSizeRes = destPos; *packSizeRes = destPos;
return SZ_OK; return SZ_OK;
} }
} }
/* ---------- Lzma2 Props ---------- */ /* ---------- Lzma2 Props ---------- */
void Lzma2EncProps_Init(CLzma2EncProps *p) void Lzma2EncProps_Init(CLzma2EncProps *p)
@@ -221,6 +227,8 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
LzmaEncProps_Normalize(&p->lzmaProps); LzmaEncProps_Normalize(&p->lzmaProps);
t1 = p->lzmaProps.numThreads;
if (p->blockSize == 0) if (p->blockSize == 0)
{ {
UInt32 dictSize = p->lzmaProps.dictSize; UInt32 dictSize = p->lzmaProps.dictSize;
@@ -232,7 +240,8 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
if (blockSize < dictSize) blockSize = dictSize; if (blockSize < dictSize) blockSize = dictSize;
p->blockSize = (size_t)blockSize; p->blockSize = (size_t)blockSize;
} }
if (t2 > 1)
if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)
{ {
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
if (temp > p->lzmaProps.reduceSize) if (temp > p->lzmaProps.reduceSize)
@@ -241,19 +250,24 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
if (numBlocks < (unsigned)t2) if (numBlocks < (unsigned)t2)
{ {
t2 = (unsigned)numBlocks; t2 = (unsigned)numBlocks;
if (t2 == 0)
t2 = 1;
t3 = t1 * t2; t3 = t1 * t2;
} }
} }
} }
p->numBlockThreads = t2; p->numBlockThreads = t2;
p->numTotalThreads = t3; p->numTotalThreads = t3;
} }
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{ {
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
} }
/* ---------- Lzma2 ---------- */ /* ---------- Lzma2 ---------- */
typedef struct typedef struct
@@ -283,15 +297,17 @@ static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
UInt64 packTotal = 0; UInt64 packTotal = 0;
SRes res = SZ_OK; SRes res = SZ_OK;
if (mainEncoder->outBuf == 0) if (!mainEncoder->outBuf)
{ {
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (mainEncoder->outBuf == 0) if (!mainEncoder->outBuf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE, RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig)); mainEncoder->alloc, mainEncoder->allocBig));
for (;;) for (;;)
{ {
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
@@ -305,16 +321,20 @@ static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
if (packSize == 0) if (packSize == 0)
break; break;
} }
LzmaEnc_Finish(p->enc); LzmaEnc_Finish(p->enc);
if (res == SZ_OK) if (res == SZ_OK)
{ {
Byte b = 0; Byte b = 0;
if (outStream->Write(outStream, &b, 1) != 1) if (outStream->Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
} }
return res; return res;
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
typedef struct typedef struct
@@ -362,10 +382,12 @@ static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *des
break; break;
} }
} }
LzmaEnc_Finish(p->enc); LzmaEnc_Finish(p->enc);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
} }
if (finished) if (finished)
{ {
if (*destSize == destLim) if (*destSize == destLim)
@@ -378,12 +400,13 @@ static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *des
#endif #endif
/* ---------- Lzma2Enc ---------- */ /* ---------- Lzma2Enc ---------- */
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig) CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc)); CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
if (p == 0) if (!p)
return NULL; return NULL;
Lzma2EncProps_Init(&p->props); Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props); Lzma2EncProps_Normalize(&p->props);
@@ -395,6 +418,7 @@ CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->coders[i].enc = 0; p->coders[i].enc = 0;
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MtCoder_Construct(&p->mtCoder); MtCoder_Construct(&p->mtCoder);
#endif #endif
@@ -455,22 +479,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
for (i = 0; i < p->props.numBlockThreads; i++) for (i = 0; i < p->props.numBlockThreads; i++)
{ {
CLzma2EncInt *t = &p->coders[i]; CLzma2EncInt *t = &p->coders[(unsigned)i];
if (t->enc == NULL) if (!t->enc)
{ {
t->enc = LzmaEnc_Create(p->alloc); t->enc = LzmaEnc_Create(p->alloc);
if (t->enc == NULL) if (!t->enc)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
if (p->props.numBlockThreads <= 1) if (p->props.numBlockThreads > 1)
#endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
#ifndef _7ZIP_ST
{ {
CMtCallbackImp mtCallback; CMtCallbackImp mtCallback;
@@ -485,9 +504,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
p->mtCoder.blockSize = p->props.blockSize; p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
if (p->mtCoder.destBlockSize < p->props.blockSize)
{
p->mtCoder.destBlockSize = (size_t)0 - 1;
if (p->mtCoder.destBlockSize < p->props.blockSize)
return SZ_ERROR_FAIL;
}
p->mtCoder.numThreads = p->props.numBlockThreads; p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder); return MtCoder_Code(&p->mtCoder);
} }
#endif #endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
} }

View File

@@ -1,5 +1,7 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2009-08-14 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Lzma86.h" #include "Lzma86.h"
@@ -7,9 +9,6 @@
#include "Bra.h" #include "Bra.h"
#include "LzmaDec.h" #include "LzmaDec.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
{ {
unsigned i; unsigned i;
@@ -23,7 +22,6 @@ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes res; SRes res;
int useFilter; int useFilter;
SizeT inSizePure; SizeT inSizePure;

View File

@@ -1,5 +1,7 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2009-08-14 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h> #include <string.h>
@@ -11,13 +13,9 @@
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode) int level, UInt32 dictSize, int filterMode)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
size_t outSize2 = *destLen; size_t outSize2 = *destLen;
Byte *filteredStream; Byte *filteredStream;
Bool useFilter; Bool useFilter;

View File

@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder /* LzmaDec.c -- LZMA Decoder
2015-06-23 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -294,14 +294,14 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
#ifdef _LZMA_SIZE_OPT #ifdef _LZMA_SIZE_OPT
{ {
unsigned limit, offset; unsigned lim, offset;
CLzmaProb *probLen = prob + LenChoice; CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits); probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0; offset = 0;
limit = (1 << kLenNumLowBits); lim = (1 << kLenNumLowBits);
} }
else else
{ {
@@ -312,17 +312,17 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits); probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols; offset = kLenNumLowSymbols;
limit = (1 << kLenNumMidBits); lim = (1 << kLenNumMidBits);
} }
else else
{ {
UPDATE_1(probLen); UPDATE_1(probLen);
probLen = prob + LenHigh; probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols; offset = kLenNumLowSymbols + kLenNumMidSymbols;
limit = (1 << kLenNumHighBits); lim = (1 << kLenNumHighBits);
} }
} }
TREE_DECODE(probLen, limit, len); TREE_DECODE(probLen, lim, len);
len += offset; len += offset;
} }
#else #else

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2015-05-15 Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -108,7 +108,7 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
#define kDicLogSizeMaxCompress 32 #define kDicLogSizeMaxCompress 32
#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
static UInt32 GetPosSlot1(UInt32 pos) static UInt32 GetPosSlot1(UInt32 pos)
{ {
@@ -145,19 +145,19 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */ /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
/* /*
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ #define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
res = p->g_FastPos[pos >> i] + (i * 2); } res = p->g_FastPos[pos >> zz] + (zz * 2); }
*/ */
/* /*
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ #define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \ (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
res = p->g_FastPos[pos >> i] + (i * 2); } res = p->g_FastPos[pos >> zz] + (zz * 2); }
*/ */
#define BSR2_RET(pos, res) { UInt32 i = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \ #define BSR2_RET(pos, res) { UInt32 zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
res = p->g_FastPos[pos >> i] + (i * 2); } res = p->g_FastPos[pos >> zz] + (zz * 2); }
/* /*
#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
@@ -505,8 +505,8 @@ static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11,
static void RangeEnc_Construct(CRangeEnc *p) static void RangeEnc_Construct(CRangeEnc *p)
{ {
p->outStream = 0; p->outStream = NULL;
p->bufBase = 0; p->bufBase = NULL;
} }
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
@@ -514,10 +514,10 @@ static void RangeEnc_Construct(CRangeEnc *p)
#define RC_BUF_SIZE (1 << 16) #define RC_BUF_SIZE (1 << 16)
static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
{ {
if (p->bufBase == 0) if (!p->bufBase)
{ {
p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
if (p->bufBase == 0) if (!p->bufBase)
return 0; return 0;
p->bufLim = p->bufBase + RC_BUF_SIZE; p->bufLim = p->bufBase + RC_BUF_SIZE;
} }
@@ -854,7 +854,7 @@ static void MovePos(CLzmaEnc *p, UInt32 num)
{ {
#ifdef SHOW_STAT #ifdef SHOW_STAT
g_STAT_OFFSET += num; g_STAT_OFFSET += num;
printf("\n MovePos %d", num); printf("\n MovePos %u", num);
#endif #endif
if (num != 0) if (num != 0)
@@ -871,12 +871,12 @@ static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
#ifdef SHOW_STAT #ifdef SHOW_STAT
printf("\n i = %d numPairs = %d ", g_STAT_OFFSET, numPairs / 2); printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2);
g_STAT_OFFSET++; g_STAT_OFFSET++;
{ {
UInt32 i; UInt32 i;
for (i = 0; i < numPairs; i += 2) for (i = 0; i < numPairs; i += 2)
printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); printf("%2u %6u | ", p->matches[i], p->matches[i + 1]);
} }
#endif #endif
@@ -983,12 +983,17 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{ {
UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 lenEnd, cur;
UInt32 matchPrice, repMatchPrice, normalMatchPrice;
UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
UInt32 *matches; UInt32 *matches;
{
UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, len;
UInt32 matchPrice, repMatchPrice, normalMatchPrice;
const Byte *data; const Byte *data;
Byte curByte, matchByte; Byte curByte, matchByte;
if (p->optimumEndIndex != p->optimumCurrentIndex) if (p->optimumEndIndex != p->optimumCurrentIndex)
{ {
const COptimal *opt = &p->opt[p->optimumCurrentIndex]; const COptimal *opt = &p->opt[p->optimumCurrentIndex];
@@ -1167,17 +1172,20 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
cur = 0; cur = 0;
#ifdef SHOW_STAT2 #ifdef SHOW_STAT2
if (position >= 0) /* if (position >= 0) */
{ {
unsigned i; unsigned i;
printf("\n pos = %4X", position); printf("\n pos = %4X", position);
for (i = cur; i <= lenEnd; i++) for (i = cur; i <= lenEnd; i++)
printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
} }
#endif #endif
}
for (;;) for (;;)
{ {
UInt32 numAvail;
UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
Bool nextIsChar; Bool nextIsChar;
@@ -1397,13 +1405,13 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{ {
UInt32 lenTest2 = lenTest + 1; UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes; UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
if (limit > numAvailFull) if (limit > numAvailFull)
limit = numAvailFull; limit = numAvailFull;
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
lenTest2 -= lenTest + 1; lenTest2 -= lenTest + 1;
if (lenTest2 >= 2) if (lenTest2 >= 2)
{ {
UInt32 nextRepMatchPrice;
UInt32 state2 = kRepNextStates[state]; UInt32 state2 = kRepNextStates[state];
UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 posStateNext = (position + lenTest) & p->pbMask;
UInt32 curAndLenCharPrice = UInt32 curAndLenCharPrice =
@@ -1465,6 +1473,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
for (lenTest = /*2*/ startLen; ; lenTest++) for (lenTest = /*2*/ startLen; ; lenTest++)
{ {
UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
{
UInt32 lenToPosState = GetLenToPosState(lenTest); UInt32 lenToPosState = GetLenToPosState(lenTest);
COptimal *opt; COptimal *opt;
if (curBack < kNumFullDistances) if (curBack < kNumFullDistances)
@@ -1480,6 +1489,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
opt->backPrev = curBack + LZMA_NUM_REPS; opt->backPrev = curBack + LZMA_NUM_REPS;
opt->prev1IsChar = False; opt->prev1IsChar = False;
} }
}
if (/*_maxMode && */lenTest == matches[offs]) if (/*_maxMode && */lenTest == matches[offs])
{ {
@@ -1487,13 +1497,13 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
const Byte *data2 = data - curBack - 1; const Byte *data2 = data - curBack - 1;
UInt32 lenTest2 = lenTest + 1; UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes; UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
if (limit > numAvailFull) if (limit > numAvailFull)
limit = numAvailFull; limit = numAvailFull;
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
lenTest2 -= lenTest + 1; lenTest2 -= lenTest + 1;
if (lenTest2 >= 2) if (lenTest2 >= 2)
{ {
UInt32 nextRepMatchPrice;
UInt32 state2 = kMatchNextStates[state]; UInt32 state2 = kMatchNextStates[state];
UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 posStateNext = (position + lenTest) & p->pbMask;
UInt32 curAndLenCharPrice = curAndLenPrice + UInt32 curAndLenCharPrice = curAndLenPrice +
@@ -1509,15 +1519,15 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
/* for (; lenTest2 >= 2; lenTest2--) */ /* for (; lenTest2 >= 2; lenTest2--) */
{ {
UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 offset = cur + lenTest + 1 + lenTest2;
UInt32 curAndLenPrice; UInt32 curAndLenPrice2;
COptimal *opt; COptimal *opt;
while (lenEnd < offset) while (lenEnd < offset)
p->opt[++lenEnd].price = kInfinityPrice; p->opt[++lenEnd].price = kInfinityPrice;
curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); curAndLenPrice2 = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
opt = &p->opt[offset]; opt = &p->opt[offset];
if (curAndLenPrice < opt->price) if (curAndLenPrice2 < opt->price)
{ {
opt->price = curAndLenPrice; opt->price = curAndLenPrice2;
opt->posPrev = cur + lenTest + 1; opt->posPrev = cur + lenTest + 1;
opt->backPrev = 0; opt->backPrev = 0;
opt->prev1IsChar = True; opt->prev1IsChar = True;
@@ -1718,7 +1728,6 @@ static void FillDistancesPrices(CLzmaEnc *p)
{ {
UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
UInt32 i;
for (i = 0; i < kStartPosModelIndex; i++) for (i = 0; i < kStartPosModelIndex; i++)
distancesPrices[i] = posSlotPrices[i]; distancesPrices[i] = posSlotPrices[i];
for (; i < kNumFullDistances; i++) for (; i < kNumFullDistances; i++)
@@ -1749,15 +1758,15 @@ void LzmaEnc_Construct(CLzmaEnc *p)
#endif #endif
LzmaEnc_InitPriceTables(p->ProbPrices); LzmaEnc_InitPriceTables(p->ProbPrices);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
{ {
void *p; void *p;
p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
if (p != 0) if (p)
LzmaEnc_Construct((CLzmaEnc *)p); LzmaEnc_Construct((CLzmaEnc *)p);
return p; return p;
} }
@@ -1766,8 +1775,8 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->litProbs);
alloc->Free(alloc, p->saveState.litProbs); alloc->Free(alloc, p->saveState.litProbs);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
@@ -1829,7 +1838,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
len = GetOptimum(p, nowPos32, &pos); len = GetOptimum(p, nowPos32, &pos);
#ifdef SHOW_STAT2 #ifdef SHOW_STAT2
printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); printf("\n pos = %4X, len = %u pos = %u", nowPos32, len, pos);
#endif #endif
posState = nowPos32 & p->pbMask; posState = nowPos32 & p->pbMask;
@@ -1963,12 +1972,12 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
{ {
unsigned lclp = p->lc + p->lp; unsigned lclp = p->lc + p->lp;
if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
if (p->litProbs == 0 || p->saveState.litProbs == 0) if (!p->litProbs || !p->saveState.litProbs)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@@ -2140,6 +2149,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
#endif #endif
} }
typedef struct typedef struct
{ {
ISeqOutStream funcTable; ISeqOutStream funcTable;
@@ -2169,12 +2179,14 @@ UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
} }
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
{ {
const CLzmaEnc *p = (CLzmaEnc *)pp; const CLzmaEnc *p = (CLzmaEnc *)pp;
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
} }
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{ {
@@ -2209,6 +2221,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
return res; return res;
} }
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
@@ -2222,9 +2235,9 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
for (;;) for (;;)
{ {
res = LzmaEnc_CodeOneBlock(p, False, 0, 0); res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
if (res != SZ_OK || p->finished != 0) if (res != SZ_OK || p->finished)
break; break;
if (progress != 0) if (progress)
{ {
res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
if (res != SZ_OK) if (res != SZ_OK)
@@ -2234,10 +2247,19 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
} }
} }
} }
LzmaEnc_Finish(p); LzmaEnc_Finish(p);
/*
if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
res = SZ_ERROR_FAIL;
}
*/
return res; return res;
} }
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
ISzAlloc *alloc, ISzAlloc *allocBig) ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
@@ -2245,6 +2267,7 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
} }
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2272,6 +2295,7 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
return SZ_OK; return SZ_OK;
} }
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
@@ -2280,19 +2304,22 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
CSeqOutStreamBuf outStream; CSeqOutStreamBuf outStream;
LzmaEnc_SetInputBuf(p, src, srcLen);
outStream.funcTable.Write = MyWrite; outStream.funcTable.Write = MyWrite;
outStream.data = dest; outStream.data = dest;
outStream.rem = *destLen; outStream.rem = *destLen;
outStream.overflow = False; outStream.overflow = False;
p->writeEndMark = writeEndMark; p->writeEndMark = writeEndMark;
p->rc.outStream = &outStream.funcTable; p->rc.outStream = &outStream.funcTable;
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
if (res == SZ_OK) if (res == SZ_OK)
{
res = LzmaEnc_Encode2(p, progress); res = LzmaEnc_Encode2(p, progress);
if (res == SZ_OK && p->nowPos64 != srcLen)
res = SZ_ERROR_FAIL;
}
*destLen -= outStream.rem; *destLen -= outStream.rem;
if (outStream.overflow) if (outStream.overflow)
@@ -2300,13 +2327,14 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
return res; return res;
} }
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
SRes res; SRes res;
if (p == 0) if (!p)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = LzmaEnc_SetProps(p, props); res = LzmaEnc_SetProps(p, props);

View File

@@ -1,10 +1,8 @@
/* MtCoder.c -- Multi-thread Coder /* MtCoder.c -- Multi-thread Coder
2010-09-24 : Igor Pavlov : Public domain */ 2015-10-13 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h>
#include "MtCoder.h" #include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p) void LoopThread_Construct(CLoopThread *p)
@@ -120,7 +118,7 @@ void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
LoopThread_Construct(&p->thread); LoopThread_Construct(&p->thread);
} }
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
static void CMtThread_CloseEvents(CMtThread *p) static void CMtThread_CloseEvents(CMtThread *p)
{ {

View File

@@ -1,5 +1,5 @@
/* Ppmd.h -- PPMD codec common code /* Ppmd.h -- PPMD codec common code
2013-01-18 : Igor Pavlov : Public domain 2016-05-16 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H #ifndef __PPMD_H
@@ -77,8 +77,8 @@ typedef
CPpmd_Byte_Ref; CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \ #define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \ { unsigned z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }} p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
EXTERN_C_END EXTERN_C_END

View File

@@ -1,10 +1,10 @@
/* Ppmd7.c -- PPMdH codec /* Ppmd7.c -- PPMdH codec
2010-03-12 : Igor Pavlov : Public domain 2016-05-21 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <memory.h> #include <string.h>
#include "Ppmd7.h" #include "Ppmd7.h"
@@ -66,7 +66,7 @@ void Ppmd7_Construct(CPpmd7 *p)
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{ {
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step); do { p->Units2Indx[k++] = (Byte)i; } while (--step);
p->Indx2Units[i] = (Byte)k; p->Indx2Units[i] = (Byte)k;
} }
@@ -257,7 +257,7 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
#define MyMem12Cpy(dest, src, num) \ #define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{ {
@@ -639,10 +639,10 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
unsigned nonMasked = p->MinContext->NumStats - numMasked; unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256) if (p->MinContext->NumStats != 256)
{ {
see = p->See[p->NS2Indx[nonMasked - 1]] + see = p->See[(unsigned)p->NS2Indx[nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (numMasked > nonMasked) + 4 * (unsigned)(numMasked > nonMasked) +
p->HiBitsFlag; p->HiBitsFlag;
{ {
unsigned r = (see->Summ >> see->Shift); unsigned r = (see->Summ >> see->Shift);

View File

@@ -1,5 +1,5 @@
/* Ppmd7.h -- PPMdH compression codec /* Ppmd7.h -- PPMdH compression codec
2010-03-12 : Igor Pavlov : Public domain 2016-05-21 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation /* This code supports virtual RangeDecoder and includes the implementation
@@ -86,10 +86,10 @@ void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p); void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \ #define Ppmd7_GetBinSumm(p) \
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ &p->BinSumm[(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)] ((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);

View File

@@ -1,5 +1,5 @@
/* Ppmd7Enc.c -- PPMdH Encoder /* Ppmd7Enc.c -- PPMdH Encoder
2010-03-12 : Igor Pavlov : Public domain 2015-09-28 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -26,7 +26,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF; temp = 0xFF;
} }
while(--p->CacheSize != 0); while (--p->CacheSize != 0);
p->Cache = (Byte)((UInt32)p->Low >> 24); p->Cache = (Byte)((UInt32)p->Low >> 24);
} }
p->CacheSize++; p->CacheSize++;

View File

@@ -1,10 +1,10 @@
/* Ppmd8.c -- PPMdI codec /* Ppmd8.c -- PPMdI codec
2013-11-12 : Igor Pavlov : Public domain 2016-05-21 : Igor Pavlov : Public domain
This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <memory.h> #include <string.h>
#include "Ppmd8.h" #include "Ppmd8.h"
@@ -67,7 +67,7 @@ void Ppmd8_Construct(CPpmd8 *p)
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{ {
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step); do { p->Units2Indx[k++] = (Byte)i; } while (--step);
p->Indx2Units[i] = (Byte)k; p->Indx2Units[i] = (Byte)k;
} }
@@ -240,8 +240,8 @@ static void *AllocUnits(CPpmd8 *p, unsigned indx)
} }
#define MyMem12Cpy(dest, src, num) \ #define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU) static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{ {
@@ -772,7 +772,7 @@ static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
if (SUCCESSOR(s) <= upBranch) if (SUCCESSOR(s) <= upBranch)
{ {
CTX_PTR successor; CTX_PTR successor;
CPpmd_State *s1 = p->FoundState; CPpmd_State *s2 = p->FoundState;
p->FoundState = s; p->FoundState = s;
successor = CreateSuccessors(p, False, NULL, c); successor = CreateSuccessors(p, False, NULL, c);
@@ -780,7 +780,7 @@ static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
SetSuccessor(s, 0); SetSuccessor(s, 0);
else else
SetSuccessor(s, REF(successor)); SetSuccessor(s, REF(successor));
p->FoundState = s1; p->FoundState = s2;
} }
if (p->OrderFall == 1 && c1 == p->MaxContext) if (p->OrderFall == 1 && c1 == p->MaxContext)
@@ -924,19 +924,19 @@ static void UpdateModel(CPpmd8 *p)
} }
else else
{ {
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0);
if (!s) if (!s2)
{ {
RESTORE_MODEL(c, CTX(fSuccessor)); RESTORE_MODEL(c, CTX(fSuccessor));
return; return;
} }
*s = *ONE_STATE(c); *s2 = *ONE_STATE(c);
c->Stats = REF(s); c->Stats = REF(s2);
if (s->Freq < MAX_FREQ / 4 - 1) if (s2->Freq < MAX_FREQ / 4 - 1)
s->Freq <<= 1; s2->Freq <<= 1;
else else
s->Freq = MAX_FREQ - 4; s2->Freq = MAX_FREQ - 4;
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 2)); c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2));
} }
cf = 2 * fFreq * (c->SummFreq + 6); cf = 2 * fFreq * (c->SummFreq + 6);
sf = (UInt32)s0 + c->SummFreq; sf = (UInt32)s0 + c->SummFreq;
@@ -951,10 +951,10 @@ static void UpdateModel(CPpmd8 *p)
c->SummFreq = (UInt16)(c->SummFreq + cf); c->SummFreq = (UInt16)(c->SummFreq + cf);
} }
{ {
CPpmd_State *s = STATS(c) + ns1 + 1; CPpmd_State *s2 = STATS(c) + ns1 + 1;
SetSuccessor(s, successor); SetSuccessor(s2, successor);
s->Symbol = fSymbol; s2->Symbol = fSymbol;
s->Freq = (Byte)cf; s2->Freq = (Byte)cf;
c->Flags |= flag; c->Flags |= flag;
c->NumStats = (Byte)(ns1 + 1); c->NumStats = (Byte)(ns1 + 1);
} }
@@ -1038,9 +1038,9 @@ CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
CPpmd_See *see; CPpmd_See *see;
if (p->MinContext->NumStats != 0xFF) if (p->MinContext->NumStats != 0xFF)
{ {
see = p->See[p->NS2Indx[p->MinContext->NumStats + 2] - 3] + see = p->See[(unsigned)p->NS2Indx[(unsigned)p->MinContext->NumStats + 2] - 3] +
(p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) + (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +
2 * (2 * (unsigned)p->MinContext->NumStats < 2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats <
((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) + ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +
p->MinContext->Flags; p->MinContext->Flags;
{ {

View File

@@ -1,5 +1,5 @@
/* Sha1.c -- SHA-1 Hash /* Sha1.c -- SHA-1 Hash
2015-05-10 : Igor Pavlov : Public domain 2016-05-20 : Igor Pavlov : Public domain
This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
#include "Precomp.h" #include "Precomp.h"
@@ -151,18 +151,23 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
if (pos2 != 0) if (pos2 != 0)
{ {
UInt32 w = ((UInt32)data[0]) << 24; UInt32 w;
if (--size && pos2 < 3) pos2 = (3 - pos2) * 8;
w = ((UInt32)*data++) << pos2;
if (--size && pos2)
{ {
w |= ((UInt32)data[1]) << 16; pos2 -= 8;
if (--size && pos2 < 2) w |= ((UInt32)*data++) << pos2;
if (--size && pos2)
{ {
w |= ((UInt32)data[2]) << 8; pos2 -= 8;
--size; w |= ((UInt32)*data++) << pos2;
size--;
} }
} }
data += 4 - pos2; p->buffer[pos] |= w;
p->buffer[pos++] |= (w >> (8 * pos2)); if (pos2 == 0)
pos++;
} }
for (;;) for (;;)
@@ -207,7 +212,7 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
} }
} }
void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode) void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size /* , int rar350Mode */)
{ {
int returnRes = False; int returnRes = False;
@@ -241,7 +246,8 @@ void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode)
SetUi32(prev, d); SetUi32(prev, d);
} }
} }
returnRes = rar350Mode; // returnRes = rar350Mode;
returnRes = True;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* Sha1.h -- SHA-1 Hash /* Sha1.h -- SHA-1 Hash
2015-03-04 : Igor Pavlov : Public domain */ 2016-05-20 : Igor Pavlov : Public domain */
#ifndef __7Z_SHA1_H #ifndef __7Z_SHA1_H
#define __7Z_SHA1_H #define __7Z_SHA1_H
@@ -27,7 +27,7 @@ void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest);
void Sha1_Update(CSha1 *p, const Byte *data, size_t size); void Sha1_Update(CSha1 *p, const Byte *data, size_t size);
void Sha1_Final(CSha1 *p, Byte *digest); void Sha1_Final(CSha1 *p, Byte *digest);
void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode); void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size /* , int rar350Mode */);
void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size); void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size);
void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size); void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size);

View File

@@ -1,5 +1,5 @@
/* Crypto/Sha256.c -- SHA-256 Hash /* Crypto/Sha256.c -- SHA-256 Hash
2015-03-02 : Igor Pavlov : Public domain 2015-11-14 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */ This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h" #include "Precomp.h"
@@ -113,10 +113,26 @@ static void Sha256_WriteByteBlock(CSha256 *p)
{ {
UInt32 W[16]; UInt32 W[16];
unsigned j; unsigned j;
UInt32 *state = p->state; UInt32 *state;
#ifdef _SHA256_UNROLL2 #ifdef _SHA256_UNROLL2
UInt32 a,b,c,d,e,f,g,h; UInt32 a,b,c,d,e,f,g,h;
#else
UInt32 T[8];
#endif
for (j = 0; j < 16; j += 4)
{
const Byte *ccc = p->buffer + j * 4;
W[j ] = GetBe32(ccc);
W[j + 1] = GetBe32(ccc + 4);
W[j + 2] = GetBe32(ccc + 8);
W[j + 3] = GetBe32(ccc + 12);
}
state = p->state;
#ifdef _SHA256_UNROLL2
a = state[0]; a = state[0];
b = state[1]; b = state[1];
c = state[2]; c = state[2];
@@ -126,17 +142,10 @@ static void Sha256_WriteByteBlock(CSha256 *p)
g = state[6]; g = state[6];
h = state[7]; h = state[7];
#else #else
UInt32 T[8];
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
T[j] = state[j]; T[j] = state[j];
#endif #endif
for (j = 0; j < 16; j += 2)
{
W[j ] = GetBe32(p->buffer + j * 4);
W[j + 1] = GetBe32(p->buffer + j * 4 + 4);
}
for (j = 0; j < 64; j += 16) for (j = 0; j < 64; j += 16)
{ {
RX_16 RX_16
@@ -226,11 +235,13 @@ void Sha256_Final(CSha256 *p, Byte *digest)
Sha256_WriteByteBlock(p); Sha256_WriteByteBlock(p);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i += 2)
{ {
UInt32 v = p->state[i]; UInt32 v0 = p->state[i];
SetBe32(digest, v); UInt32 v1 = p->state[i + 1];
digest += 4; SetBe32(digest , v0);
SetBe32(digest + 4, v1);
digest += 8;
} }
Sha256_Init(p); Sha256_Init(p);

View File

@@ -1,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2015-08-02 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -310,10 +310,10 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
ms[1] = 29; ms[1] = 29;
for (mon = 0;; mon++) for (mon = 0;; mon++)
{ {
unsigned s = ms[mon]; unsigned d = ms[mon];
if (v < s) if (v < d)
break; break;
v -= s; v -= d;
} }
s = UIntToStr(s, year, 4); *s++ = '-'; s = UIntToStr(s, year, 4); *s++ = '-';
UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;

View File

@@ -73,4 +73,3 @@ Ppmd7Dec.o: ../../Ppmd7Dec.c
clean: clean:
-$(RM) $(PROG) $(OBJS) -$(RM) $(PROG) $(OBJS)

View File

@@ -1,5 +1,5 @@
/* 7zipInstall.c - 7-Zip Installer /* 7zipInstall.c - 7-Zip Installer
2015-08-04 : Igor Pavlov : Public domain */ 2016-06-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -21,6 +21,7 @@
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../7zVersion.h" #include "../../7zVersion.h"
#include "../../CpuArch.h" #include "../../CpuArch.h"
#include "../../DllSecur.h"
#include "resource.h" #include "resource.h"
@@ -261,7 +262,7 @@ static LONG MyRegistry_CreateKeyAndVal(HKEY parentKey, LPCWSTR keyName, LPCWSTR
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
res = MyRegistry_SetString(destKey, valName, val); res = MyRegistry_SetString(destKey, valName, val);
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
return res; return res;
} }
@@ -284,7 +285,7 @@ static LONG MyRegistry_CreateKeyAndVal_32(HKEY parentKey, LPCWSTR keyName, LPCWS
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
res = MyRegistry_SetString(destKey, valName, val); res = MyRegistry_SetString(destKey, valName, val);
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
return res; return res;
} }
@@ -322,7 +323,7 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
processed -= k7zStartHeaderSize; processed -= k7zStartHeaderSize;
for (pos = 0; pos <= processed; pos++) for (pos = 0; pos <= processed; pos++)
{ {
for (; buf[pos] != '7' && pos <= processed; pos++); for (; pos <= processed && buf[pos] != '7'; pos++);
if (pos > processed) if (pos > processed)
break; break;
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
@@ -571,6 +572,8 @@ static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
#endif #endif
break; break;
} }
default: return FALSE;
} }
break; break;
@@ -598,8 +601,8 @@ static LONG SetRegKey_Path2(HKEY parentKey)
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
res = MyRegistry_SetString(destKey, k_Reg_Path32, path); res = MyRegistry_SetString(destKey, k_Reg_Path32, path);
res = MyRegistry_SetString(destKey, k_Reg_Path, path); /* res = */ MyRegistry_SetString(destKey, k_Reg_Path, path);
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
return res; return res;
} }
@@ -718,10 +721,10 @@ static void WriteCLSID()
WCHAR destPath[MAX_PATH + 10]; WCHAR destPath[MAX_PATH + 10];
wcscpy(destPath, path); wcscpy(destPath, path);
wcscat(destPath, L"7-zip32.dll"); wcscat(destPath, L"7-zip32.dll");
res = MyRegistry_SetString(destKey, NULL, destPath); /* res = */ MyRegistry_SetString(destKey, NULL, destPath);
res = MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment"); /* res = */ MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment");
// DeleteRegValue(destKey, L"InprocServer32"); // DeleteRegValue(destKey, L"InprocServer32");
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
#endif #endif
@@ -737,10 +740,10 @@ static void WriteCLSID()
WCHAR destPath[MAX_PATH + 10]; WCHAR destPath[MAX_PATH + 10];
wcscpy(destPath, path); wcscpy(destPath, path);
wcscat(destPath, L"7-zip.dll"); wcscat(destPath, L"7-zip.dll");
res = MyRegistry_SetString(destKey, NULL, destPath); /* res = */ MyRegistry_SetString(destKey, NULL, destPath);
res = MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment"); /* res = */ MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment");
// DeleteRegValue(destKey, L"InprocServer32"); // DeleteRegValue(destKey, L"InprocServer32");
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
} }
@@ -874,6 +877,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
UNUSED_VAR(nCmdShow) UNUSED_VAR(nCmdShow)
#ifndef UNDER_CE #ifndef UNDER_CE
LoadSecurityDlls();
CoInitialize(NULL); CoInitialize(NULL);
#endif #endif
@@ -1011,7 +1015,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
BOOL bRet; BOOL bRet;
MSG msg; MSG msg;
while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0) // we need messages for all thread windows (including EDITTEXT window in dialog)
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{ {
if (bRet == -1) if (bRet == -1)
return retCode; return retCode;
@@ -1083,7 +1088,6 @@ static int Install()
WCHAR sfxPath[MAX_PATH + 2]; WCHAR sfxPath[MAX_PATH + 2];
Bool needReboot = False; Bool needReboot = False;
size_t pathLen;
allocImp.Alloc = SzAlloc; allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree; allocImp.Free = SzFree;
@@ -1116,6 +1120,7 @@ static int Install()
if (res == SZ_OK) if (res == SZ_OK)
{ {
size_t pathLen;
if (!g_SilentMode) if (!g_SilentMode)
{ {
GetDlgItemTextW(g_HWND, IDE_EXTRACT_PATH, path, MAX_PATH); GetDlgItemTextW(g_HWND, IDE_EXTRACT_PATH, path, MAX_PATH);
@@ -1161,9 +1166,9 @@ if (res == SZ_OK)
if (res == SZ_OK) if (res == SZ_OK)
{ {
UInt32 i; UInt32 i;
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if(!outBuf) */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if (!outBuf) */
Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */ Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */
size_t outBufSize = 0; /* it can have any value before first call, if(!outBuf) */ size_t outBufSize = 0; /* it can have any value before first call, if (!outBuf) */
g_TotalSize = 0; g_TotalSize = 0;

View File

@@ -191,6 +191,14 @@ SOURCE=..\..\Delta.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\DllSecur.c
# End Source File
# Begin Source File
SOURCE=..\..\DllSecur.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c SOURCE=..\..\Lzma2Dec.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -25,6 +25,7 @@ C_OBJS = \
$O\7zStream.obj \ $O\7zStream.obj \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\DllSecur.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
OBJS = \ OBJS = \

View File

@@ -1,6 +1,6 @@
#define IDD_INSTALL 100 #define IDD_INSTALL 100
#define IDT_EXTRACT_EXTRACT_TO 110 #define IDT_EXTRACT_EXTRACT_TO 110
#define IDE_EXTRACT_PATH 111 #define IDE_EXTRACT_PATH 111
#define IDB_EXTRACT_SET_PATH 112 #define IDB_EXTRACT_SET_PATH 112
#define IDT_CUR_FILE 113 #define IDT_CUR_FILE 113

View File

@@ -1,5 +1,5 @@
/* 7zipUninstall.c - 7-Zip Uninstaller /* 7zipUninstall.c - 7-Zip Uninstaller
2015-08-09 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -362,9 +362,11 @@ static void WriteCLSID()
{ {
if (AreEqual_Path_PrefixName(s, path, L"7-zip.dll")) if (AreEqual_Path_PrefixName(s, path, L"7-zip.dll"))
{ {
LONG res = MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc); {
if (res == ERROR_SUCCESS) LONG res = MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc);
MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip); if (res == ERROR_SUCCESS)
MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip);
}
{ {
unsigned i; unsigned i;
@@ -384,7 +386,7 @@ static void WriteCLSID()
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
RegDeleteValueW(destKey, k_7zip_CLSID); RegDeleteValueW(destKey, k_7zip_CLSID);
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
} }
} }
@@ -397,9 +399,11 @@ static void WriteCLSID()
{ {
if (AreEqual_Path_PrefixName(s, path, L"7-zip32.dll")) if (AreEqual_Path_PrefixName(s, path, L"7-zip32.dll"))
{ {
LONG res = MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc); {
if (res == ERROR_SUCCESS) LONG res = MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc);
MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip); if (res == ERROR_SUCCESS)
MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip);
}
{ {
unsigned i; unsigned i;
@@ -419,7 +423,7 @@ static void WriteCLSID()
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
RegDeleteValueW(destKey, k_7zip_CLSID); RegDeleteValueW(destKey, k_7zip_CLSID);
res = RegCloseKey(destKey); /* res = */ RegCloseKey(destKey);
} }
} }
} }
@@ -542,7 +546,7 @@ static BOOL RemoveDir()
#define k_Lang L"Lang" #define k_Lang L"Lang"
// NUM_LANG_TXT_FILES files are placed before en.ttt // NUM_LANG_TXT_FILES files are placed before en.ttt
#define NUM_LANG_TXT_FILES 86 #define NUM_LANG_TXT_FILES 87
#ifdef _64BIT_INSTALLER #ifdef _64BIT_INSTALLER
#define NUM_EXTRA_FILES_64BIT 1 #define NUM_EXTRA_FILES_64BIT 1
@@ -556,7 +560,7 @@ static const char *k_Names =
"af an ar ast az ba be bg bn br ca co cs cy da de el eo es et eu ext" "af an ar ast az ba be bg bn br ca co cs cy da de el eo es et eu ext"
" fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kk ko ku ku-ckb ky" " fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kk ko ku ku-ckb ky"
" lij lt lv mk mn mng mng2 mr ms nb ne nl nn pa-in pl ps pt pt-br ro ru" " lij lt lv mk mn mng mng2 mr ms nb ne nl nn pa-in pl ps pt pt-br ro ru"
" sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi zh-cn zh-tw" " sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi yo zh-cn zh-tw"
" en.ttt" " en.ttt"
" descript.ion" " descript.ion"
" History.txt" " History.txt"
@@ -771,6 +775,8 @@ static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
OnClose(); OnClose();
break; break;
} }
default: return FALSE;
} }
break; break;
@@ -1033,7 +1039,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
BOOL bRet; BOOL bRet;
MSG msg; MSG msg;
while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0) while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{ {
if (bRet == -1) if (bRet == -1)
return retCode; return retCode;

View File

@@ -1,6 +1,6 @@
#define IDD_INSTALL 100 #define IDD_INSTALL 100
#define IDT_EXTRACT_EXTRACT_TO 110 #define IDT_EXTRACT_EXTRACT_TO 110
#define IDE_EXTRACT_PATH 111 #define IDE_EXTRACT_PATH 111
#define IDT_CUR_FILE 113 #define IDT_CUR_FILE 113

View File

@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression /* LzmaUtil.c -- Test application for LZMA compression
2015-06-13 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "../../Precomp.h" #include "../../Precomp.h"
@@ -133,7 +133,7 @@ static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 file
SRes res; SRes res;
CLzmaEncProps props; CLzmaEncProps props;
rs = rs; UNUSED_VAR(rs);
enc = LzmaEnc_Create(&g_Alloc); enc = LzmaEnc_Create(&g_Alloc);
if (enc == 0) if (enc == 0)

View File

@@ -1,12 +1,14 @@
/* LzmaLibExports.c -- LZMA library DLL Entry point /* LzmaLibExports.c -- LZMA library DLL Entry point
2008-10-04 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "../../Precomp.h"
#include <windows.h> #include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{ {
hInstance = hInstance; UNUSED_VAR(hInstance);
dwReason = dwReason; UNUSED_VAR(dwReason);
lpReserved = lpReserved; UNUSED_VAR(lpReserved);
return TRUE; return TRUE;
} }

View File

@@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup /* SfxSetup.c - 7z SFX Setup
2015-03-25 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -20,6 +20,7 @@
#include "../../7zCrc.h" #include "../../7zCrc.h"
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../CpuArch.h" #include "../../CpuArch.h"
#include "../../DllSecur.h"
#define k_EXE_ExtIndex 2 #define k_EXE_ExtIndex 2
@@ -88,7 +89,7 @@ static unsigned FindItem(const char * const *items, unsigned num, const wchar_t
#ifdef _CONSOLE #ifdef _CONSOLE
static BOOL WINAPI HandlerRoutine(DWORD ctrlType) static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
{ {
ctrlType = ctrlType; UNUSED_VAR(ctrlType);
return TRUE; return TRUE;
} }
#endif #endif
@@ -144,7 +145,7 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
processed -= k7zStartHeaderSize; processed -= k7zStartHeaderSize;
for (pos = 0; pos <= processed; pos++) for (pos = 0; pos <= processed; pos++)
{ {
for (; buf[pos] != '7' && pos <= processed; pos++); for (; pos <= processed && buf[pos] != '7'; pos++);
if (pos > processed) if (pos > processed)
break; break;
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
@@ -254,13 +255,15 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
Bool useShellExecute = True; Bool useShellExecute = True;
DWORD exitCode = 0; DWORD exitCode = 0;
LoadSecurityDlls();
#ifdef _CONSOLE #ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleCtrlHandler(HandlerRoutine, TRUE);
#else #else
hInstance = hInstance; UNUSED_VAR(hInstance);
hPrevInstance = hPrevInstance; UNUSED_VAR(hPrevInstance);
lpCmdLine = lpCmdLine; UNUSED_VAR(lpCmdLine);
nCmdShow = nCmdShow; UNUSED_VAR(nCmdShow);
#endif #endif
CrcGenerateTable(); CrcGenerateTable();
@@ -396,11 +399,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{ {
size_t offset = 0; size_t offset = 0;
size_t outSizeProcessed = 0; size_t outSizeProcessed = 0;
size_t len;
WCHAR *temp; WCHAR *temp;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (len >= MAX_PATH) if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH)
{ {
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;

View File

@@ -187,6 +187,14 @@ SOURCE=..\..\Delta.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\DllSecur.c
# End Source File
# Begin Source File
SOURCE=..\..\DllSecur.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c SOURCE=..\..\Lzma2Dec.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -16,6 +16,7 @@ C_OBJS = \
$O\BraIA64.obj \ $O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \ $O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

View File

@@ -17,6 +17,7 @@ C_OBJS = \
$O\BraIA64.obj \ $O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \ $O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

View File

@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode /* XzDec.c -- Xz Decode
2015-05-01 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -74,7 +74,7 @@ static void BraState_Free(void *pp, ISzAlloc *alloc)
static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{ {
CBraState *p = ((CBraState *)pp); CBraState *p = ((CBraState *)pp);
alloc = alloc; UNUSED_VAR(alloc);
p->ip = 0; p->ip = 0;
if (p->methodId == XZ_ID_Delta) if (p->methodId == XZ_ID_Delta)
{ {
@@ -129,9 +129,9 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
CBraState *p = ((CBraState *)pp); CBraState *p = ((CBraState *)pp);
SizeT destLenOrig = *destLen; SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen; SizeT srcLenOrig = *srcLen;
UNUSED_VAR(finishMode);
*destLen = 0; *destLen = 0;
*srcLen = 0; *srcLen = 0;
finishMode = finishMode;
*wasFinished = 0; *wasFinished = 0;
while (destLenOrig > 0) while (destLenOrig > 0)
{ {
@@ -236,8 +236,8 @@ static void SbState_Free(void *pp, ISzAlloc *alloc)
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{ {
UNUSED_VAR(pp); UNUSED_VAR(pp);
props = props; UNUSED_VAR(props);
alloc = alloc; UNUSED_VAR(alloc);
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
} }
@@ -251,7 +251,7 @@ static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
{ {
CSbDec *p = (CSbDec *)pp; CSbDec *p = (CSbDec *)pp;
SRes res; SRes res;
srcWasFinished = srcWasFinished; UNUSED_VAR(srcWasFinished);
p->dest = dest; p->dest = dest;
p->destLen = *destLen; p->destLen = *destLen;
p->src = src; p->src = src;
@@ -308,7 +308,7 @@ static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *sr
ELzmaStatus status; ELzmaStatus status;
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status); SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);
srcWasFinished = srcWasFinished; UNUSED_VAR(srcWasFinished);
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
return res; return res;
} }
@@ -555,7 +555,7 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
pos += (unsigned)size; pos += (unsigned)size;
#ifdef XZ_DUMP #ifdef XZ_DUMP
printf("\nf[%d] = %2X: ", i, filter->id); printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
{ {
unsigned i; unsigned i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)

View File

@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode /* XzEnc.c -- Xz Encode
2015-05-01 : Igor Pavlov : Public domain */ 2015-09-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -10,6 +10,7 @@
#include "Alloc.h" #include "Alloc.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h" #include "CpuArch.h"
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
#include "Bcj3Enc.c" #include "Bcj3Enc.c"
#include "SbFind.c" #include "SbFind.c"
@@ -34,7 +35,7 @@ static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UIn
return WriteBytes(s, buf, size); return WriteBytes(s, buf, size);
} }
SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s) static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
{ {
UInt32 crc; UInt32 crc;
Byte header[XZ_STREAM_HEADER_SIZE]; Byte header[XZ_STREAM_HEADER_SIZE];
@@ -46,7 +47,8 @@ SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);
} }
SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
{ {
Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
@@ -75,7 +77,8 @@ SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
return WriteBytes(s, header, pos + 4); return WriteBytes(s, header, pos + 4);
} }
SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
static SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
{ {
Byte buf[32]; Byte buf[32];
UInt64 globalPos; UInt64 globalPos;
@@ -87,6 +90,7 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
globalPos = pos; globalPos = pos;
buf[0] = 0; buf[0] = 0;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
for (i = 0; i < p->numBlocks; i++) for (i = 0; i < p->numBlocks; i++)
{ {
const CXzBlockSizes *block = &p->blocks[i]; const CXzBlockSizes *block = &p->blocks[i];
@@ -95,7 +99,9 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
globalPos += pos; globalPos += pos;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
} }
pos = ((unsigned)globalPos & 3); pos = ((unsigned)globalPos & 3);
if (pos != 0) if (pos != 0)
{ {
buf[0] = buf[1] = buf[2] = 0; buf[0] = buf[1] = buf[2] = 0;
@@ -120,34 +126,36 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
} }
} }
SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
static SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
{ {
if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks) if (!p->blocks || p->numBlocksAllocated == p->numBlocks)
{ {
size_t num = (p->numBlocks + 1) * 2; size_t num = p->numBlocks * 2 + 1;
size_t newSize = sizeof(CXzBlockSizes) * num; size_t newSize = sizeof(CXzBlockSizes) * num;
CXzBlockSizes *blocks; CXzBlockSizes *blocks;
if (newSize / sizeof(CXzBlockSizes) != num) if (newSize / sizeof(CXzBlockSizes) != num)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize); blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize);
if (blocks == 0) if (!blocks)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
if (p->numBlocks != 0) if (p->numBlocks != 0)
{ {
memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes)); memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
Xz_Free(p, alloc); alloc->Free(alloc, p->blocks);
} }
p->blocks = blocks; p->blocks = blocks;
p->numBlocksAllocated = num; p->numBlocksAllocated = num;
} }
{ {
CXzBlockSizes *block = &p->blocks[p->numBlocks++]; CXzBlockSizes *block = &p->blocks[p->numBlocks++];
block->totalSize = totalSize;
block->unpackSize = unpackSize; block->unpackSize = unpackSize;
block->totalSize = totalSize;
} }
return SZ_OK; return SZ_OK;
} }
/* ---------- CSeqCheckInStream ---------- */ /* ---------- CSeqCheckInStream ---------- */
typedef struct typedef struct
@@ -178,6 +186,7 @@ static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
return res; return res;
} }
/* ---------- CSeqSizeOutStream ---------- */ /* ---------- CSeqSizeOutStream ---------- */
typedef struct typedef struct
@@ -195,6 +204,7 @@ static size_t MyWrite(void *pp, const void *data, size_t size)
return size; return size;
} }
/* ---------- CSeqInFilter ---------- */ /* ---------- CSeqInFilter ---------- */
#define FILTER_BUF_SIZE (1 << 20) #define FILTER_BUF_SIZE (1 << 20)
@@ -217,6 +227,7 @@ static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
if (sizeOriginal == 0) if (sizeOriginal == 0)
return SZ_OK; return SZ_OK;
*size = 0; *size = 0;
for (;;) for (;;)
{ {
if (!p->srcWasFinished && p->curPos == p->endPos) if (!p->srcWasFinished && p->curPos == p->endPos)
@@ -274,6 +285,7 @@ static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
return SZ_OK; return SZ_OK;
} }
/* ---------- CSbEncInStream ---------- */ /* ---------- CSbEncInStream ---------- */
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
@@ -291,6 +303,7 @@ static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
size_t sizeOriginal = *size; size_t sizeOriginal = *size;
if (sizeOriginal == 0) if (sizeOriginal == 0)
return S_OK; return S_OK;
for (;;) for (;;)
{ {
if (p->enc.needRead && !p->enc.readWasFinished) if (p->enc.needRead && !p->enc.readWasFinished)
@@ -305,6 +318,7 @@ static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
} }
p->enc.needRead = False; p->enc.needRead = False;
} }
*size = sizeOriginal; *size = sizeOriginal;
RINOK(SbEnc_Read(&p->enc, data, size)); RINOK(SbEnc_Read(&p->enc, data, size));
if (*size != 0 || !p->enc.needRead) if (*size != 0 || !p->enc.needRead)
@@ -357,7 +371,7 @@ static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, IS
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
{ {
p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc); p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
if (p->lzma2 == 0) if (!p->lzma2)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
return SZ_OK; return SZ_OK;
} }
@@ -375,10 +389,11 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
} }
} }
void XzProps_Init(CXzProps *p) void XzProps_Init(CXzProps *p)
{ {
p->lzma2Props = 0; p->lzma2Props = NULL;
p->filterProps = 0; p->filterProps = NULL;
p->checkId = XZ_CHECK_CRC32; p->checkId = XZ_CHECK_CRC32;
} }
@@ -386,10 +401,11 @@ void XzFilterProps_Init(CXzFilterProps *p)
{ {
p->id = 0; p->id = 0;
p->delta = 0; p->delta = 0;
p->ip= 0; p->ip = 0;
p->ipDefined = False; p->ipDefined = False;
} }
static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
ISeqOutStream *outStream, ISeqInStream *inStream, ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress) const CXzProps *props, ICompressProgress *progress)
@@ -415,6 +431,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
filter = &block.filters[filterIndex++]; filter = &block.filters[filterIndex++];
filter->id = fp->id; filter->id = fp->id;
filter->propsSize = 0; filter->propsSize = 0;
if (fp->id == XZ_ID_Delta) if (fp->id == XZ_ID_Delta)
{ {
filter->props[0] = (Byte)(fp->delta - 1); filter->props[0] = (Byte)(fp->delta - 1);
@@ -462,14 +479,16 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
{ {
UInt64 packPos = seqSizeOutStream.processed; UInt64 packPos = seqSizeOutStream.processed;
SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
fp ? fp ?
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
(fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:
#endif #endif
&lzmaf->filter.p: &lzmaf->filter.p:
&checkInStream.p, &checkInStream.p,
progress); progress);
RINOK(res); RINOK(res);
block.unpackSize = checkInStream.processed; block.unpackSize = checkInStream.processed;
block.packSize = seqSizeOutStream.processed - packPos; block.packSize = seqSizeOutStream.processed - packPos;
@@ -478,7 +497,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
{ {
unsigned padSize = 0; unsigned padSize = 0;
Byte buf[128]; Byte buf[128];
while((((unsigned)block.packSize + padSize) & 3) != 0) while ((((unsigned)block.packSize + padSize) & 3) != 0)
buf[padSize++] = 0; buf[padSize++] = 0;
SeqCheckInStream_GetDigest(&checkInStream, buf + padSize); SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags))); RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
@@ -488,6 +507,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
return Xz_WriteFooter(xz, outStream); return Xz_WriteFooter(xz, outStream);
} }
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress) const CXzProps *props, ICompressProgress *progress)
{ {
@@ -504,6 +524,7 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
return res; return res;
} }
SRes Xz_EncodeEmpty(ISeqOutStream *outStream) SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
{ {
SRes res; SRes res;

View File

@@ -1,5 +1,5 @@
/* XzIn.c - Xz input /* XzIn.c - Xz input
2015-04-21 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -72,7 +72,7 @@ SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc) static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)
{ {
size_t i, numBlocks, pos = 1; size_t numBlocks, pos = 1;
UInt32 crc; UInt32 crc;
if (size < 5 || buf[0] != 0) if (size < 5 || buf[0] != 0)
@@ -94,6 +94,7 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
Xz_Free(p, alloc); Xz_Free(p, alloc);
if (numBlocks != 0) if (numBlocks != 0)
{ {
size_t i;
p->numBlocks = numBlocks; p->numBlocks = numBlocks;
p->numBlocksAllocated = numBlocks; p->numBlocksAllocated = numBlocks;
p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);

View File

@@ -158,14 +158,6 @@ SOURCE=.\7zFolderInStream.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\7zFolderOutStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderOutStream.h
# End Source File
# Begin Source File
SOURCE=.\7zHandler.cpp SOURCE=.\7zHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -350,14 +342,6 @@ SOURCE=..\Common\CoderMixer2.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.h
# End Source File
# Begin Source File
SOURCE=..\Common\HandlerOut.cpp SOURCE=..\Common\HandlerOut.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -404,11 +404,11 @@ HRESULT CDecoder::Decode(
len = password.Len(); len = password.Len();
} }
CByteBuffer buffer(len * 2); CByteBuffer buffer(len * 2);
for (size_t i = 0; i < len; i++) for (size_t k = 0; k < len; k++)
{ {
wchar_t c = passwordBSTR[i]; wchar_t c = passwordBSTR[k];
((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[k * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
} }
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
} }

View File

@@ -148,9 +148,9 @@ HRESULT CEncoder::CreateMixerCoder(
RINOK(_mixer->SetBindInfo(_bindInfo)); RINOK(_mixer->SetBindInfo(_bindInfo));
FOR_VECTOR (i, _options.Methods) FOR_VECTOR (m, _options.Methods)
{ {
const CMethodFull &methodFull = _options.Methods[i]; const CMethodFull &methodFull = _options.Methods[m];
CCreatedCoder cod; CCreatedCoder cod;
@@ -410,9 +410,9 @@ HRESULT CEncoder::Encode(
mtOutStreamNotifySpec->_stream = outStream; mtOutStreamNotifySpec->_stream = outStream;
mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec; mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
FOR_VECTOR(i, tempBufferSpecs) FOR_VECTOR(t, tempBufferSpecs)
{ {
tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec; tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;
} }
} }
@@ -591,9 +591,9 @@ HRESULT CEncoder::EncoderConstr()
continue; continue;
} }
int i = _bindInfo.FindStream_in_PackStreams(outIndex); int si = _bindInfo.FindStream_in_PackStreams(outIndex);
if (i >= 0) if (si >= 0)
_bindInfo.PackStreams.MoveToFront(i); _bindInfo.PackStreams.MoveToFront(si);
break; break;
} }
} }

View File

@@ -254,8 +254,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
CDecoder decoder( CDecoder decoder(
#ifndef USE_MIXER_ST #if !defined(USE_MIXER_MT)
false false
#elif !defined(USE_MIXER_ST)
true
#elif !defined(__7Z_SET_PROPERTIES)
#ifdef _7ZIP_ST
false
#else
true
#endif
#else #else
_useMultiThreadMixer _useMultiThreadMixer
#endif #endif
@@ -311,13 +319,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
curUnpacked += _db.Files[k].Size; curUnpacked += _db.Files[k].Size;
} }
HRESULT result = folderOutStream->Init(fileIndex, {
allFilesMode ? NULL : indices + i, HRESULT result = folderOutStream->Init(fileIndex,
numSolidFiles); allFilesMode ? NULL : indices + i,
numSolidFiles);
i += numSolidFiles; i += numSolidFiles;
RINOK(result); RINOK(result);
}
// to test solid block with zero unpacked size we disable that code // to test solid block with zero unpacked size we disable that code
if (folderOutStream->WasWritingFinished()) if (folderOutStream->WasWritingFinished())

View File

@@ -1,3 +0,0 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"

View File

@@ -1,6 +0,0 @@
// 7zFolderOutStream.h
#ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H
#endif

View File

@@ -36,10 +36,14 @@ CHandler::CHandler()
#endif #endif
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
_crcSize = 4; _crcSize = 4;
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
_numThreads = NSystem::GetNumberOfProcessors(); _numThreads = NSystem::GetNumberOfProcessors();
_useMultiThreadMixer = true;
#endif #endif
#endif #endif
} }
@@ -425,11 +429,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
name = "LZMA2"; name = "LZMA2";
if (propsSize == 1) if (propsSize == 1)
{ {
Byte p = props[0]; Byte d = props[0];
if ((p & 1) == 0) if ((d & 1) == 0)
ConvertUInt32ToString((UInt32)((p >> 1) + 12), s); ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
else else
GetStringForSizeValue(s, 3 << ((p >> 1) + 11)); GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
} }
} }
else if (id == k_PPMD) else if (id == k_PPMD)
@@ -722,10 +726,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
return E_INVALIDARG; return E_INVALIDARG;
const PROPVARIANT &value = values[i]; const PROPVARIANT &value = values[i];
UInt32 number; UInt32 number;
int index = ParseStringToUInt32(name, number); unsigned index = ParseStringToUInt32(name, number);
if (index == 0) if (index == 0)
{ {
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); if (name.IsEqualTo("mtf"))
{
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
continue;
}
if (name.IsPrefixedBy_Ascii_NoCase("mt")) if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{ {
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));

View File

@@ -21,11 +21,11 @@ namespace N7z {
#ifndef __7Z_SET_PROPERTIES #ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
#if !defined(_7ZIP_ST) && !defined(_SFX) #if !defined(_7ZIP_ST) && !defined(_SFX)
#define __7Z_SET_PROPERTIES #define __7Z_SET_PROPERTIES
#endif #endif
#else #else
#define __7Z_SET_PROPERTIES #define __7Z_SET_PROPERTIES
#endif #endif
#endif #endif

View File

@@ -282,7 +282,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool need_CTime = (Write_CTime.Def && Write_CTime.Val); bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val); bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
if (db)
if (db && !db->Files.IsEmpty())
{ {
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
@@ -674,14 +675,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream) static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{ {
stream = 0; stream = 0;
int index = ParseStringToUInt32(srcString, coder); {
if (index == 0) unsigned index = ParseStringToUInt32(srcString, coder);
return E_INVALIDARG; if (index == 0)
srcString.DeleteFrontal(index); return E_INVALIDARG;
srcString.DeleteFrontal(index);
}
if (srcString[0] == 's') if (srcString[0] == 's')
{ {
srcString.Delete(0); srcString.Delete(0);
int index = ParseStringToUInt32(srcString, stream); unsigned index = ParseStringToUInt32(srcString, stream);
if (index == 0) if (index == 0)
return E_INVALIDARG; return E_INVALIDARG;
srcString.DeleteFrontal(index); srcString.DeleteFrontal(index);

View File

@@ -93,6 +93,8 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d
Byte external = archive->ReadByte(); Byte external = archive->ReadByte();
if (external != 0) if (external != 0)
{ {
if (!dataVector)
ThrowIncorrect();
CNum dataIndex = archive->ReadNum(); CNum dataIndex = archive->ReadNum();
if (dataIndex >= dataVector->Size()) if (dataIndex >= dataVector->Size())
ThrowIncorrect(); ThrowIncorrect();
@@ -761,6 +763,8 @@ void CInArchive::ReadUnpackInfo(
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
numCodersOutStreams += numCoders; numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoStartPackStreamIndex[fo] = packStreamIndex;
if (numPackStreams > folders.NumPackStreams - packStreamIndex)
ThrowIncorrect();
packStreamIndex += numPackStreams; packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
} }
@@ -770,6 +774,8 @@ void CInArchive::ReadUnpackInfo(
folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoStartPackStreamIndex[fo] = packStreamIndex;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
folders.CodersData.CopyFrom(startBufPtr, dataSize); folders.CodersData.CopyFrom(startBufPtr, dataSize);
// if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
} }
WaitId(NID::kCodersUnpackSize); WaitId(NID::kCodersUnpackSize);
@@ -1091,7 +1097,10 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
ThrowIncorrect(); ThrowIncorrect();
} }
HeadersSize += folders.PackPositions[folders.NumPackStreams];
if (folders.PackPositions)
HeadersSize += folders.PackPositions[folders.NumPackStreams];
return S_OK; return S_OK;
} }
@@ -1144,9 +1153,8 @@ HRESULT CInArchive::ReadHeader(
if (type == NID::kFilesInfo) if (type == NID::kFilesInfo)
{ {
CNum numFiles = ReadNum(); const CNum numFiles = ReadNum();
db.Files.ClearAndSetSize(numFiles); db.Files.ClearAndSetSize(numFiles);
CNum i;
/* /*
db.Files.Reserve(numFiles); db.Files.Reserve(numFiles);
CNum i; CNum i;
@@ -1168,8 +1176,8 @@ HRESULT CInArchive::ReadHeader(
for (;;) for (;;)
{ {
UInt64 type = ReadID(); const UInt64 type2 = ReadID();
if (type == NID::kEnd) if (type2 == NID::kEnd)
break; break;
UInt64 size = ReadNumber(); UInt64 size = ReadNumber();
if (size > _inByteBack->GetRem()) if (size > _inByteBack->GetRem())
@@ -1178,9 +1186,9 @@ HRESULT CInArchive::ReadHeader(
switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
bool addPropIdToList = true; bool addPropIdToList = true;
bool isKnownType = true; bool isKnownType = true;
if (type > ((UInt32)1 << 30)) if (type2 > ((UInt32)1 << 30))
isKnownType = false; isKnownType = false;
else switch((UInt32)type) else switch ((UInt32)type2)
{ {
case NID::kName: case NID::kName:
{ {
@@ -1214,7 +1222,7 @@ HRESULT CInArchive::ReadHeader(
ReadBoolVector2(db.Files.Size(), boolVector); ReadBoolVector2(db.Files.Size(), boolVector);
CStreamSwitch streamSwitch; CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector); streamSwitch.Set(this, &dataVector);
for (i = 0; i < numFiles; i++) for (CNum i = 0; i < numFiles; i++)
{ {
CFileItem &file = db.Files[i]; CFileItem &file = db.Files[i];
file.AttribDefined = boolVector[i]; file.AttribDefined = boolVector[i];
@@ -1257,7 +1265,7 @@ HRESULT CInArchive::ReadHeader(
{ {
ReadBoolVector(numFiles, emptyStreamVector); ReadBoolVector(numFiles, emptyStreamVector);
numEmptyStreams = 0; numEmptyStreams = 0;
for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)
if (emptyStreamVector[i]) if (emptyStreamVector[i])
numEmptyStreams++; numEmptyStreams++;
@@ -1331,14 +1339,14 @@ HRESULT CInArchive::ReadHeader(
if (isKnownType) if (isKnownType)
{ {
if (addPropIdToList) if (addPropIdToList)
db.ArcInfo.FileInfoPopIDs.Add(type); db.ArcInfo.FileInfoPopIDs.Add(type2);
} }
else else
{ {
db.UnsupportedFeatureWarning = true; db.UnsupportedFeatureWarning = true;
_inByteBack->SkipRem(); _inByteBack->SkipRem();
} }
// SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
if (_inByteBack->GetRem() != 0) if (_inByteBack->GetRem() != 0)
ThrowIncorrect(); ThrowIncorrect();
} }
@@ -1352,6 +1360,9 @@ HRESULT CInArchive::ReadHeader(
CNum sizeIndex = 0; CNum sizeIndex = 0;
CNum numAntiItems = 0; CNum numAntiItems = 0;
CNum i;
for (i = 0; i < numEmptyStreams; i++) for (i = 0; i < numEmptyStreams; i++)
if (antiFileVector[i]) if (antiFileVector[i])
numAntiItems++; numAntiItems++;

View File

@@ -87,6 +87,8 @@ struct CFolders
return PackPositions[index + 1] - PackPositions[index]; return PackPositions[index + 1] - PackPositions[index];
} }
CFolders(): NumPackStreams(0), NumFolders(0) {}
void Clear() void Clear()
{ {
NumPackStreams = 0; NumPackStreams = 0;

View File

@@ -540,13 +540,13 @@ void COutArchive::WriteHeader(
*/ */
_useAlign = true; _useAlign = true;
unsigned i; {
UInt64 packSize = 0;
FOR_VECTOR (i, db.PackSizes)
packSize += db.PackSizes[i];
headerOffset = packSize;
}
UInt64 packedSize = 0;
for (i = 0; i < db.PackSizes.Size(); i++)
packedSize += db.PackSizes[i];
headerOffset = packedSize;
WriteByte(NID::kHeader); WriteByte(NID::kHeader);
@@ -560,7 +560,7 @@ void COutArchive::WriteHeader(
CRecordVector<UInt64> unpackSizes; CRecordVector<UInt64> unpackSizes;
CUInt32DefVector digests; CUInt32DefVector digests;
for (i = 0; i < db.Files.Size(); i++) FOR_VECTOR (i, db.Files)
{ {
const CFileItem &file = db.Files[i]; const CFileItem &file = db.Files[i];
if (!file.HasStream) if (!file.HasStream)
@@ -588,14 +588,17 @@ void COutArchive::WriteHeader(
CBoolVector emptyStreamVector; CBoolVector emptyStreamVector;
emptyStreamVector.ClearAndSetSize(db.Files.Size()); emptyStreamVector.ClearAndSetSize(db.Files.Size());
unsigned numEmptyStreams = 0; unsigned numEmptyStreams = 0;
for (i = 0; i < db.Files.Size(); i++) {
if (db.Files[i].HasStream) FOR_VECTOR (i, db.Files)
emptyStreamVector[i] = false; if (db.Files[i].HasStream)
else emptyStreamVector[i] = false;
{ else
emptyStreamVector[i] = true; {
numEmptyStreams++; emptyStreamVector[i] = true;
} numEmptyStreams++;
}
}
if (numEmptyStreams != 0) if (numEmptyStreams != 0)
{ {
WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
@@ -605,7 +608,8 @@ void COutArchive::WriteHeader(
antiVector.ClearAndSetSize(numEmptyStreams); antiVector.ClearAndSetSize(numEmptyStreams);
bool thereAreEmptyFiles = false, thereAreAntiItems = false; bool thereAreEmptyFiles = false, thereAreAntiItems = false;
unsigned cur = 0; unsigned cur = 0;
for (i = 0; i < db.Files.Size(); i++)
FOR_VECTOR (i, db.Files)
{ {
const CFileItem &file = db.Files[i]; const CFileItem &file = db.Files[i];
if (file.HasStream) if (file.HasStream)
@@ -672,17 +676,21 @@ void COutArchive::WriteHeader(
CBoolVector boolVector; CBoolVector boolVector;
boolVector.ClearAndSetSize(db.Files.Size()); boolVector.ClearAndSetSize(db.Files.Size());
unsigned numDefined = 0; unsigned numDefined = 0;
for (i = 0; i < db.Files.Size(); i++)
{ {
bool defined = db.Files[i].AttribDefined; FOR_VECTOR (i, db.Files)
boolVector[i] = defined; {
if (defined) bool defined = db.Files[i].AttribDefined;
numDefined++; boolVector[i] = defined;
if (defined)
numDefined++;
}
} }
if (numDefined != 0) if (numDefined != 0)
{ {
WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4); WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
for (i = 0; i < db.Files.Size(); i++) FOR_VECTOR (i, db.Files)
{ {
const CFileItem &file = db.Files[i]; const CFileItem &file = db.Files[i];
if (file.AttribDefined) if (file.AttribDefined)

View File

@@ -14,7 +14,7 @@ namespace N7z {
struct CPropMap struct CPropMap
{ {
UInt32 FilePropID; UInt32 FilePropID;
STATPROPSTG StatPROPSTG; CStatProp StatProp;
}; };
static const CPropMap kPropMap[] = static const CPropMap kPropMap[] =
@@ -24,11 +24,11 @@ static const CPropMap kPropMap[] =
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } }, { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
#ifdef _MULTI_PACK #ifdef _MULTI_PACK
{ 100, { L"Pack0", kpidPackedSize0, VT_UI8 } }, { 100, { "Pack0", kpidPackedSize0, VT_UI8 } },
{ 101, { L"Pack1", kpidPackedSize1, VT_UI8 } }, { 101, { "Pack1", kpidPackedSize1, VT_UI8 } },
{ 102, { L"Pack2", kpidPackedSize2, VT_UI8 } }, { 102, { "Pack2", kpidPackedSize2, VT_UI8 } },
{ 103, { L"Pack3", kpidPackedSize3, VT_UI8 } }, { 103, { "Pack3", kpidPackedSize3, VT_UI8 } },
{ 104, { L"Pack4", kpidPackedSize4, VT_UI8 } }, { 104, { "Pack4", kpidPackedSize4, VT_UI8 } },
#endif #endif
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } }, { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
@@ -90,7 +90,7 @@ void CHandler::FillPopIDs()
_fileInfoPopIDs.Clear(); _fileInfoPopIDs.Clear();
#ifdef _7Z_VOL #ifdef _7Z_VOL
if(_volumes.Size() < 1) if (_volumes.Size() < 1)
return; return;
const CVolume &volume = _volumes.Front(); const CVolume &volume = _volumes.Front();
const CArchiveDatabaseEx &_db = volume.Database; const CArchiveDatabaseEx &_db = volume.Database;
@@ -156,8 +156,8 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID,
const CPropMap &pr = kPropMap[i]; const CPropMap &pr = kPropMap[i];
if (pr.FilePropID == id) if (pr.FilePropID == id)
{ {
const STATPROPSTG &st = pr.StatPROPSTG; const CStatProp &st = pr.StatProp;
*propID = st.propid; *propID = st.PropID;
*varType = st.vt; *varType = st.vt;
/* /*
if (st.lpwstrName) if (st.lpwstrName)

View File

@@ -38,7 +38,7 @@ struct CFilterMode
{ {
if (Id == k_IA64) if (Id == k_IA64)
Delta = 16; Delta = 16;
else if (Id == k_ARM || Id == k_PPC || Id == k_PPC) else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC)
Delta = 4; Delta = 4;
else if (Id == k_ARMT) else if (Id == k_ARMT)
Delta = 2; Delta = 2;
@@ -118,11 +118,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
#define ELF_SIG 0x464C457F #define ELF_SIG 0x464C457F
#define ELF_CLASS_32 1 #define ELF_CLASS_32 1
#define ELF_CLASS_64 2 #define ELF_CLASS_64 2
#define ELF_DATA_2LSB 1 #define ELF_DATA_2LSB 1
#define ELF_DATA_2MSB 2 #define ELF_DATA_2MSB 2
static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); } static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }
@@ -380,29 +380,33 @@ static inline bool IsExeFilter(CMethodId m)
return false; return false;
} }
static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f) static unsigned Get_FilterGroup_for_Folder(
CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)
{ {
CFilterMode2 m; CFilterMode2 m;
m.Id = 0; m.Id = 0;
m.Delta = 0; m.Delta = 0;
m.Encrypted = f.IsEncrypted(); m.Encrypted = f.IsEncrypted();
const CCoderInfo &coder = f.Coders[f.UnpackCoder]; if (extractFilter)
{
const CCoderInfo &coder = f.Coders[f.UnpackCoder];
if (coder.MethodID == k_Delta) if (coder.MethodID == k_Delta)
{
if (coder.Props.Size() == 1)
{ {
m.Delta = (unsigned)coder.Props[0] + 1; if (coder.Props.Size() == 1)
m.Id = k_Delta; {
m.Delta = (unsigned)coder.Props[0] + 1;
m.Id = k_Delta;
}
}
else if (IsExeFilter(coder.MethodID))
{
m.Id = (UInt32)coder.MethodID;
if (m.Id == k_BCJ2)
m.Id = k_BCJ;
m.SetDelta();
} }
}
else if (IsExeFilter(coder.MethodID))
{
m.Id = (UInt32)coder.MethodID;
if (m.Id == k_BCJ2)
m.Id = k_BCJ;
m.SetDelta();
} }
return GetGroup(filters, m); return GetGroup(filters, m);
@@ -567,14 +571,17 @@ static const char *g_Exts =
" iso bin nrg mdf img pdi tar cpio xpi" " iso bin nrg mdf img pdi tar cpio xpi"
" vfd vhd vud vmc vsv" " vfd vhd vud vmc vsv"
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
" inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " inl inc idl acf asa"
" h hpp hxx c cpp cxx m mm go swift"
" rc java cs rs pas bas vb cls ctl frm dlg def"
" f77 f f90 f95" " f77 f f90 f95"
" asm sql manifest dep" " asm s"
" sql manifest dep"
" mak clw csproj vcproj sln dsp dsw" " mak clw csproj vcproj sln dsp dsw"
" class" " class"
" bat cmd" " bat cmd bash sh"
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
" awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"
" text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
" sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
" abw afp cwk lwp wpd wps wpt wrf wri" " abw afp cwk lwp wpd wps wpt wrf wri"
@@ -772,7 +779,7 @@ struct CSolidGroup
CRecordVector<CFolderRepack> folderRefs; CRecordVector<CFolderRepack> folderRefs;
}; };
static const char *g_ExeExts[] = static const char * const g_ExeExts[] =
{ {
"dll" "dll"
, "exe" , "exe"
@@ -1574,7 +1581,7 @@ HRESULT Update(
return E_NOTIMPL; return E_NOTIMPL;
*/ */
UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0; UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0;
if (startBlockSize > 0 && !options.RemoveSfxBlock) if (startBlockSize > 0 && !options.RemoveSfxBlock)
{ {
RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
@@ -1589,7 +1596,20 @@ HRESULT Update(
CObjectVector<CSolidGroup> groups; CObjectVector<CSolidGroup> groups;
bool thereAreRepacks = false; bool thereAreRepacks = false;
if (db != 0) bool useFilters = options.UseFilters;
if (useFilters)
{
const CCompressionMethodMode &method = *options.Method;
FOR_VECTOR (i, method.Methods)
if (IsFilterMethod(method.Methods[i].Id))
{
useFilters = false;
break;
}
}
if (db)
{ {
fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
unsigned i; unsigned i;
@@ -1635,16 +1655,18 @@ HRESULT Update(
CFolderEx f; CFolderEx f;
db->ParseFolderEx(i, f); db->ParseFolderEx(i, f);
bool isEncrypted = f.IsEncrypted(); const bool isEncrypted = f.IsEncrypted();
const bool needCopy = (numCopyItems == numUnpackStreams);
const bool extractFilter = (useFilters || needCopy);
unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f); unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);
while (groupIndex >= groups.Size()) while (groupIndex >= groups.Size())
groups.AddNew(); groups.AddNew();
groups[groupIndex].folderRefs.Add(rep); groups[groupIndex].folderRefs.Add(rep);
if (numCopyItems == numUnpackStreams) if (needCopy)
complexity += db->GetFolderFullPackSize(i); complexity += db->GetFolderFullPackSize(i);
else else
{ {
@@ -1659,17 +1681,18 @@ HRESULT Update(
} }
UInt64 inSizeForReduce = 0; UInt64 inSizeForReduce = 0;
unsigned i;
for (i = 0; i < updateItems.Size(); i++)
{ {
const CUpdateItem &ui = updateItems[i]; FOR_VECTOR (i, updateItems)
if (ui.NewData)
{ {
complexity += ui.Size; const CUpdateItem &ui = updateItems[i];
if (numSolidFiles != 1) if (ui.NewData)
inSizeForReduce += ui.Size; {
else if (inSizeForReduce < ui.Size) complexity += ui.Size;
inSizeForReduce = ui.Size; if (numSolidFiles != 1)
inSizeForReduce += ui.Size;
else if (inSizeForReduce < ui.Size)
inSizeForReduce = ui.Size;
}
} }
} }
@@ -1729,23 +1752,9 @@ HRESULT Update(
// ---------- Split files to groups ---------- // ---------- Split files to groups ----------
bool useFilters = options.UseFilters;
const CCompressionMethodMode &method = *options.Method; const CCompressionMethodMode &method = *options.Method;
if (useFilters) FOR_VECTOR (i, updateItems)
for (i = 0; i < method.Methods.Size(); i++)
if (IsFilterMethod(method.Methods[i].Id))
{
useFilters = false;
break;
}
/*
if (!method.Bonds.IsEmpty())
useFilters = false;
*/
for (i = 0; i < updateItems.Size(); i++)
{ {
const CUpdateItem &ui = updateItems[i]; const CUpdateItem &ui = updateItems[i];
if (!ui.NewData || !ui.HasStream()) if (!ui.NewData || !ui.HasStream())
@@ -1849,6 +1858,8 @@ HRESULT Update(
/* ---------- Write non-AUX dirs and Empty files ---------- */ /* ---------- Write non-AUX dirs and Empty files ---------- */
CUIntVector emptyRefs; CUIntVector emptyRefs;
unsigned i;
for (i = 0; i < updateItems.Size(); i++) for (i = 0; i < updateItems.Size(); i++)
{ {
const CUpdateItem &ui = updateItems[i]; const CUpdateItem &ui = updateItems[i];
@@ -1911,7 +1922,8 @@ HRESULT Update(
const CFilterMode2 &filterMode = filters[groupIndex]; const CFilterMode2 &filterMode = filters[groupIndex];
CCompressionMethodMode method = *options.Method; CCompressionMethodMode method = *options.Method;
HRESULT res = MakeExeMethod(method, filterMode, {
HRESULT res = MakeExeMethod(method, filterMode,
#ifdef _7ZIP_ST #ifdef _7ZIP_ST
false false
#else #else
@@ -1919,7 +1931,8 @@ HRESULT Update(
#endif #endif
); );
RINOK(res); RINOK(res);
}
if (filterMode.Encrypted) if (filterMode.Encrypted)
{ {
@@ -2153,7 +2166,13 @@ HRESULT Update(
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
if (options.MultiThreadMixer) if (options.MultiThreadMixer)
{ {
// 16.00: hang was fixed : for case if decoding was not finished.
// We close CBinderInStream and it calls CStreamBinder::CloseRead()
inStreamSizeCount.Release();
sbInStream.Release();
threadDecoder.WaitExecuteFinish(); threadDecoder.WaitExecuteFinish();
HRESULT decodeRes = threadDecoder.Result; HRESULT decodeRes = threadDecoder.Result;
// if (res == k_My_HRESULT_CRC_ERROR) // if (res == k_My_HRESULT_CRC_ERROR)
if (decodeRes == S_FALSE) if (decodeRes == S_FALSE)
@@ -2252,8 +2271,12 @@ HRESULT Update(
CRecordVector<CRefItem> refItems; CRecordVector<CRefItem> refItems;
refItems.ClearAndSetSize(numFiles); refItems.ClearAndSetSize(numFiles);
bool sortByType = (options.UseTypeSorting && numSolidFiles > 1); bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
unsigned i;
for (i = 0; i < numFiles; i++) for (i = 0; i < numFiles; i++)
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
CSortParam sortParam; CSortParam sortParam;
// sortParam.TreeFolders = &treeFolders; // sortParam.TreeFolders = &treeFolders;
sortParam.SortByType = sortByType; sortParam.SortByType = sortByType;

View File

@@ -13,7 +13,6 @@ AR_OBJS = \
$O\7zEncode.obj \ $O\7zEncode.obj \
$O\7zExtract.obj \ $O\7zExtract.obj \
$O\7zFolderInStream.obj \ $O\7zFolderInStream.obj \
$O\7zFolderOutStream.obj \
$O\7zHandler.obj \ $O\7zHandler.obj \
$O\7zHandlerOut.obj \ $O\7zHandlerOut.obj \
$O\7zHeader.obj \ $O\7zHeader.obj \
@@ -65,7 +64,6 @@ COMPRESS_OBJS = \
AR_COMMON_OBJS = \ AR_COMMON_OBJS = \
$O\CoderMixer2.obj \ $O\CoderMixer2.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \ $O\HandlerOut.obj \
$O\InStreamWithCRC.obj \ $O\InStreamWithCRC.obj \
$O\ItemNameUtils.obj \ $O\ItemNameUtils.obj \

View File

@@ -7,16 +7,13 @@
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/Defs.h" #include "../../Common/Defs.h"
#include "../../Common/IntToString.h" #include "../../Common/IntToString.h"
#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h" #include "HandlerCont.h"
#define Get16(p) GetBe16(p) #define Get16(p) GetBe16(p)
#define Get32(p) GetBe32(p) #define Get32(p) GetBe32(p)
@@ -75,13 +72,9 @@ struct CItem
} }
}; };
class CHandler: class CHandler: public CHandlerCont
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{ {
CRecordVector<CItem> _items; CRecordVector<CItem> _items;
CMyComPtr<IInStream> _stream;
unsigned _blockSizeLog; unsigned _blockSizeLog;
UInt32 _numBlocks; UInt32 _numBlocks;
UInt64 _phySize; UInt64 _phySize;
@@ -89,11 +82,17 @@ class CHandler:
HRESULT ReadTables(IInStream *stream); HRESULT ReadTables(IInStream *stream);
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
UInt64 GetItemSize(const CItem &item) const { return BlocksToBytes(item.NumBlocks); }
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
{
const CItem &item = _items[index];
pos = BlocksToBytes(item.StartBlock);
size = BlocksToBytes(item.NumBlocks);
return NExtract::NOperationResult::kOK;
}
public: public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive_Cont(;)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
}; };
static const UInt32 kSectorSize = 512; static const UInt32 kSectorSize = 512;
@@ -300,7 +299,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
} }
case kpidSize: case kpidSize:
case kpidPackSize: case kpidPackSize:
prop = GetItemSize(item); prop = BlocksToBytes(item.NumBlocks);
break; break;
case kpidOffset: prop = BlocksToBytes(item.StartBlock); break; case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;
} }
@@ -309,73 +308,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP 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 (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += GetItemSize(_items[allFilesMode ? i : indices[i]]);
extractCallback->SetTotal(totalSize);
totalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++)
{
lps->InSize = totalSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &outStream, askMode));
UInt64 size = GetItemSize(item);
totalSize += size;
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(_stream->Seek(BlocksToBytes(item.StartBlock), STREAM_SEEK_SET, NULL));
streamSpec->Init(size);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release();
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == size ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItem &item = _items[index];
return CreateLimitedInStream(_stream, BlocksToBytes(item.StartBlock), GetItemSize(item), stream);
COM_TRY_END
}
static const Byte k_Signature[] = { kSig0, kSig1 }; static const Byte k_Signature[] = { kSig0, kSig1 };
REGISTER_ARC_I( REGISTER_ARC_I(

View File

@@ -343,16 +343,17 @@ HRESULT CHandler::ParseLongNames(IInStream *stream)
if (item.Size > ((UInt32)1 << 30)) if (item.Size > ((UInt32)1 << 30))
return S_FALSE; return S_FALSE;
RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL)); RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
size_t size = (size_t)item.Size; const size_t size = (size_t)item.Size;
CByteArr p(size); CByteArr p(size);
RINOK(ReadStream_FALSE(stream, p, size)); RINOK(ReadStream_FALSE(stream, p, size));
for (i = 0; i < _items.Size(); i++) for (i = 0; i < _items.Size(); i++)
{ {
CItem &item = _items[i]; CItem &item2 = _items[i];
if (item.Name[0] != '/') if (item2.Name[0] != '/')
continue; continue;
const char *ptr = item.Name.Ptr(1); const char *ptr = item2.Name.Ptr(1);
const char *end; const char *end;
UInt32 pos = ConvertStringToUInt32(ptr, &end); UInt32 pos = ConvertStringToUInt32(ptr, &end);
if (*end != 0 || end == ptr) if (*end != 0 || end == ptr)
@@ -369,8 +370,9 @@ HRESULT CHandler::ParseLongNames(IInStream *stream)
break; break;
pos++; pos++;
} }
item.Name.SetFrom((const char *)(p + start), pos - start); item2.Name.SetFrom((const char *)(p + start), pos - start);
} }
_longNames_FileIndex = fileIndex; _longNames_FileIndex = fileIndex;
return S_OK; return S_OK;
} }

View File

@@ -29,15 +29,24 @@ CCabBlockInStream::~CCabBlockInStream()
static UInt32 CheckSum(const Byte *p, UInt32 size) static UInt32 CheckSum(const Byte *p, UInt32 size)
{ {
UInt32 sum = 0; UInt32 sum = 0;
for (UInt32 i = size >> 2; i != 0; i--)
for (; size >= 8; size -= 8)
{
sum ^= GetUi32(p) ^ GetUi32(p + 4);
p += 8;
}
if (size >= 4)
{ {
sum ^= GetUi32(p); sum ^= GetUi32(p);
p += 4; p += 4;
} }
size &= 3; size &= 3;
if (size > 2) sum ^= (UInt32)(*p++) << 16; if (size > 2) sum ^= (UInt32)(*p++) << 16;
if (size > 1) sum ^= (UInt32)(*p++) << 8; if (size > 1) sum ^= (UInt32)(*p++) << 8;
if (size > 0) sum ^= (UInt32)(*p++); if (size > 0) sum ^= (UInt32)(*p++);
return sum; return sum;
} }

View File

@@ -25,10 +25,16 @@ public:
CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {} CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {}
~CCabBlockInStream(); ~CCabBlockInStream();
bool Create(); bool Create();
void InitForNewBlock() { _size = 0; _pos = 0; } void InitForNewBlock() { _size = 0; _pos = 0; }
HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize); HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
UInt32 GetPackSizeAvail() const { return _size - _pos; }
const Byte *GetData() const { return _buf + _pos; }
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
}; };

View File

@@ -168,7 +168,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidVolumeIndex: case kpidVolumeIndex:
{ {
if (m_Database.Volumes.Size() == 1) if (!m_Database.Volumes.IsEmpty())
{ {
const CDatabaseEx &db = m_Database.Volumes[0]; const CDatabaseEx &db = m_Database.Volumes[0];
const CInArcInfo &ai = db.ArcInfo; const CInArcInfo &ai = db.ArcInfo;
@@ -348,15 +348,19 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
CMyComPtr<IInStream> nextStream = inStream; CMyComPtr<IInStream> nextStream = inStream;
bool prevChecked = false; bool prevChecked = false;
UString startVolName;
bool startVolName_was_Requested = false;
UInt64 numItems = 0; UInt64 numItems = 0;
unsigned numTempVolumes = 0; unsigned numTempVolumes = 0;
// try // try
{ {
while (nextStream != NULL) while (nextStream)
{ {
CDatabaseEx db; CDatabaseEx db;
db.Stream = nextStream; db.Stream = nextStream;
HRESULT res = archive.Open(db, maxCheckStartPosition); HRESULT res = archive.Open(db, maxCheckStartPosition);
_errorInHeaders |= archive.HeaderError; _errorInHeaders |= archive.HeaderError;
_errorInHeaders |= archive.ErrorInNames; _errorInHeaders |= archive.ErrorInNames;
_unexpectedEnd |= archive.UnexpectedEnd; _unexpectedEnd |= archive.UnexpectedEnd;
@@ -426,6 +430,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
for (;;) for (;;)
{ {
const COtherArc *otherArc = NULL; const COtherArc *otherArc = NULL;
if (!prevChecked) if (!prevChecked)
{ {
if (numTempVolumes == 0) if (numTempVolumes == 0)
@@ -449,18 +454,35 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
} }
} }
} }
if (!otherArc) if (!otherArc)
{ {
const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo; const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;
if (ai.IsThereNext()) if (ai.IsThereNext())
otherArc = &ai.NextArc; otherArc = &ai.NextArc;
} }
if (!otherArc) if (!otherArc)
break; break;
if (!openVolumeCallback) if (!openVolumeCallback)
break; break;
// printf("\n%s", otherArc->FileName); // printf("\n%s", otherArc->FileName);
const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP); const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);
if (!startVolName_was_Requested)
{
// some "bad" cab example can contain the link to itself.
startVolName_was_Requested = true;
{
NCOM::CPropVariant prop;
RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
if (prop.vt == VT_BSTR)
startVolName = prop.bstrVal;
}
if (fullName == startVolName)
break;
}
HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
if (result == S_OK) if (result == S_OK)
break; break;
@@ -569,13 +591,15 @@ public:
UInt64 folderSize, UInt64 folderSize,
IArchiveExtractCallback *extractCallback, IArchiveExtractCallback *extractCallback,
bool testMode); bool testMode);
HRESULT FlushCorrupted(); HRESULT FlushCorrupted(unsigned folderIndex);
HRESULT Unsupported(); HRESULT Unsupported();
bool NeedMoreWrite() const { return (m_FolderSize > m_PosInFolder); }
UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; } UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; }
UInt64 GetPosInFolder() const { return m_PosInFolder; } UInt64 GetPosInFolder() const { return m_PosInFolder; }
}; };
void CFolderOutStream::Init( void CFolderOutStream::Init(
const CMvDatabaseEx *database, const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses, const CRecordVector<bool> *extractStatuses,
@@ -600,6 +624,7 @@ void CFolderOutStream::Init(
NumIdenticalFiles = 0; NumIdenticalFiles = 0;
} }
HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp) HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp)
{ {
m_RealOutStream.Release(); m_RealOutStream.Release();
@@ -608,6 +633,7 @@ HRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp)
return m_ExtractCallback->SetOperationResult(resOp); return m_ExtractCallback->SetOperationResult(resOp);
} }
HRESULT CFolderOutStream::CloseFile() HRESULT CFolderOutStream::CloseFile()
{ {
return CloseFileWithResOp(m_IsOk ? return CloseFileWithResOp(m_IsOk ?
@@ -615,6 +641,7 @@ HRESULT CFolderOutStream::CloseFile()
NExtract::NOperationResult::kDataError); NExtract::NOperationResult::kDataError);
} }
HRESULT CFolderOutStream::OpenFile() HRESULT CFolderOutStream::OpenFile()
{ {
if (NumIdenticalFiles == 0) if (NumIdenticalFiles == 0)
@@ -680,6 +707,7 @@ HRESULT CFolderOutStream::OpenFile()
return m_ExtractCallback->PrepareOperation(askMode); return m_ExtractCallback->PrepareOperation(askMode);
} }
HRESULT CFolderOutStream::WriteEmptyFiles() HRESULT CFolderOutStream::WriteEmptyFiles()
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
@@ -699,13 +727,15 @@ HRESULT CFolderOutStream::WriteEmptyFiles()
return S_OK; return S_OK;
} }
// This is Write function
HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
UInt32 realProcessed = 0; UInt32 realProcessed = 0;
if (processedSize) if (processedSize)
*processedSize = 0; *processedSize = 0;
while (size != 0) while (size != 0)
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
@@ -732,8 +762,10 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
size -= numBytesToWrite; size -= numBytesToWrite;
m_RemainFileSize -= numBytesToWrite; m_RemainFileSize -= numBytesToWrite;
m_PosInFolder += numBytesToWrite; m_PosInFolder += numBytesToWrite;
if (res != S_OK) if (res != S_OK)
return res; return res;
if (m_RemainFileSize == 0) if (m_RemainFileSize == 0)
{ {
RINOK(CloseFile()); RINOK(CloseFile());
@@ -754,17 +786,28 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{ {
RINOK(CloseFile()); RINOK(CloseFile());
} }
RINOK(result); RINOK(result);
} }
TempBufMode = false; TempBufMode = false;
} }
if (realProcessed > 0) if (realProcessed > 0)
break; // with this break this function works as Write-Part break; // with this break this function works as Write-Part
} }
else else
{ {
if (m_CurrentIndex >= m_ExtractStatuses->Size()) if (m_CurrentIndex >= m_ExtractStatuses->Size())
return E_FAIL; {
// we ignore extra data;
realProcessed += size;
if (processedSize)
*processedSize = realProcessed;
m_PosInFolder += size;
return S_OK;
// return E_FAIL;
}
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
@@ -772,8 +815,10 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
m_RemainFileSize = item.Size; m_RemainFileSize = item.Size;
UInt32 fileOffset = item.Offset; UInt32 fileOffset = item.Offset;
if (fileOffset < m_PosInFolder) if (fileOffset < m_PosInFolder)
return E_FAIL; return E_FAIL;
if (fileOffset > m_PosInFolder) if (fileOffset > m_PosInFolder)
{ {
UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size); UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
@@ -784,6 +829,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
size -= numBytesToWrite; size -= numBytesToWrite;
m_PosInFolder += numBytesToWrite; m_PosInFolder += numBytesToWrite;
} }
if (fileOffset == m_PosInFolder) if (fileOffset == m_PosInFolder)
{ {
RINOK(OpenFile()); RINOK(OpenFile());
@@ -793,32 +839,49 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
} }
} }
} }
return WriteEmptyFiles(); return WriteEmptyFiles();
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
return Write2(data, size, processedSize, true); return Write2(data, size, processedSize, true);
} }
HRESULT CFolderOutStream::FlushCorrupted()
HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
{ {
const unsigned kBufSize = (1 << 10); if (!NeedMoreWrite())
{
CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
m_ExtractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
if (callbackMessage)
{
RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, NExtract::NOperationResult::kDataError));
}
return S_OK;
}
const unsigned kBufSize = (1 << 12);
Byte buf[kBufSize]; Byte buf[kBufSize];
for (unsigned i = 0; i < kBufSize; i++) for (unsigned i = 0; i < kBufSize; i++)
buf[i] = 0; buf[i] = 0;
for (;;) for (;;)
{ {
UInt64 remain = GetRemain(); if (!NeedMoreWrite())
if (remain == 0)
return S_OK; return S_OK;
UInt64 remain = GetRemain();
UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize); UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
UInt32 processedSizeLocal = 0; UInt32 processedSizeLocal = 0;
RINOK(Write2(buf, size, &processedSizeLocal, false)); RINOK(Write2(buf, size, &processedSizeLocal, false));
} }
} }
HRESULT CFolderOutStream::Unsupported() HRESULT CFolderOutStream::Unsupported()
{ {
while (m_CurrentIndex < m_ExtractStatuses->Size()) while (m_CurrentIndex < m_ExtractStatuses->Size())
@@ -838,6 +901,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallback) Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)(Int32)-1); bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode) if (allFilesMode)
numItems = m_Database.Items.Size(); numItems = m_Database.Items.Size();
@@ -883,10 +947,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressCoder> deflateDecoder; CMyComPtr<ICompressCoder> deflateDecoder;
NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL; NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL;
CMyComPtr<ICompressCoder> lzxDecoder; CMyComPtr<IUnknown> lzxDecoder;
NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL; NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL;
CMyComPtr<ICompressCoder> quantumDecoder; CMyComPtr<IUnknown> quantumDecoder;
CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream(); CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream();
CMyComPtr<ISequentialInStream> cabBlockInStream = cabBlockInStreamSpec; CMyComPtr<ISequentialInStream> cabBlockInStream = cabBlockInStreamSpec;
@@ -895,8 +959,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CRecordVector<bool> extractStatuses; CRecordVector<bool> extractStatuses;
for (i = 0; i < numItems;) for (i = 0;;)
{ {
lps->OutSize = totalUnPacked;
lps->InSize = totalPacked;
RINOK(lps->SetCur());
if (i >= numItems)
break;
unsigned index = allFilesMode ? i : indices[i]; unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index]; const CMvItem &mvItem = m_Database.Items[index];
@@ -946,11 +1017,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (; i < numItems; i++) for (; i < numItems; i++)
{ {
unsigned indexNext = allFilesMode ? i : indices[i]; unsigned indexNext = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[indexNext]; const CMvItem &mvItem2 = m_Database.Items[indexNext];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; const CItem &item2 = m_Database.Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];
if (item.IsDir()) if (item2.IsDir())
continue; continue;
int newFolderIndex = m_Database.GetFolderIndex(&mvItem); int newFolderIndex = m_Database.GetFolderIndex(&mvItem2);
if (newFolderIndex != folderIndex) if (newFolderIndex != folderIndex)
break; break;
@@ -958,17 +1029,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
extractStatuses.Add(false); extractStatuses.Add(false);
extractStatuses.Add(true); extractStatuses.Add(true);
startIndex++; startIndex++;
curUnpack = item.GetEndOffset(); curUnpack = item2.GetEndOffset();
} }
lps->OutSize = totalUnPacked;
lps->InSize = totalPacked;
RINOK(lps->SetCur());
CFolderOutStream *cabFolderOutStream = new CFolderOutStream; CFolderOutStream *cabFolderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream); CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())]; unsigned folderIndex2 = item.GetFolderIndex(db.Folders.Size());
const CFolder &folder = db.Folders[folderIndex2];
cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,
curUnpack, extractCallback, testMode); curUnpack, extractCallback, testMode);
@@ -980,6 +1048,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
case NHeader::NMethod::kNone: case NHeader::NMethod::kNone:
break; break;
case NHeader::NMethod::kMSZip: case NHeader::NMethod::kMSZip:
if (!deflateDecoder) if (!deflateDecoder)
{ {
@@ -988,14 +1057,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
cabBlockInStreamSpec->MsZip = true; cabBlockInStreamSpec->MsZip = true;
break; break;
case NHeader::NMethod::kLZX: case NHeader::NMethod::kLZX:
if (!lzxDecoder) if (!lzxDecoder)
{ {
lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec; lzxDecoder = lzxDecoderSpec;
} }
res = lzxDecoderSpec->SetParams(folder.MethodMinor); res = lzxDecoderSpec->SetParams_and_Alloc(folder.MethodMinor);
break; break;
case NHeader::NMethod::kQuantum: case NHeader::NMethod::kQuantum:
if (!quantumDecoder) if (!quantumDecoder)
{ {
@@ -1004,6 +1075,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
res = quantumDecoderSpec->SetParams(folder.MethodMinor); res = quantumDecoderSpec->SetParams(folder.MethodMinor);
break; break;
default: default:
res = E_INVALIDARG; res = E_INVALIDARG;
break; break;
@@ -1022,8 +1094,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
bool keepHistory = false; bool keepHistory = false;
bool keepInputBuffer = false; bool keepInputBuffer = false;
bool thereWasNotAlignedChunk = false;
for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;) for (UInt32 bl = 0; cabFolderOutStream->NeedMoreWrite();)
{ {
if (volIndex >= m_Database.Volumes.Size()) if (volIndex >= m_Database.Volumes.Size())
{ {
@@ -1031,16 +1104,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
break; break;
} }
const CDatabaseEx &db = m_Database.Volumes[volIndex]; const CDatabaseEx &db2 = m_Database.Volumes[volIndex];
const CFolder &folder = db.Folders[locFolderIndex]; const CFolder &folder2 = db2.Folders[locFolderIndex];
if (bl == 0) if (bl == 0)
{ {
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize(); cabBlockInStreamSpec->ReservedSize = db2.ArcInfo.GetDataBlockReserveSize();
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); RINOK(db2.Stream->Seek(db2.StartPosition + folder2.DataStart, STREAM_SEEK_SET, NULL));
} }
if (bl == folder.NumDataBlocks) if (bl == folder2.NumDataBlocks)
{ {
/* /*
CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit. CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.
@@ -1058,13 +1131,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue; continue;
} }
} }
bl++; bl++;
if (!keepInputBuffer) if (!keepInputBuffer)
cabBlockInStreamSpec->InitForNewBlock(); cabBlockInStreamSpec->InitForNewBlock();
UInt32 packSize, unpackSize; UInt32 packSize, unpackSize;
res = cabBlockInStreamSpec->PreRead(db.Stream, packSize, unpackSize); res = cabBlockInStreamSpec->PreRead(db2.Stream, packSize, unpackSize);
if (res == S_FALSE) if (res == S_FALSE)
break; break;
RINOK(res); RINOK(res);
@@ -1079,19 +1153,39 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lps->InSize = totalPacked; lps->InSize = totalPacked;
RINOK(lps->SetCur()); RINOK(lps->SetCur());
UInt64 unpackRemain = cabFolderOutStream->GetRemain();
const UInt32 kBlockSizeMax = (1 << 15); const UInt32 kBlockSizeMax = (1 << 15);
if (unpackRemain > kBlockSizeMax)
unpackRemain = kBlockSizeMax;
if (unpackRemain > unpackSize)
unpackRemain = unpackSize;
switch (folder.GetMethod()) /* We don't try to reduce last block.
Note that LZX converts data with x86 filter.
and filter needs larger input data than reduced size.
It's simpler to decompress full chunk here.
also we need full block for quantum for more integrity checks */
if (unpackSize > kBlockSizeMax)
{
res = S_FALSE;
break;
}
if (unpackSize != kBlockSizeMax)
{
if (thereWasNotAlignedChunk)
{
res = S_FALSE;
break;
}
thereWasNotAlignedChunk = true;
}
UInt64 unpackSize64 = unpackSize;
UInt32 packSizeChunk = cabBlockInStreamSpec->GetPackSizeAvail();
switch (folder2.GetMethod())
{ {
case NHeader::NMethod::kNone: case NHeader::NMethod::kNone:
res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackSize64, NULL);
break; break;
case NHeader::NMethod::kMSZip: case NHeader::NMethod::kMSZip:
deflateDecoderSpec->Set_KeepHistory(keepHistory); deflateDecoderSpec->Set_KeepHistory(keepHistory);
/* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block. /* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block.
@@ -1100,7 +1194,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Maybe we also should ignore that error? Maybe we also should ignore that error?
Or we should extract full file and show the warning? */ Or we should extract full file and show the warning? */
deflateDecoderSpec->Set_NeedFinishInput(true); deflateDecoderSpec->Set_NeedFinishInput(true);
res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackSize64, NULL);
if (res == S_OK) if (res == S_OK)
{ {
if (!deflateDecoderSpec->IsFinished()) if (!deflateDecoderSpec->IsFinished())
@@ -1108,16 +1202,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (!deflateDecoderSpec->IsFinalBlock()) if (!deflateDecoderSpec->IsFinalBlock())
res = S_FALSE; res = S_FALSE;
} }
break; break;
case NHeader::NMethod::kLZX: case NHeader::NMethod::kLZX:
lzxDecoderSpec->SetKeepHistory(keepHistory); lzxDecoderSpec->SetKeepHistory(keepHistory);
res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); lzxDecoderSpec->KeepHistoryForNext = true;
res = lzxDecoderSpec->Code(cabBlockInStreamSpec->GetData(), packSizeChunk, unpackSize);
if (res == S_OK)
res = WriteStream(outStream,
lzxDecoderSpec->GetUnpackData(),
lzxDecoderSpec->GetUnpackSize());
break; break;
case NHeader::NMethod::kQuantum: case NHeader::NMethod::kQuantum:
quantumDecoderSpec->SetKeepHistory(keepHistory); res = quantumDecoderSpec->Code(cabBlockInStreamSpec->GetData(),
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); packSizeChunk, outStream, unpackSize, keepHistory);
break; break;
} }
if (res != S_OK) if (res != S_OK)
@@ -1135,17 +1237,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(cabFolderOutStream->WriteEmptyFiles()); RINOK(cabFolderOutStream->WriteEmptyFiles());
} }
} }
if (res != S_OK || cabFolderOutStream->GetRemain() != 0)
if (res != S_OK || cabFolderOutStream->NeedMoreWrite())
{ {
RINOK(cabFolderOutStream->FlushCorrupted()); RINOK(cabFolderOutStream->FlushCorrupted(folderIndex2));
} }
totalUnPacked += curUnpack; totalUnPacked += curUnpack;
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{ {
*numItems = m_Database.Items.Size(); *numItems = m_Database.Items.Size();

View File

@@ -67,6 +67,7 @@ void CInArchive::ReadOtherArc(COtherArc &oa)
ReadName(oa.DiskName); ReadName(oa.DiskName);
} }
struct CSignatureFinder struct CSignatureFinder
{ {
Byte *Buf; Byte *Buf;
@@ -100,6 +101,7 @@ struct CSignatureFinder
HRESULT Find(); HRESULT Find();
}; };
HRESULT CSignatureFinder::Find() HRESULT CSignatureFinder::Find()
{ {
for (;;) for (;;)
@@ -156,6 +158,7 @@ HRESULT CSignatureFinder::Find()
} }
} }
bool CInArcInfo::Parse(const Byte *p) bool CInArcInfo::Parse(const Byte *p)
{ {
if (Get32(p + 0x0C) != 0 || if (Get32(p + 0x0C) != 0 ||
@@ -177,6 +180,7 @@ bool CInArcInfo::Parse(const Byte *p)
return true; return true;
} }
HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
{ {
IsArc = false; IsArc = false;
@@ -286,7 +290,9 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
if (ai.IsThereNext()) ReadOtherArc(ai.NextArc); if (ai.IsThereNext()) ReadOtherArc(ai.NextArc);
UInt32 i; UInt32 i;
db.Folders.ClearAndReserve(ai.NumFolders); db.Folders.ClearAndReserve(ai.NumFolders);
for (i = 0; i < ai.NumFolders; i++) for (i = 0; i < ai.NumFolders; i++)
{ {
Read(p, 8); Read(p, 8);
@@ -311,6 +317,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
} }
db.Items.ClearAndReserve(ai.NumFiles); db.Items.ClearAndReserve(ai.NumFiles);
for (i = 0; i < ai.NumFiles; i++) for (i = 0; i < ai.NumFiles; i++)
{ {
Read(p, 16); Read(p, 16);
@@ -324,6 +331,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
item.Attributes = Get16(p + 14); item.Attributes = Get16(p + 14);
ReadName(item.Name); ReadName(item.Name);
if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size()) if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size())
{ {
HeaderError = true; HeaderError = true;
@@ -336,6 +344,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
return S_OK; return S_OK;
} }
HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
{ {
try try
@@ -370,6 +379,7 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
return MyCompare(p1->ItemIndex, p2->ItemIndex); return MyCompare(p1->ItemIndex, p2->ItemIndex);
} }
bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
{ {
const CMvItem *p1 = &Items[i1]; const CMvItem *p1 = &Items[i1];
@@ -384,12 +394,15 @@ bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
&& item1.Name == item2.Name; && item1.Name == item2.Name;
} }
void CMvDatabaseEx::FillSortAndShrink() void CMvDatabaseEx::FillSortAndShrink()
{ {
Items.Clear(); Items.Clear();
StartFolderOfVol.Clear(); StartFolderOfVol.Clear();
FolderStartFileIndex.Clear(); FolderStartFileIndex.Clear();
int offset = 0; int offset = 0;
FOR_VECTOR (v, Volumes) FOR_VECTOR (v, Volumes)
{ {
const CDatabaseEx &db = Volumes[v]; const CDatabaseEx &db = Volumes[v];
@@ -422,11 +435,12 @@ void CMvDatabaseEx::FillSortAndShrink()
FOR_VECTOR (i, Items) FOR_VECTOR (i, Items)
{ {
int folderIndex = GetFolderIndex(&Items[i]); int folderIndex = GetFolderIndex(&Items[i]);
if (folderIndex >= (int)FolderStartFileIndex.Size()) while (folderIndex >= (int)FolderStartFileIndex.Size())
FolderStartFileIndex.Add(i); FolderStartFileIndex.Add(i);
} }
} }
bool CMvDatabaseEx::Check() bool CMvDatabaseEx::Check()
{ {
for (unsigned v = 1; v < Volumes.Size(); v++) for (unsigned v = 1; v < Volumes.Size(); v++)
@@ -444,9 +458,11 @@ bool CMvDatabaseEx::Check()
return false; return false;
} }
} }
UInt32 beginPos = 0; UInt32 beginPos = 0;
UInt64 endPos = 0; UInt64 endPos = 0;
int prevFolder = -2; int prevFolder = -2;
FOR_VECTOR (i, Items) FOR_VECTOR (i, Items)
{ {
const CMvItem &mvItem = Items[i]; const CMvItem &mvItem = Items[i];
@@ -456,15 +472,19 @@ bool CMvDatabaseEx::Check()
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir()) if (item.IsDir())
continue; continue;
int folderIndex = GetFolderIndex(&mvItem); int folderIndex = GetFolderIndex(&mvItem);
if (folderIndex != prevFolder) if (folderIndex != prevFolder)
prevFolder = folderIndex; prevFolder = folderIndex;
else if (item.Offset < endPos && else if (item.Offset < endPos &&
(item.Offset != beginPos || item.GetEndOffset() != endPos)) (item.Offset != beginPos || item.GetEndOffset() != endPos))
return false; return false;
beginPos = item.Offset; beginPos = item.Offset;
endPos = item.GetEndOffset(); endPos = item.GetEndOffset();
} }
return true; return true;
} }

View File

@@ -25,6 +25,7 @@ struct COtherArc
} }
}; };
struct CArchInfo struct CArchInfo
{ {
Byte VersionMinor; // cabinet file format version, minor Byte VersionMinor; // cabinet file format version, minor
@@ -65,6 +66,7 @@ struct CArchInfo
} }
}; };
struct CInArcInfo: public CArchInfo struct CInArcInfo: public CArchInfo
{ {
UInt32 Size; // size of this cabinet file in bytes UInt32 Size; // size of this cabinet file in bytes
@@ -105,17 +107,20 @@ struct CDatabase
} }
}; };
struct CDatabaseEx: public CDatabase struct CDatabaseEx: public CDatabase
{ {
CMyComPtr<IInStream> Stream; CMyComPtr<IInStream> Stream;
}; };
struct CMvItem struct CMvItem
{ {
unsigned VolumeIndex; unsigned VolumeIndex;
unsigned ItemIndex; unsigned ItemIndex;
}; };
class CMvDatabaseEx class CMvDatabaseEx
{ {
bool AreItemsEqual(unsigned i1, unsigned i2); bool AreItemsEqual(unsigned i1, unsigned i2);

View File

@@ -101,9 +101,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
if (m_Database.NewFormat) if (m_Database.NewFormat)
{ {
switch(propID) switch (propID)
{ {
case kpidSize: case kpidSize:
prop = (UInt64)m_Database.NewFormatString.Len(); prop = (UInt64)m_Database.NewFormatString.Len();
@@ -112,12 +113,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
} }
int entryIndex;
unsigned entryIndex;
if (m_Database.LowLevel) if (m_Database.LowLevel)
entryIndex = index; entryIndex = index;
else else
entryIndex = m_Database.Indices[index]; entryIndex = m_Database.Indices[index];
const CItem &item = m_Database.Items[entryIndex]; const CItem &item = m_Database.Items[entryIndex];
switch (propID) switch (propID)
{ {
case kpidPath: case kpidPath:
@@ -144,13 +148,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.Section == 0) if (item.Section == 0)
prop = "Copy"; prop = "Copy";
else if (item.Section < m_Database.Sections.Size()) else if (item.Section < m_Database.Sections.Size())
prop = m_Database.Sections[(int)item.Section].GetMethodName(); prop = m_Database.Sections[(unsigned)item.Section].GetMethodName();
break; break;
} }
case kpidBlock: case kpidBlock:
if (m_Database.LowLevel) if (m_Database.LowLevel)
prop = item.Section; prop = item.Section;
else if (item.Section != 0) else if (item.Section != 0 && item.Section < m_Database.Sections.Size())
prop = m_Database.GetFolder(index); prop = m_Database.GetFolder(index);
break; break;
@@ -161,6 +165,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif #endif
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
@@ -244,9 +249,9 @@ public:
UInt64 m_PosInFolder; UInt64 m_PosInFolder;
UInt64 m_PosInSection; UInt64 m_PosInSection;
const CRecordVector<bool> *m_ExtractStatuses; const CRecordVector<bool> *m_ExtractStatuses;
int m_StartIndex; unsigned m_StartIndex;
int m_CurrentIndex; unsigned m_CurrentIndex;
int m_NumFiles; unsigned m_NumFiles;
private: private:
const CFilesDatabase *m_Database; const CFilesDatabase *m_Database;
@@ -298,7 +303,7 @@ HRESULT CChmFolderOutStream::WriteEmptyFiles()
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
return S_OK; return S_OK;
for (;m_CurrentIndex < m_NumFiles; m_CurrentIndex++) for (; m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
{ {
UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex); UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
if (fileSize != 0) if (fileSize != 0)
@@ -315,9 +320,10 @@ HRESULT CChmFolderOutStream::WriteEmptyFiles()
HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
{ {
UInt32 realProcessed = 0; UInt32 realProcessed = 0;
if (processedSize != NULL) if (processedSize)
*processedSize = 0; *processedSize = 0;
while(size != 0)
while (size != 0)
{ {
if (m_FileIsOpen) if (m_FileIsOpen)
{ {
@@ -335,7 +341,7 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
} }
} }
realProcessed += numBytesToWrite; realProcessed += numBytesToWrite;
if (processedSize != NULL) if (processedSize)
*processedSize = realProcessed; *processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite); data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite; size -= numBytesToWrite;
@@ -359,23 +365,32 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
else else
{ {
if (m_CurrentIndex >= m_NumFiles) if (m_CurrentIndex >= m_NumFiles)
return E_FAIL; {
int fullIndex = m_StartIndex + m_CurrentIndex; realProcessed += size;
if (processedSize)
*processedSize = realProcessed;
return S_OK;
// return E_FAIL;
}
unsigned fullIndex = m_StartIndex + m_CurrentIndex;
m_RemainFileSize = m_Database->GetFileSize(fullIndex); m_RemainFileSize = m_Database->GetFileSize(fullIndex);
UInt64 fileOffset = m_Database->GetFileOffset(fullIndex); UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
if (fileOffset < m_PosInSection) if (fileOffset < m_PosInSection)
return E_FAIL; return E_FAIL;
if (fileOffset > m_PosInSection) if (fileOffset > m_PosInSection)
{ {
UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size)); UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));
realProcessed += numBytesToWrite; realProcessed += numBytesToWrite;
if (processedSize != NULL) if (processedSize)
*processedSize = realProcessed; *processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite); data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite; size -= numBytesToWrite;
m_PosInSection += numBytesToWrite; m_PosInSection += numBytesToWrite;
m_PosInFolder += numBytesToWrite; m_PosInFolder += numBytesToWrite;
} }
if (fileOffset == m_PosInSection) if (fileOffset == m_PosInSection)
{ {
RINOK(OpenFile()); RINOK(OpenFile());
@@ -385,6 +400,7 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
} }
} }
} }
return WriteEmptyFiles(); return WriteEmptyFiles();
} }
@@ -397,7 +413,7 @@ HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
{ {
const UInt32 kBufferSize = (1 << 10); const UInt32 kBufferSize = (1 << 10);
Byte buffer[kBufferSize]; Byte buffer[kBufferSize];
for (int i = 0; i < kBufferSize; i++) for (unsigned i = 0; i < kBufferSize; i++)
buffer[i] = 0; buffer[i] = 0;
if (maxSize > m_FolderSize) if (maxSize > m_FolderSize)
maxSize = m_FolderSize; maxSize = m_FolderSize;
@@ -430,7 +446,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 currentTotalSize = 0; UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
UInt32 i; UInt32 i;
@@ -446,11 +462,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
UInt64 currentItemSize = 0; UInt64 currentItemSize = 0;
UInt64 totalSize = 0; UInt64 totalSize = 0;
if (m_Database.NewFormat) if (m_Database.NewFormat)
totalSize = m_Database.NewFormatString.Len(); totalSize = m_Database.NewFormatString.Len();
else else
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
extractCallback->SetTotal(totalSize); extractCallback->SetTotal(totalSize);
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
@@ -481,6 +499,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue; continue;
} }
const CItem &item = m_Database.Items[index]; const CItem &item = m_Database.Items[index];
currentItemSize = item.Size; currentItemSize = item.Size;
@@ -513,12 +532,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
UInt64 lastFolderIndex = ((UInt64)0 - 1); UInt64 lastFolderIndex = ((UInt64)0 - 1);
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
int entryIndex = m_Database.Indices[index]; const CItem &item = m_Database.Items[m_Database.Indices[index]];
const CItem &item = m_Database.Items[entryIndex]; const UInt64 sectionIndex = item.Section;
UInt64 sectionIndex = item.Section;
if (item.IsDir() || item.Size == 0) if (item.IsDir() || item.Size == 0)
continue; continue;
if (sectionIndex == 0) if (sectionIndex == 0)
@@ -526,7 +545,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
currentTotalSize += item.Size; currentTotalSize += item.Size;
continue; continue;
} }
const CSectionInfo &section = m_Database.Sections[(int)item.Section];
if (sectionIndex >= m_Database.Sections.Size())
continue;
const CSectionInfo &section = m_Database.Sections[(unsigned)sectionIndex];
if (section.IsLzx()) if (section.IsLzx())
{ {
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
@@ -541,25 +564,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetTotal(currentTotalSize)); RINOK(extractCallback->SetTotal(currentTotalSize));
NCompress::NLzx::CDecoder *lzxDecoderSpec = 0; NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL;
CMyComPtr<ICompressCoder> lzxDecoder; CMyComPtr<IUnknown> lzxDecoder;
CChmFolderOutStream *chmFolderOutStream = 0; CChmFolderOutStream *chmFolderOutStream = 0;
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
currentTotalSize = 0; currentTotalSize = 0;
CRecordVector<bool> extractStatuses; CRecordVector<bool> extractStatuses;
for (i = 0; i < numItems;)
CByteBuffer packBuf;
for (i = 0;;)
{ {
RINOK(extractCallback->SetCompleted(&currentTotalSize)); RINOK(extractCallback->SetCompleted(&currentTotalSize));
if (i >= numItems)
break;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
i++; i++;
int entryIndex = m_Database.Indices[index]; const CItem &item = m_Database.Items[m_Database.Indices[index]];
const CItem &item = m_Database.Items[entryIndex]; const UInt64 sectionIndex = item.Section;
UInt64 sectionIndex = item.Section;
Int32 askMode= testMode ? Int32 askMode= testMode ?
NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
if (item.IsDir()) if (item.IsDir())
{ {
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
@@ -595,7 +625,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue; continue;
} }
const CSectionInfo &section = m_Database.Sections[(int)sectionIndex]; if (sectionIndex >= m_Database.Sections.Size())
{
// we must report error here;
CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError));
continue;
}
const CSectionInfo &section = m_Database.Sections[(unsigned)sectionIndex];
if (!section.IsLzx()) if (!section.IsLzx())
{ {
@@ -610,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
if (chmFolderOutStream == 0) if (!chmFolderOutStream)
{ {
chmFolderOutStream = new CChmFolderOutStream; chmFolderOutStream = new CChmFolderOutStream;
outStream = chmFolderOutStream; outStream = chmFolderOutStream;
@@ -618,7 +660,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
chmFolderOutStream->Init(&m_Database, extractCallback, testMode); chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
if (lzxDecoderSpec == NULL) if (!lzxDecoderSpec)
{ {
lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec; lzxDecoder = lzxDecoderSpec;
@@ -626,9 +668,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 folderIndex = m_Database.GetFolder(index); UInt64 folderIndex = m_Database.GetFolder(index);
UInt64 compressedPos = m_Database.ContentOffset + section.Offset; const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
UInt32 numDictBits = lzxInfo.GetNumDictBits(); RINOK(lzxDecoderSpec->SetParams_and_Alloc(lzxInfo.GetNumDictBits()));
RINOK(lzxDecoderSpec->SetParams(numDictBits));
const CItem *lastItem = &item; const CItem *lastItem = &item;
extractStatuses.Clear(); extractStatuses.Clear();
@@ -645,17 +686,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastFolderIndex = m_Database.GetLastFolder(index); lastFolderIndex = m_Database.GetLastFolder(index);
UInt64 folderSize = lzxInfo.GetFolderSize(); UInt64 folderSize = lzxInfo.GetFolderSize();
UInt64 unPackSize = folderSize; UInt64 unPackSize = folderSize;
if (extractStatuses.IsEmpty()) if (extractStatuses.IsEmpty())
chmFolderOutStream->m_StartIndex = index + 1; chmFolderOutStream->m_StartIndex = index + 1;
else else
chmFolderOutStream->m_StartIndex = index; chmFolderOutStream->m_StartIndex = index;
if (limitFolderIndex == folderIndex) if (limitFolderIndex == folderIndex)
{ {
for (; i < numItems; i++) for (; i < numItems; i++)
{ {
UInt32 nextIndex = allFilesMode ? i : indices[i]; const UInt32 nextIndex = allFilesMode ? i : indices[i];
int entryIndex = m_Database.Indices[nextIndex]; const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];
const CItem &nextItem = m_Database.Items[entryIndex];
if (nextItem.Section != sectionIndex) if (nextItem.Section != sectionIndex)
break; break;
UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex); UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
@@ -671,6 +713,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastFolderIndex = m_Database.GetLastFolder(index); lastFolderIndex = m_Database.GetLastFolder(index);
} }
} }
unPackSize = MyMin(finishPos - startPos, unPackSize); unPackSize = MyMin(finishPos - startPos, unPackSize);
chmFolderOutStream->m_FolderSize = folderSize; chmFolderOutStream->m_FolderSize = folderSize;
@@ -679,11 +722,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
chmFolderOutStream->m_ExtractStatuses = &extractStatuses; chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
chmFolderOutStream->m_NumFiles = extractStatuses.Size(); chmFolderOutStream->m_NumFiles = extractStatuses.Size();
chmFolderOutStream->m_CurrentIndex = 0; chmFolderOutStream->m_CurrentIndex = 0;
try try
{ {
UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex); UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
const CResetTable &rt = lzxInfo.ResetTable; const CResetTable &rt = lzxInfo.ResetTable;
UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize); UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
for (UInt32 b = 0; b < numBlocks; b++) for (UInt32 b = 0; b < numBlocks; b++)
{ {
UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos; UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
@@ -691,17 +736,35 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 bCur = startBlock + b; UInt64 bCur = startBlock + b;
if (bCur >= rt.ResetOffsets.Size()) if (bCur >= rt.ResetOffsets.Size())
return E_FAIL; return E_FAIL;
UInt64 offset = rt.ResetOffsets[(int)bCur]; UInt64 offset = rt.ResetOffsets[(unsigned)bCur];
UInt64 compressedSize; UInt64 compressedSize;
rt.GetCompressedSizeOfBlock(bCur, compressedSize); rt.GetCompressedSizeOfBlock(bCur, compressedSize);
UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;
if (rem > rt.BlockSize) // chm writes full blocks. So we don't need to use reduced size for last block
rem = rt.BlockSize;
RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL)); RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));
streamSpec->SetStream(m_Stream); streamSpec->SetStream(m_Stream);
streamSpec->Init(compressedSize); streamSpec->Init(compressedSize);
lzxDecoderSpec->SetKeepHistory(b > 0); lzxDecoderSpec->SetKeepHistory(b > 0);
HRESULT res = lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL);
size_t compressedSizeT = (size_t)compressedSize;
if (compressedSizeT != compressedSize)
throw 2;
packBuf.AllocAtLeast(compressedSizeT);
HRESULT res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
if (res == S_OK)
{
lzxDecoderSpec->KeepHistoryForNext = true;
res = lzxDecoderSpec->Code(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;
if (res == S_OK)
res = WriteStream(chmFolderOutStream,
lzxDecoderSpec->GetUnpackData(),
lzxDecoderSpec->GetUnpackSize());
}
if (res != S_OK) if (res != S_OK)
{ {
if (res != S_FALSE) if (res != S_FALSE)
@@ -714,6 +777,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
RINOK(chmFolderOutStream->FlushCorrupted(unPackSize)); RINOK(chmFolderOutStream->FlushCorrupted(unPackSize));
} }
currentTotalSize += folderSize; currentTotalSize += folderSize;
if (folderIndex == lastFolderIndex) if (folderIndex == lastFolderIndex)
break; break;

View File

@@ -4,6 +4,8 @@
// #include <stdio.h> // #include <stdio.h>
#include "../../../../C/CpuArch.h"
#include "../../../Common/IntToString.h" #include "../../../Common/IntToString.h"
#include "../../../Common/UTFConvert.h" #include "../../../Common/UTFConvert.h"
@@ -11,6 +13,10 @@
#include "ChmIn.h" #include "ChmIn.h"
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
namespace NArchive { namespace NArchive {
namespace NChm { namespace NChm {
@@ -168,38 +174,36 @@ Byte CInArchive::ReadByte()
void CInArchive::Skip(size_t size) void CInArchive::Skip(size_t size)
{ {
while (size-- != 0) if (_inBuffer.Skip(size) != size)
ReadByte(); throw CEnexpectedEndException();
} }
void CInArchive::ReadBytes(Byte *data, UInt32 size) void CInArchive::ReadBytes(Byte *data, UInt32 size)
{ {
for (UInt32 i = 0; i < size; i++) if (_inBuffer.ReadBytes(data, size) != size)
data[i] = ReadByte(); throw CEnexpectedEndException();
} }
UInt16 CInArchive::ReadUInt16() UInt16 CInArchive::ReadUInt16()
{ {
UInt16 val = 0; Byte b0, b1;
for (int i = 0; i < 2; i++) if (!_inBuffer.ReadByte(b0)) throw CEnexpectedEndException();
val |= ((UInt16)(ReadByte()) << (8 * i)); if (!_inBuffer.ReadByte(b1)) throw CEnexpectedEndException();
return val; return (UInt16)(((UInt16)b1 << 8) | b0);
} }
UInt32 CInArchive::ReadUInt32() UInt32 CInArchive::ReadUInt32()
{ {
UInt32 val = 0; Byte p[4];
for (int i = 0; i < 4; i++) ReadBytes(p, 4);
val |= ((UInt32)(ReadByte()) << (8 * i)); return Get32(p);
return val;
} }
UInt64 CInArchive::ReadUInt64() UInt64 CInArchive::ReadUInt64()
{ {
UInt64 val = 0; Byte p[8];
for (int i = 0; i < 8; i++) ReadBytes(p, 8);
val |= ((UInt64)(ReadByte()) << (8 * i)); return Get64(p);
return val;
} }
UInt64 CInArchive::ReadEncInt() UInt64 CInArchive::ReadEncInt()
@@ -227,15 +231,10 @@ void CInArchive::ReadGUID(GUID &g)
void CInArchive::ReadString(unsigned size, AString &s) void CInArchive::ReadString(unsigned size, AString &s)
{ {
s.Empty(); s.Empty();
while (size-- != 0) if (size != 0)
{ {
char c = (char)ReadByte(); ReadBytes((Byte *)s.GetBuf(size), size);
if (c == 0) s.ReleaseBuf_CalcLen(size);
{
Skip(size);
return;
}
s += c;
} }
} }
@@ -380,6 +379,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
ReadUInt32(); // Chunk number of next listing chunk when reading ReadUInt32(); // Chunk number of next listing chunk when reading
// directory in sequence (-1 if this is the last listing chunk) // directory in sequence (-1 if this is the last listing chunk)
unsigned numItems = 0; unsigned numItems = 0;
for (;;) for (;;)
{ {
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
@@ -391,9 +391,16 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
RINOK(ReadDirEntry(database)); RINOK(ReadDirEntry(database));
numItems++; numItems++;
} }
Skip(quickrefLength - 2); Skip(quickrefLength - 2);
if (ReadUInt16() != numItems)
return S_FALSE; unsigned rrr = ReadUInt16();
if (rrr != numItems)
{
// Lazarus 9-26-2 chm contains 0 here.
if (rrr != 0)
return S_FALSE;
}
} }
else else
Skip(dirChunkSize - 4); Skip(dirChunkSize - 4);
@@ -649,7 +656,7 @@ static AString GetSectionPrefix(const AString &name)
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
static int CompareFiles(const int *p1, const int *p2, void *param) static int CompareFiles(const unsigned *p1, const unsigned *p2, void *param)
{ {
const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param; const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
const CItem &item1 = items[*p1]; const CItem &item1 = items[*p1];
@@ -660,13 +667,15 @@ static int CompareFiles(const int *p1, const int *p2, void *param)
return -1; return -1;
if (isDir2) if (isDir2)
{ {
if (isDir1) if (!isDir1)
return MyCompare(*p1, *p2); return 1;
return 1; }
else
{
RINOZ(MyCompare(item1.Section, item2.Section));
RINOZ(MyCompare(item1.Offset, item2.Offset));
RINOZ(MyCompare(item1.Size, item2.Size));
} }
RINOZ(MyCompare(item1.Section, item2.Section));
RINOZ(MyCompare(item1.Offset, item2.Offset));
RINOZ(MyCompare(item1.Size, item2.Size));
return MyCompare(*p1, *p2); return MyCompare(*p1, *p2);
} }
@@ -709,6 +718,27 @@ bool CFilesDatabase::Check()
return true; return true;
} }
bool CFilesDatabase::CheckSectionRefs()
{
FOR_VECTOR (i, Indices)
{
const CItem &item = Items[Indices[i]];
if (item.Section == 0 || item.IsDir())
continue;
if (item.Section >= Sections.Size())
return false;
}
return true;
}
static int inline GetLog(UInt32 num)
{
for (int i = 0; i < 32; i++)
if (((UInt32)1 << i) == num)
return i;
return -1;
}
HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
{ {
{ {
@@ -716,7 +746,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, kNameList)); RINOK(DecompressStream(inStream, database, kNameList));
/* UInt16 length = */ ReadUInt16(); /* UInt16 length = */ ReadUInt16();
UInt16 numSections = ReadUInt16(); UInt16 numSections = ReadUInt16();
for (int i = 0; i < numSections; i++) for (unsigned i = 0; i < numSections; i++)
{ {
CSectionInfo section; CSectionInfo section;
UInt16 nameLen = ReadUInt16(); UInt16 nameLen = ReadUInt16();
@@ -730,10 +760,10 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
} }
} }
unsigned i; unsigned si;
for (i = 1; i < database.Sections.Size(); i++) for (si = 1; si < database.Sections.Size(); si++)
{ {
CSectionInfo &section = database.Sections[i]; CSectionInfo &section = database.Sections[si];
AString sectionPrefix = GetSectionPrefix(section.Name); AString sectionPrefix = GetSectionPrefix(section.Name);
{ {
// Content // Content
@@ -751,10 +781,10 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList)); RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));
if ((_chunkSize & 0xF) != 0) if ((_chunkSize & 0xF) != 0)
return S_FALSE; return S_FALSE;
int numGuids = (int)(_chunkSize / 0x10); unsigned numGuids = (unsigned)(_chunkSize / 0x10);
if (numGuids < 1) if (numGuids < 1)
return S_FALSE; return S_FALSE;
for (int i = 0; i < numGuids; i++) for (unsigned i = 0; i < numGuids; i++)
{ {
CMethodInfo method; CMethodInfo method;
ReadGUID(method.Guid); ReadGUID(method.Guid);
@@ -771,6 +801,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
{ {
// Control Data // Control Data
RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData)); RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData));
FOR_VECTOR (mi, section.Methods) FOR_VECTOR (mi, section.Methods)
{ {
CMethodInfo &method = section.Methods[mi]; CMethodInfo &method = section.Methods[mi];
@@ -785,27 +816,25 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
li.Version = ReadUInt32(); li.Version = ReadUInt32();
if (li.Version != 2 && li.Version != 3) if (li.Version != 2 && li.Version != 3)
return S_FALSE; return S_FALSE;
li.ResetInterval = ReadUInt32();
li.WindowSize = ReadUInt32(); {
// There is bug in VC6, if we use function call as parameter for inline function
UInt32 val32 = ReadUInt32();
int n = GetLog(val32);
if (n < 0 || n > 16)
return S_FALSE;
li.ResetIntervalBits = n;
}
{
UInt32 val32 = ReadUInt32();
int n = GetLog(val32);
if (n < 0 || n > 16)
return S_FALSE;
li.WindowSizeBits = n;
}
li.CacheSize = ReadUInt32(); li.CacheSize = ReadUInt32();
if (
li.ResetInterval != 1 &&
li.ResetInterval != 2 &&
li.ResetInterval != 4 &&
li.ResetInterval != 8 &&
li.ResetInterval != 16 &&
li.ResetInterval != 32 &&
li.ResetInterval != 64)
return S_FALSE;
if (
li.WindowSize != 1 &&
li.WindowSize != 2 &&
li.WindowSize != 4 &&
li.WindowSize != 8 &&
li.WindowSize != 16 &&
li.WindowSize != 32 &&
li.WindowSize != 64)
return S_FALSE;
numDWORDS -= 5; numDWORDS -= 5;
while (numDWORDS-- != 0) while (numDWORDS-- != 0)
ReadUInt32(); ReadUInt32();
@@ -835,6 +864,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, transformPrefix + RINOK(DecompressStream(inStream, database, transformPrefix +
method.GetGuidString() + kResetTable)); method.GetGuidString() + kResetTable));
CResetTable &rt = method.LzxInfo.ResetTable; CResetTable &rt = method.LzxInfo.ResetTable;
if (_chunkSize < 4) if (_chunkSize < 4)
{ {
if (_chunkSize != 0) if (_chunkSize != 0)
@@ -844,7 +874,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
return S_FALSE; return S_FALSE;
rt.UncompressedSize = 0; rt.UncompressedSize = 0;
rt.CompressedSize = 0; rt.CompressedSize = 0;
rt.BlockSize = 0; // rt.BlockSize = 0;
} }
else else
{ {
@@ -852,18 +882,45 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
if (ver != 2 && ver != 3) if (ver != 2 && ver != 3)
return S_FALSE; return S_FALSE;
UInt32 numEntries = ReadUInt32(); UInt32 numEntries = ReadUInt32();
if (ReadUInt32() != 8) // Size of table entry (bytes) const unsigned kEntrySize = 8;
if (ReadUInt32() != kEntrySize)
return S_FALSE; return S_FALSE;
if (ReadUInt32() != 0x28) // Len of table header const unsigned kRtHeaderSize = 4 * 4 + 8 * 3;
if (ReadUInt32() != kRtHeaderSize)
return S_FALSE; return S_FALSE;
if (kRtHeaderSize + kEntrySize * (UInt64)numEntries != _chunkSize)
return S_FALSE;
rt.UncompressedSize = ReadUInt64(); rt.UncompressedSize = ReadUInt64();
rt.CompressedSize = ReadUInt64(); rt.CompressedSize = ReadUInt64();
rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below UInt64 blockSize = ReadUInt64();
if (rt.BlockSize != 0x8000) if (blockSize != kBlockSize)
return S_FALSE; return S_FALSE;
UInt64 numBlocks = (rt.UncompressedSize + kBlockSize + 1) / kBlockSize;
if (numEntries != numBlocks &&
numEntries != numBlocks + 1)
return S_FALSE;
rt.ResetOffsets.ClearAndReserve(numEntries); rt.ResetOffsets.ClearAndReserve(numEntries);
for (UInt32 i = 0; i < numEntries; i++) for (UInt32 i = 0; i < numEntries; i++)
rt.ResetOffsets.AddInReserved(ReadUInt64()); {
UInt64 v = ReadUInt64();
if (i != 0 && v < rt.ResetOffsets[i - 1])
return S_FALSE;
rt.ResetOffsets.AddInReserved(v);
}
if (numEntries != 0)
if (rt.ResetOffsets[0] != 0)
return S_FALSE;
if (numEntries == numBlocks + 1)
{
// Lazarus 9-26-2 chm contains additional entty
if (rt.ResetOffsets.Back() != rt.CompressedSize)
return S_FALSE;
}
} }
} }
} }
@@ -896,14 +953,16 @@ HRESULT CInArchive::Open2(IInStream *inStream,
if (_help2) if (_help2)
{ {
const int kSignatureSize = 8; const unsigned kSignatureSize = 8;
UInt64 signature = ((UInt64)kSignature_ITLS << 32)| kSignature_ITOL; const UInt64 signature = ((UInt64)kSignature_ITLS << 32) | kSignature_ITOL;
UInt64 limit = 1 << 18; UInt64 limit = 1 << 18;
if (searchHeaderSizeLimit) if (searchHeaderSizeLimit)
if (limit > *searchHeaderSizeLimit) if (limit > *searchHeaderSizeLimit)
limit = *searchHeaderSizeLimit; limit = *searchHeaderSizeLimit;
UInt64 val = 0; UInt64 val = 0;
for (;;) for (;;)
{ {
Byte b; Byte b;
@@ -919,6 +978,7 @@ HRESULT CInArchive::Open2(IInStream *inStream,
return S_FALSE; return S_FALSE;
} }
} }
database.StartPosition += _inBuffer.GetProcessedSize() - kSignatureSize; database.StartPosition += _inBuffer.GetProcessedSize() - kSignatureSize;
RINOK(OpenHelp2(inStream, database)); RINOK(OpenHelp2(inStream, database));
if (database.NewFormat) if (database.NewFormat)
@@ -948,6 +1008,8 @@ HRESULT CInArchive::Open2(IInStream *inStream,
return S_OK; return S_OK;
} }
RINOK(res); RINOK(res);
if (!database.CheckSectionRefs())
HeadersError = true;
database.LowLevel = false; database.LowLevel = false;
} }
catch(...) catch(...)

View File

@@ -36,12 +36,13 @@ struct CItem
bool IsDir() const bool IsDir() const
{ {
if (Name.Len() == 0) if (Name.IsEmpty())
return false; return false;
return (Name.Back() == '/'); return (Name.Back() == '/');
} }
}; };
struct CDatabase struct CDatabase
{ {
UInt64 StartPosition; UInt64 StartPosition;
@@ -73,11 +74,14 @@ struct CDatabase
} }
}; };
const UInt32 kBlockSize = 1 << 15;
struct CResetTable struct CResetTable
{ {
UInt64 UncompressedSize; UInt64 UncompressedSize;
UInt64 CompressedSize; UInt64 CompressedSize;
UInt64 BlockSize; // unsigned BlockSizeBits;
CRecordVector<UInt64> ResetOffsets; CRecordVector<UInt64> ResetOffsets;
bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
@@ -91,39 +95,41 @@ struct CResetTable
size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos; size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos;
return true; return true;
} }
bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
{ {
return GetCompressedSizeOfBlocks(blockIndex, 1, size); return GetCompressedSizeOfBlocks(blockIndex, 1, size);
} }
UInt64 GetNumBlocks(UInt64 size) const UInt64 GetNumBlocks(UInt64 size) const
{ {
return (size + BlockSize - 1) / BlockSize; return (size + kBlockSize - 1) / kBlockSize;
} }
}; };
struct CLzxInfo struct CLzxInfo
{ {
UInt32 Version; UInt32 Version;
UInt32 ResetInterval;
UInt32 WindowSize; unsigned ResetIntervalBits;
unsigned WindowSizeBits;
UInt32 CacheSize; UInt32 CacheSize;
CResetTable ResetTable; CResetTable ResetTable;
UInt32 GetNumDictBits() const unsigned GetNumDictBits() const
{ {
if (Version == 2 || Version == 3) if (Version == 2 || Version == 3)
{ return 15 + WindowSizeBits;
for (unsigned i = 0; i <= 31; i++)
if (((UInt32)1 << i) >= WindowSize)
return 15 + i;
}
return 0; return 0;
} }
UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; } UInt64 GetFolderSize() const { return kBlockSize << ResetIntervalBits; }
UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); } UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); } UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; } UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; }
bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
{ {
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
@@ -132,24 +138,28 @@ struct CLzxInfo
offset = ResetTable.ResetOffsets[(unsigned)blockIndex]; offset = ResetTable.ResetOffsets[(unsigned)blockIndex];
return true; return true;
} }
bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
{ {
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size); return ResetTable.GetCompressedSizeOfBlocks(blockIndex, (UInt32)1 << ResetIntervalBits, size);
} }
}; };
struct CMethodInfo struct CMethodInfo
{ {
GUID Guid; GUID Guid;
CByteBuffer ControlData; CByteBuffer ControlData;
CLzxInfo LzxInfo; CLzxInfo LzxInfo;
bool IsLzx() const; bool IsLzx() const;
bool IsDes() const; bool IsDes() const;
AString GetGuidString() const; AString GetGuidString() const;
UString GetName() const; UString GetName() const;
}; };
struct CSectionInfo struct CSectionInfo
{ {
UInt64 Offset; UInt64 Offset;
@@ -167,27 +177,33 @@ class CFilesDatabase: public CDatabase
{ {
public: public:
bool LowLevel; bool LowLevel;
CRecordVector<int> Indices; CUIntVector Indices;
CObjectVector<CSectionInfo> Sections; CObjectVector<CSectionInfo> Sections;
UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; } UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; } UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }
UInt64 GetFolder(int fileIndex) const UInt64 GetFolder(unsigned fileIndex) const
{ {
const CItem &item = Items[Indices[fileIndex]]; const CItem &item = Items[Indices[fileIndex]];
const CSectionInfo &section = Sections[(int)item.Section]; if (item.Section < Sections.Size())
if (section.IsLzx()) {
return section.Methods[0].LzxInfo.GetFolder(item.Offset); const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset);
}
return 0; return 0;
} }
UInt64 GetLastFolder(int fileIndex) const UInt64 GetLastFolder(unsigned fileIndex) const
{ {
const CItem &item = Items[Indices[fileIndex]]; const CItem &item = Items[Indices[fileIndex]];
const CSectionInfo &section = Sections[(int)item.Section]; if (item.Section < Sections.Size())
if (section.IsLzx()) {
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1); const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
}
return 0; return 0;
} }
@@ -203,19 +219,13 @@ public:
CDatabase::Clear(); CDatabase::Clear();
HighLevelClear(); HighLevelClear();
} }
void SetIndices(); void SetIndices();
void Sort(); void Sort();
bool Check(); bool Check();
bool CheckSectionRefs();
}; };
/*
class CProgressVirt
{
public:
STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;
STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
};
*/
class CInArchive class CInArchive
{ {

View File

@@ -167,7 +167,7 @@ HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSiz
{ {
UpdatePhySize(((UInt64)sid + 2) << sectorSizeBits); UpdatePhySize(((UInt64)sid + 2) << sectorSizeBits);
RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL)); RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL));
return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits); return ReadStream_FALSE(inStream, buf, (size_t)1 << sectorSizeBits);
} }
HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest) HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest)
@@ -433,9 +433,9 @@ HRESULT CDatabase::Open(IInStream *inStream)
SectorSizeBits = sectorSizeBits; SectorSizeBits = sectorSizeBits;
MiniSectorSizeBits = miniSectorSizeBits; MiniSectorSizeBits = miniSectorSizeBits;
if (sectorSizeBits > 28 || if (sectorSizeBits > 24 ||
sectorSizeBits < 7 || sectorSizeBits < 7 ||
miniSectorSizeBits > 28 || miniSectorSizeBits > 24 ||
miniSectorSizeBits < 2 || miniSectorSizeBits < 2 ||
miniSectorSizeBits > sectorSizeBits) miniSectorSizeBits > sectorSizeBits)
return S_FALSE; return S_FALSE;
@@ -571,34 +571,41 @@ HRESULT CDatabase::Open(IInStream *inStream)
RINOK(AddNode(-1, root.SonDid)); RINOK(AddNode(-1, root.SonDid));
unsigned numCabs = 0; unsigned numCabs = 0;
FOR_VECTOR (i, Refs) FOR_VECTOR (i, Refs)
{ {
const CItem &item = Items[Refs[i].Did]; const CItem &item = Items[Refs[i].Did];
if (item.IsDir() || numCabs > 1) if (item.IsDir() || numCabs > 1)
continue; continue;
bool isMsiName; bool isMsiName;
UString msiName = ConvertName(item.Name, isMsiName); const UString msiName = ConvertName(item.Name, isMsiName);
if (isMsiName) if (isMsiName && !msiName.IsEmpty())
{ {
// bool isThereExt = (msiName.Find(L'.') >= 0);
bool isMsiSpec = (msiName[0] == k_Msi_SpecChar);
if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
|| msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) || !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")
// || !isMsiSpec && !isThereExt
)
{ {
numCabs++; numCabs++;
MainSubfile = i; MainSubfile = i;
} }
} }
} }
if (numCabs > 1) if (numCabs > 1)
MainSubfile = -1; MainSubfile = -1;
{ {
FOR_VECTOR(t, Items) FOR_VECTOR (t, Items)
{ {
Update_PhySize_WithItem(t); Update_PhySize_WithItem(t);
} }
} }
{ {
FOR_VECTOR(t, Items) FOR_VECTOR (t, Items)
{ {
const CItem &item = Items[t]; const CItem &item = Items[t];
@@ -739,7 +746,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return S_OK; return S_OK;
UInt32 i; UInt32 i;
UInt64 totalSize = 0; UInt64 totalSize = 0;
for(i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did]; const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did];
if (!item.IsDir()) if (!item.IsDir())

View File

@@ -1,15 +0,0 @@
// CrossThreadProgress.cpp
#include "StdAfx.h"
#include "CrossThreadProgress.h"
STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
InSize = inSize;
OutSize = outSize;
ProgressEvent.Set();
WaitEvent.Lock();
return Result;
}

View File

@@ -1,37 +0,0 @@
// CrossThreadProgress.h
#ifndef __CROSSTHREADPROGRESS_H
#define __CROSSTHREADPROGRESS_H
#include "../../ICoder.h"
#include "../../../Windows/Synchronization.h"
#include "../../../Common/MyCom.h"
class CCrossThreadProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
public:
const UInt64 *InSize;
const UInt64 *OutSize;
HRESULT Result;
NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
NWindows::NSynchronization::CAutoResetEvent WaitEvent;
HRes Create()
{
RINOK(ProgressEvent.CreateIfNotCreated());
return WaitEvent.CreateIfNotCreated();
}
void Init()
{
ProgressEvent.Reset();
WaitEvent.Reset();
}
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
#endif

View File

@@ -81,7 +81,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
} }
UInt32 number; UInt32 number;
int index = ParseStringToUInt32(name, number); unsigned index = ParseStringToUInt32(name, number);
UString realName = name.Ptr(index); UString realName = name.Ptr(index);
if (index == 0) if (index == 0)
{ {
@@ -147,7 +147,9 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PR
#endif #endif
} }
else else
return ParseMethodFromPROPVARIANT(names[i], value); {
RINOK(ParseMethodFromPROPVARIANT(names[i], value));
}
} }
return S_OK; return S_OK;
} }

View File

@@ -119,9 +119,9 @@ HRESULT COutVolumeStream::Flush()
/* /*
STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
if(processedSize != NULL) if (processedSize)
*processedSize = 0; *processedSize = 0;
while(size > 0) while (size > 0)
{ {
if (_streamIndex >= Streams.Size()) if (_streamIndex >= Streams.Size())
{ {
@@ -157,7 +157,7 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce
_absPos += realProcessed; _absPos += realProcessed;
if (_absPos > _length) if (_absPos > _length)
_length = _absPos; _length = _absPos;
if(processedSize != NULL) if (processedSize)
*processedSize += realProcessed; *processedSize += realProcessed;
if (subStream.Pos == subStream.Size) if (subStream.Pos == subStream.Size)
{ {

View File

@@ -5,6 +5,7 @@
#include "../../../C/CpuArch.h" #include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/MyLinux.h"
#include "../../Common/StringConvert.h" #include "../../Common/StringConvert.h"
#include "../../Common/StringToInt.h" #include "../../Common/StringToInt.h"
#include "../../Common/UTFConvert.h" #include "../../Common/UTFConvert.h"
@@ -121,7 +122,7 @@ struct CItem
bool IsBin() const { return Type == k_Type_BinLe || Type == k_Type_BinBe; } bool IsBin() const { return Type == k_Type_BinLe || Type == k_Type_BinBe; }
bool IsCrcFormat() const { return Type == k_Type_HexCrc; } bool IsCrcFormat() const { return Type == k_Type_HexCrc; }
bool IsDir() const { return (Mode & 0170000) == 0040000; } bool IsDir() const { return MY_LIN_S_ISDIR(Mode); }
bool IsTrailer() const { return strcmp(Name, kName_TRAILER) == 0; } bool IsTrailer() const { return strcmp(Name, kName_TRAILER) == 0; }
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
}; };

View File

@@ -8,6 +8,7 @@
#include "../../../C/LzmaDec.h" #include "../../../C/LzmaDec.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/MyLinux.h"
#include "../../Common/StringConvert.h" #include "../../Common/StringConvert.h"
#include "../../Windows/PropVariantUtils.h" #include "../../Windows/PropVariantUtils.h"
@@ -98,7 +99,7 @@ struct CNode
#define Get32(p) (be ? GetBe32(p) : GetUi32(p)) #define Get32(p) (be ? GetBe32(p) : GetUi32(p))
static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; } static bool IsDir(const Byte *p, bool be) { return MY_LIN_S_ISDIR(GetMode(p, be)); }
static UInt32 GetSize(const Byte *p, bool be) static UInt32 GetSize(const Byte *p, bool be)
{ {
@@ -146,7 +147,7 @@ struct CHeader
{ {
if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0) if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0)
return false; return false;
switch(GetUi32(p)) switch (GetUi32(p))
{ {
case 0x28CD3D45: be = false; break; case 0x28CD3D45: be = false; break;
case 0x453DCD28: be = true; break; case 0x453DCD28: be = true; break;
@@ -354,7 +355,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
if (!_h.IsVer2()) if (!_h.IsVer2())
{ {
FOR_VECTOR(i, _items) FOR_VECTOR (i, _items)
{ {
const CItem &item = _items[i]; const CItem &item = _items[i];
const Byte *p = _data + item.Offset; const Byte *p = _data + item.Offset;
@@ -530,7 +531,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const Byte *p = _data + item.Offset; const Byte *p = _data + item.Offset;
bool be = _h.be; bool be = _h.be;
bool isDir = IsDir(p, be); bool isDir = IsDir(p, be);
switch(propID) switch (propID)
{ {
case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
case kpidIsDir: prop = isDir; break; case kpidIsDir: prop = isDir; break;
@@ -582,13 +583,13 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
} }
} }
bool be = _h.be; const bool be = _h.be;
const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4); const Byte *p2 = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4)); const UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p2 - 4));
UInt32 end = Get32(p); const UInt32 end = Get32(p2);
if (end < start || end > _size) if (end < start || end > _size)
return S_FALSE; return S_FALSE;
UInt32 inSize = end - start; const UInt32 inSize = end - start;
if (_method == k_Flags_Method_LZMA) if (_method == k_Flags_Method_LZMA)
{ {
@@ -660,10 +661,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> progress = lps; CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
lps->InSize = totalPackSize; lps->InSize = totalPackSize;
@@ -701,20 +698,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int res = NExtract::NOperationResult::kDataError; int res = NExtract::NOperationResult::kDataError;
{ {
CMyComPtr<ISequentialInStream> inSeqStream; CMyComPtr<ISequentialInStream> inSeqStream;
CMyComPtr<IInStream> inStream;
HRESULT hres = GetStream(index, &inSeqStream); HRESULT hres = GetStream(index, &inSeqStream);
if (inSeqStream)
inSeqStream.QueryInterface(IID_IInStream, &inStream);
if (hres == E_OUTOFMEMORY) if (hres == E_OUTOFMEMORY)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (hres == S_FALSE || !inStream) if (hres == S_FALSE || !inSeqStream)
res = NExtract::NOperationResult::kUnsupportedMethod; res = NExtract::NOperationResult::kUnsupportedMethod;
else else
{ {
RINOK(hres); RINOK(hres);
if (inStream)
{ {
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); hres = copyCoder->Code(inSeqStream, outStream, NULL, NULL, progress);
if (hres == S_OK) if (hres == S_OK)
{ {
if (copyCoderSpec->TotalSize == curSize) if (copyCoderSpec->TotalSize == curSize)
@@ -729,6 +722,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
RINOK(extractCallback->SetOperationResult(res)); RINOK(extractCallback->SetOperationResult(res));
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
} }

View File

@@ -26,6 +26,7 @@ HINSTANCE g_hInstance;
#define NT_CHECK_FAIL_ACTION return FALSE; #define NT_CHECK_FAIL_ACTION return FALSE;
#ifdef _WIN32
extern "C" extern "C"
BOOL WINAPI DllMain( BOOL WINAPI DllMain(
#ifdef UNDER_CE #ifdef UNDER_CE
@@ -49,6 +50,7 @@ BOOL WINAPI DllMain(
*/ */
return TRUE; return TRUE;
} }
#endif
DEFINE_GUID(CLSID_CArchiveHandler, DEFINE_GUID(CLSID_CArchiveHandler,
k_7zip_GUID_Data1, k_7zip_GUID_Data1,

View File

@@ -34,48 +34,35 @@
static const Byte k_Base64Table[256] = static const Byte k_Base64Table[256] =
{ {
64,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,
77,77,77,77,77,77,77,77,77,77,77,62,77,64,77,63,52,53,54,55,56,57,58,59,60,61,77,77,77,77,77,77, 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,
77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
}; };
static Byte *Base64ToBin(Byte *dest, const char *src) static Byte *Base64ToBin(Byte *dest, const char *src)
{ {
UInt32 val = 1; UInt32 val = 1;
UInt32 c = k_Base64Table[(Byte)(*src++)];
for (;;) for (;;)
{ {
/* UInt32 c = k_Base64Table[(Byte)(*src++)];
UInt32 c = (Byte)(*src++);
if (c >= 'A')
{
if (c <= 'Z') c -= 'A';
else if (c >= 'a' && c <= 'z') c -= 'a' - 26;
else continue;
}
else if (c >= '0')
{
if (c <= '9') c += 52 - '0';
else if (c == '=') break;
else continue;
}
else if (c == '+') c = 62;
else if (c == '/') c = 63;
else if (c == 0) break;
else continue;
*/
// UInt32 c = k_Base64Table[(Byte)(*src++)];
if (c < 64) if (c < 64)
{ {
val = (val << 6) | c; val = (val << 6) | c;
c = k_Base64Table[(Byte)(*src++)];
if ((val & ((UInt32)1 << 24)) == 0) if ((val & ((UInt32)1 << 24)) == 0)
continue; continue;
dest[0] = (Byte)(val >> 16); dest[0] = (Byte)(val >> 16);
@@ -85,19 +72,41 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
val = 1; val = 1;
continue; continue;
} }
if (c == 64)
if (c == 65) // space
continue;
if (c == 64) // '='
break; break;
c = k_Base64Table[(Byte)(*src++)];
if (c == 66 && val == 1) // end of string
return dest;
return NULL;
} }
if (val >= ((UInt32)1 << 12)) if (val < (1 << 12))
return NULL;
if (val & (1 << 18))
{ {
if (val >= ((UInt32)1 << 18)) *dest++ = (Byte)(val >> 10);
*dest++ = (Byte)(val >> 16); *dest++ = (Byte)(val >> 2);
*dest++ = (Byte)(val);
} }
else if (k_Base64Table[(Byte)(*src++)] != 64) // '='
return NULL;
else
*dest++ = (Byte)(val >> 4);
return dest; for (;;)
{
Byte c = k_Base64Table[(Byte)(*src++)];
if (c == 65) // space
continue;
if (c == 66) // end of string
return dest;
return NULL;
}
} }
@@ -545,8 +554,8 @@ HRESULT CHandler::Open2(IInStream *stream)
CChecksum masterChecksum; CChecksum masterChecksum;
masterChecksum.Parse(buf + 0x160); masterChecksum.Parse(buf + 0x160);
// UInt32 imageVariant = Get32(buf + 0x1E8); // UInt32 imageVariant = Get32(buf + 0x1E8);
// UInt64 numSectors = Get64(buf + 0x1EC); // UInt64 numSectors = Get64(buf + 0x1EC);
// Byte reserved[0x12] // Byte reserved[0x12]
const UInt32 RSRC_HEAD_SIZE = 0x100; const UInt32 RSRC_HEAD_SIZE = 0x100;
@@ -720,7 +729,13 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE; return S_FALSE;
destLen = dataString->Len() / 4 * 3 + 4; destLen = dataString->Len() / 4 * 3 + 4;
rawBuf.Alloc(destLen); rawBuf.Alloc(destLen);
destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf); {
const Byte *endPtr = Base64ToBin(rawBuf, *dataString);
if (!endPtr)
return S_FALSE;
destLen = (unsigned)(endPtr - rawBuf);
}
#ifdef DMG_SHOW_RAW #ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew(); CExtraFile &extra = _extras.AddNew();
{ {

View File

@@ -156,7 +156,7 @@ bool CHeader::Parse(const Byte *p)
#define PT_PHDR 6 #define PT_PHDR 6
static const char *g_SegnmentTypes[] = static const char * const g_SegnmentTypes[] =
{ {
"Unused", "Unused",
"Loadable segment", "Loadable segment",
@@ -226,25 +226,25 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
// Section types // Section types
#define SHT_NULL 0 #define SHT_NULL 0
#define SHT_PROGBITS 1 #define SHT_PROGBITS 1
#define SHT_SYMTAB 2 #define SHT_SYMTAB 2
#define SHT_STRTAB 3 #define SHT_STRTAB 3
#define SHT_RELA 4 #define SHT_RELA 4
#define SHT_HASH 5 #define SHT_HASH 5
#define SHT_DYNAMIC 6 #define SHT_DYNAMIC 6
#define SHT_NOTE 7 #define SHT_NOTE 7
#define SHT_NOBITS 8 #define SHT_NOBITS 8
#define SHT_REL 9 #define SHT_REL 9
#define SHT_SHLIB 10 #define SHT_SHLIB 10
#define SHT_DYNSYM 11 #define SHT_DYNSYM 11
#define SHT_UNKNOWN12 12 #define SHT_UNKNOWN12 12
#define SHT_UNKNOWN13 13 #define SHT_UNKNOWN13 13
#define SHT_INIT_ARRAY 14 #define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15 #define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16 #define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17 #define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18 #define SHT_SYMTAB_SHNDX 18
static const CUInt32PCharPair g_SectTypes[] = static const CUInt32PCharPair g_SectTypes[] =
@@ -554,13 +554,31 @@ static const CUInt32PCharPair g_OS[] =
{ 255, "Standalone" } { 255, "Standalone" }
}; };
#define ET_NONE 0 #define k_Machine_ARM 40
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
static const char *g_Types[] = /*
#define EF_ARM_ABIMASK 0xFF000000
#define EF_ARM_BE8 0x00800000
#define EF_ARM_GCCMASK 0x00400FFF
#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
#define EF_ARM_ABI_FLOAT_HARD 0x00000400
*/
static const CUInt32PCharPair g_ARM_Flags[] =
{
{ 9, "SF" },
{ 10, "HF" },
{ 23, "BE8" }
};
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
static const char * const g_Types[] =
{ {
"None", "None",
"Relocatable file", "Relocatable file",
@@ -569,6 +587,9 @@ static const char *g_Types[] =
"Core file" "Core file"
}; };
class CHandler: class CHandler:
public IInArchive, public IInArchive,
public IArchiveAllowTail, public IArchiveAllowTail,
@@ -632,7 +653,7 @@ enum
kpidInfoSection kpidInfoSection
}; };
static const STATPROPSTG kProps[] = static const CStatProp kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR }, { NULL, kpidPath, VT_BSTR },
{ NULL, kpidSize, VT_UI8 }, { NULL, kpidSize, VT_UI8 },
@@ -641,8 +662,8 @@ static const STATPROPSTG kProps[] =
{ NULL, kpidVa, VT_UI8 }, { NULL, kpidVa, VT_UI8 },
{ NULL, kpidType, VT_BSTR }, { NULL, kpidType, VT_BSTR },
{ NULL, kpidCharacts, VT_BSTR } { NULL, kpidCharacts, VT_BSTR }
, { (LPOLESTR)L"Link Section", kpidLinkSection, VT_BSTR} , { "Link Section", kpidLinkSection, VT_BSTR}
, { (LPOLESTR)L"Info Section", kpidInfoSection, VT_BSTR} , { "Info Section", kpidInfoSection, VT_BSTR}
}; };
IMP_IInArchive_Props_WITH_NAME IMP_IInArchive_Props_WITH_NAME
@@ -659,7 +680,29 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidBit64: if (_header.Mode64) prop = _header.Mode64; break; case kpidBit64: if (_header.Mode64) prop = _header.Mode64; break;
case kpidBigEndian: if (_header.Be) prop = _header.Be; break; case kpidBigEndian: if (_header.Be) prop = _header.Be; break;
case kpidShortComment: case kpidShortComment:
case kpidCpu: PAIR_TO_PROP(g_Machines, _header.Machine, prop); break;
case kpidCpu:
{
AString s = TypePairToString(g_Machines, ARRAY_SIZE(g_Machines), _header.Machine);
UInt32 flags = _header.Flags;
if (flags != 0)
{
char sz[16];
s.Add_Space();
if (_header.Machine == k_Machine_ARM)
{
s += FlagsToString(g_ARM_Flags, ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1));
s += " ABI:";
ConvertUInt32ToString(flags >> 24, sz);
}
else
ConvertUInt32ToHex(flags, sz);
s += sz;
}
prop = s;
break;
}
case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break; case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break;
case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break;
case kpidExtension: case kpidExtension:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -133,15 +133,23 @@ bool CHeader::Parse(const Byte *p)
default: return false; default: return false;
} }
{ {
int s = GetLog(Get16(p + 11)); {
if (s < 9 || s > 12) UInt32 val32 = Get16(p + 11);
return false; int s = GetLog(val32);
SectorSizeLog = (Byte)s; if (s < 9 || s > 12)
s = GetLog(p[13]); return false;
if (s < 0) SectorSizeLog = (Byte)s;
return false; }
SectorsPerClusterLog = (Byte)s; {
UInt32 val32 = p[13];
int s = GetLog(val32);
if (s < 0)
return false;
SectorsPerClusterLog = (Byte)s;
}
ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog); ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog);
if (ClusterSizeLog > 24)
return false;
} }
NumReservedSectors = Get16(p + 14); NumReservedSectors = Get16(p + 14);
@@ -152,10 +160,13 @@ bool CHeader::Parse(const Byte *p)
if (NumFats < 1 || NumFats > 4) if (NumFats < 1 || NumFats > 4)
return false; return false;
// we also support images that contain 0 in offset field.
bool isOkOffset = (codeOffset == 0 || (p[0] == 0xEB && p[1] == 0));
UInt16 numRootDirEntries = Get16(p + 17); UInt16 numRootDirEntries = Get16(p + 17);
if (numRootDirEntries == 0) if (numRootDirEntries == 0)
{ {
if (codeOffset < 90) if (codeOffset < 90 && !isOkOffset)
return false; return false;
NumFatBits = 32; NumFatBits = 32;
NumRootDirSectors = 0; NumRootDirSectors = 0;
@@ -163,7 +174,7 @@ bool CHeader::Parse(const Byte *p)
else else
{ {
// Some FAT12s don't contain VolFields // Some FAT12s don't contain VolFields
if (codeOffset < 62 - 24) if (codeOffset < 62 - 24 && !isOkOffset)
return false; return false;
NumFatBits = 0; NumFatBits = 0;
UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; UInt32 mask = (1 << (SectorSizeLog - 5)) - 1;
@@ -805,7 +816,7 @@ enum
// kpidFileSysType // kpidFileSysType
}; };
static const STATPROPSTG kArcProps[] = static const CStatProp kArcProps[] =
{ {
{ NULL, kpidFileSystem, VT_BSTR}, { NULL, kpidFileSystem, VT_BSTR},
{ NULL, kpidClusterSize, VT_UI4}, { NULL, kpidClusterSize, VT_UI4},
@@ -814,12 +825,12 @@ static const STATPROPSTG kArcProps[] =
{ NULL, kpidMTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidVolumeName, VT_BSTR}, { NULL, kpidVolumeName, VT_BSTR},
{ (LPOLESTR)L"FATs", kpidNumFats, VT_UI4}, { "FATs", kpidNumFats, VT_UI4},
{ NULL, kpidSectorSize, VT_UI4}, { NULL, kpidSectorSize, VT_UI4},
{ NULL, kpidId, VT_UI4}, { NULL, kpidId, VT_UI4},
// { (LPOLESTR)L"OEM Name", kpidOemName, VT_BSTR}, // { "OEM Name", kpidOemName, VT_BSTR},
// { (LPOLESTR)L"Volume Name", kpidVolName, VT_BSTR}, // { "Volume Name", kpidVolName, VT_BSTR},
// { (LPOLESTR)L"File System Type", kpidFileSysType, VT_BSTR} // { "File System Type", kpidFileSysType, VT_BSTR}
// { NULL, kpidSectorsPerTrack, VT_UI4}, // { NULL, kpidSectorsPerTrack, VT_UI4},
// { NULL, kpidNumHeads, VT_UI4}, // { NULL, kpidNumHeads, VT_UI4},
// { NULL, kpidHiddenSectors, VT_UI4} // { NULL, kpidHiddenSectors, VT_UI4}
@@ -858,7 +869,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
switch(propID) switch (propID)
{ {
case kpidFileSystem: case kpidFileSystem:
{ {
@@ -897,7 +908,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_BEGIN COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
const CItem &item = Items[index]; const CItem &item = Items[index];
switch(propID) switch (propID)
{ {
case kpidPath: prop = GetItemPath(index); break; case kpidPath: prop = GetItemPath(index); break;
case kpidShortName: prop = item.GetShortName(); break; case kpidShortName: prop = item.GetShortName(); break;

View File

@@ -93,7 +93,7 @@ static const Byte kProps[] =
IMP_IInArchive_Props IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table IMP_IInArchive_ArcProps_NO_Table
static const char *g_AudioTypes[16] = static const char * const g_AudioTypes[16] =
{ {
"pcm" "pcm"
, "adpcm" , "adpcm"
@@ -113,7 +113,7 @@ static const char *g_AudioTypes[16] =
, "audio15" , "audio15"
}; };
static const char *g_VideoTypes[16] = static const char * const g_VideoTypes[16] =
{ {
"video0" "video0"
, "jpeg" , "jpeg"
@@ -133,7 +133,7 @@ static const char *g_VideoTypes[16] =
, "video15" , "video15"
}; };
static const char *g_Rates[4] = static const char * const g_Rates[4] =
{ {
"5.5 kHz" "5.5 kHz"
, "11 kHz" , "11 kHz"
@@ -145,7 +145,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
const CItem2 &item = _items2[index]; const CItem2 &item = _items2[index];
switch(propID) switch (propID)
{ {
case kpidExtension: case kpidExtension:
prop = _isRaw ? prop = _isRaw ?
@@ -209,7 +209,7 @@ AString CHandler::GetComment()
Byte type = *p++; Byte type = *p++;
size--; size--;
bool ok = false; bool ok = false;
switch(type) switch (type)
{ {
case 0: case 0:
{ {
@@ -256,7 +256,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{ {
// COM_TRY_BEGIN // COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop; NWindows::NCOM::CPropVariant prop;
switch(propID) switch (propID)
{ {
// case kpidComment: prop = GetComment(); break; // case kpidComment: prop = GetComment(); break;
case kpidPhySize: prop = (UInt64)_phySize; break; case kpidPhySize: prop = (UInt64)_phySize; break;

View File

@@ -0,0 +1,427 @@
// GptHandler.cpp
#include "StdAfx.h"
#include "../../../C/7zCrc.h"
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
#include "../../Common/MyBuffer.h"
#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "HandlerCont.h"
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
using namespace NWindows;
namespace NArchive {
namespace NGpt {
#define SIGNATURE { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 }
static const unsigned k_SignatureSize = 12;
static const Byte k_Signature[k_SignatureSize] = SIGNATURE;
static const UInt32 kSectorSize = 512;
static const CUInt32PCharPair g_PartitionFlags[] =
{
{ 0, "Sys" },
{ 1, "Ignore" },
{ 2, "Legacy" },
{ 60, "Win-Read-only" },
{ 62, "Win-Hidden" },
{ 63, "Win-Not-Automount" }
};
static const unsigned kNameLen = 36;
struct CPartition
{
Byte Type[16];
Byte Id[16];
UInt64 FirstLba;
UInt64 LastLba;
UInt64 Flags;
Byte Name[kNameLen * 2];
bool IsUnused() const
{
for (unsigned i = 0; i < 16; i++)
if (Type[i] != 0)
return false;
return true;
}
UInt64 GetSize() const { return (LastLba - FirstLba + 1) * kSectorSize; }
UInt64 GetPos() const { return FirstLba * kSectorSize; }
UInt64 GetEnd() const { return (LastLba + 1) * kSectorSize; }
void Parse(const Byte *p)
{
memcpy(Type, p, 16);
memcpy(Id, p + 16, 16);
FirstLba = Get64(p + 32);
LastLba = Get64(p + 40);
Flags = Get64(p + 48);
memcpy(Name, p + 56, kNameLen * 2);
}
};
struct CPartType
{
UInt32 Id;
const char *Ext;
const char *Type;
};
static const CPartType kPartTypes[] =
{
// { 0x0, 0, "Unused" },
{ 0x21686148, 0, "BIOS Boot" },
{ 0xC12A7328, 0, "EFI System" },
{ 0x024DEE41, 0, "MBR" },
{ 0xE3C9E316, 0, "Windows MSR" },
{ 0xEBD0A0A2, 0, "Windows BDP" },
{ 0x5808C8AA, 0, "Windows LDM Metadata" },
{ 0xAF9B60A0, 0, "Windows LDM Data" },
{ 0xDE94BBA4, 0, "Windows Recovery" },
// { 0x37AFFC90, 0, "IBM GPFS" },
// { 0xE75CAF8F, 0, "Windows Storage Spaces" },
{ 0x0FC63DAF, 0, "Linux Data" },
{ 0x0657FD6D, 0, "Linux Swap" },
{ 0x83BD6B9D, 0, "FreeBSD Boot" },
{ 0x516E7CB4, 0, "FreeBSD Data" },
{ 0x516E7CB5, 0, "FreeBSD Swap" },
{ 0x516E7CB6, "ufs", "FreeBSD UFS" },
{ 0x516E7CB8, 0, "FreeBSD Vinum" },
{ 0x516E7CB8, "zfs", "FreeBSD ZFS" },
{ 0x48465300, "hfsx", "HFS+" },
};
static int FindPartType(const Byte *guid)
{
UInt32 val = Get32(guid);
for (unsigned i = 0; i < ARRAY_SIZE(kPartTypes); i++)
if (kPartTypes[i].Id == val)
return i;
return -1;
}
static inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); }
static void PrintHex(unsigned v, char *s)
{
s[0] = GetHex((v >> 4) & 0xF);
s[1] = GetHex(v & 0xF);
}
static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
{
PrintHex(val >> 8, s);
PrintHex(val & 0xFF, s + 2);
}
static void GuidToString(const Byte *g, char *s)
{
ConvertUInt32ToHex8Digits(Get32(g ), s); s += 8; *s++ = '-';
ConvertUInt16ToHex4Digits(Get16(g + 4), s); s += 4; *s++ = '-';
ConvertUInt16ToHex4Digits(Get16(g + 6), s); s += 4; *s++ = '-';
for (unsigned i = 0; i < 8; i++)
{
if (i == 2)
*s++ = '-';
PrintHex(g[8 + i], s);
s += 2;
}
*s = 0;
}
class CHandler: public CHandlerCont
{
CRecordVector<CPartition> _items;
UInt64 _totalSize;
Byte Guid[16];
CByteBuffer _buffer;
HRESULT Open2(IInStream *stream);
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
{
const CPartition &item = _items[index];
pos = item.GetPos();
size = item.GetSize();
return NExtract::NOperationResult::kOK;
}
public:
INTERFACE_IInArchive_Cont(;)
};
HRESULT CHandler::Open2(IInStream *stream)
{
_buffer.Alloc(kSectorSize * 2);
RINOK(ReadStream_FALSE(stream, _buffer, kSectorSize * 2));
const Byte *buf = _buffer;
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
return S_FALSE;
buf += kSectorSize;
if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
return S_FALSE;
{
// if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision
UInt32 headerSize = Get32(buf + 12); // = 0x5C usually
if (headerSize > kSectorSize)
return S_FALSE;
UInt32 crc = Get32(buf + 0x10);
SetUi32(_buffer + kSectorSize + 0x10, 0);
if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)
return S_FALSE;
}
// UInt32 reserved = Get32(buf + 0x14);
UInt64 curLba = Get64(buf + 0x18);
if (curLba != 1)
return S_FALSE;
UInt64 backupLba = Get64(buf + 0x20);
// UInt64 firstUsableLba = Get64(buf + 0x28);
// UInt64 lastUsableLba = Get64(buf + 0x30);
memcpy(Guid, buf + 0x38, 16);
UInt64 tableLba = Get64(buf + 0x48);
if (tableLba < 2)
return S_FALSE;
UInt32 numEntries = Get32(buf + 0x50);
UInt32 entrySize = Get32(buf + 0x54); // = 128 usually
UInt32 entriesCrc = Get32(buf + 0x58);
if (entrySize < 128
|| entrySize > (1 << 12)
|| numEntries > (1 << 16)
|| tableLba < 2
|| tableLba >= ((UInt64)1 << (64 - 10)))
return S_FALSE;
UInt32 tableSize = entrySize * numEntries;
UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);
_buffer.Alloc(tableSizeAligned);
UInt64 tableOffset = tableLba * kSectorSize;
RINOK(stream->Seek(tableOffset, STREAM_SEEK_SET, NULL));
RINOK(ReadStream_FALSE(stream, _buffer, tableSizeAligned));
if (CrcCalc(_buffer, tableSize) != entriesCrc)
return S_FALSE;
_totalSize = tableOffset + tableSizeAligned;
for (UInt32 i = 0; i < numEntries; i++)
{
CPartition item;
item.Parse(_buffer + i * entrySize);
if (item.IsUnused())
continue;
UInt64 endPos = item.GetEnd();
if (_totalSize < endPos)
_totalSize = endPos;
_items.Add(item);
}
{
const UInt64 end = (backupLba + 1) * kSectorSize;
if (_totalSize < end)
_totalSize = end;
}
{
UInt64 fileEnd;
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileEnd));
if (_totalSize < fileEnd)
{
const UInt64 rem = fileEnd - _totalSize;
const UInt64 kRemMax = 1 << 22;
if (rem <= kRemMax)
{
RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL));
bool areThereNonZeros = false;
UInt64 numZeros = 0;
if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK)
if (!areThereNonZeros)
_totalSize += numZeros;
}
}
}
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
Close();
RINOK(Open2(stream));
_stream = stream;
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_totalSize = 0;
memset(Guid, 0, sizeof(Guid));
_items.Clear();
_stream.Release();
return S_OK;
}
static const Byte kProps[] =
{
kpidPath,
kpidSize,
kpidFileSystem,
kpidCharacts,
kpidOffset,
kpidId
};
static const Byte kArcProps[] =
{
kpidId
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch (propID)
{
case kpidMainSubfile:
{
if (_items.Size() == 1)
prop = (UInt32)0;
break;
}
case kpidPhySize: prop = _totalSize; break;
case kpidId:
{
char s[48];
GuidToString(Guid, s);
prop = s;
break;
}
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
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 CPartition &item = _items[index];
switch (propID)
{
case kpidPath:
{
UString s;
for (unsigned i = 0; i < kNameLen; i++)
{
wchar_t c = (wchar_t)Get16(item.Name + i * 2);
if (c == 0)
break;
s += c;
}
if (s.IsEmpty())
{
char temp[16];
ConvertUInt32ToString(index, temp);
s.AddAscii(temp);
}
{
int typeIndex = FindPartType(item.Type);
s += L'.';
const char *ext = "img";
if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
ext = kPartTypes[(unsigned)typeIndex].Ext;
s.AddAscii(ext);
}
prop = s;
break;
}
case kpidSize:
case kpidPackSize: prop = item.GetSize(); break;
case kpidOffset: prop = item.GetPos(); break;
case kpidFileSystem:
{
char s[48];
const char *res;
int typeIndex = FindPartType(item.Type);
if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type)
res = kPartTypes[(unsigned)typeIndex].Type;
else
{
GuidToString(item.Type, s);
res = s;
}
prop = res;
break;
}
case kpidId:
{
char s[48];
GuidToString(item.Id, s);
prop = s;
break;
}
case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
REGISTER_ARC_I(
"GPT", "gpt mbr", NULL, 0xCB,
k_Signature,
kSectorSize,
0,
NULL)
}}

View File

@@ -0,0 +1,288 @@
// HandlerCont.cpp
#include "StdAfx.h"
#include "../../Common/ComTry.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
#include "HandlerCont.h"
namespace NArchive {
STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
{
RINOK(GetNumberOfItems(&numItems));
}
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
UInt64 pos, size;
GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size);
totalSize += size;
}
extractCallback->SetTotal(totalSize);
totalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++)
{
lps->InSize = totalSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &outStream, askMode));
UInt64 pos, size;
int opRes = GetItem_ExtractInfo(index, pos, size);
totalSize += size;
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (opRes == NExtract::NOperationResult::kOK)
{
RINOK(_stream->Seek(pos, STREAM_SEEK_SET, NULL));
streamSpec->Init(size);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
opRes = NExtract::NOperationResult::kDataError;
if (copyCoderSpec->TotalSize == size)
opRes = NExtract::NOperationResult::kOK;
else if (copyCoderSpec->TotalSize < size)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
}
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
*stream = NULL;
UInt64 pos, size;
if (GetItem_ExtractInfo(index, pos, size) != NExtract::NOperationResult::kOK)
return S_FALSE;
return CreateLimitedInStream(_stream, pos, size, stream);
COM_TRY_END
}
CHandlerImg::CHandlerImg():
_imgExt(NULL)
{
ClearStreamVars();
}
STDMETHODIMP CHandlerImg::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 = offset;
return S_OK;
}
static const Byte k_GDP_Signature[] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' };
static const char *GetImgExt(ISequentialInStream *stream)
{
const size_t kHeaderSize = 1 << 10;
Byte buf[kHeaderSize];
if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK)
{
if (buf[0x1FE] == 0x55 && buf[0x1FF] == 0xAA)
{
if (memcmp(buf + 512, k_GDP_Signature, sizeof(k_GDP_Signature)) == 0)
return "gpt";
return "mbr";
}
}
return NULL;
}
void CHandlerImg::CloseAtError()
{
Stream.Release();
}
STDMETHODIMP CHandlerImg::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * openCallback)
{
COM_TRY_BEGIN
{
Close();
HRESULT res;
try
{
res = Open2(stream, openCallback);
if (res == S_OK)
{
CMyComPtr<ISequentialInStream> inStream;
HRESULT res2 = GetStream(0, &inStream);
if (res2 == S_OK && inStream)
_imgExt = GetImgExt(inStream);
return S_OK;
}
}
catch(...)
{
CloseAtError();
throw;
}
CloseAtError();
return res;
}
COM_TRY_END
}
STDMETHODIMP CHandlerImg::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
RINOK(extractCallback->SetTotal(_size));
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &outStream, askMode));
if (!testMode && !outStream)
return S_OK;
RINOK(extractCallback->PrepareOperation(askMode));
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
int opRes = NExtract::NOperationResult::kDataError;
ClearStreamVars();
CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(0, &inStream);
if (hres == S_FALSE)
hres = E_NOTIMPL;
if (hres == S_OK && inStream)
{
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
hres = copyCoder->Code(inStream, outStream, NULL, &_size, progress);
if (hres == S_OK)
{
if (copyCoderSpec->TotalSize == _size)
opRes = NExtract::NOperationResult::kOK;
if (_stream_unavailData)
opRes = NExtract::NOperationResult::kUnavailable;
else if (_stream_unsupportedMethod)
opRes = NExtract::NOperationResult::kUnsupportedMethod;
else if (_stream_dataError)
opRes = NExtract::NOperationResult::kDataError;
else if (copyCoderSpec->TotalSize < _size)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
}
}
inStream.Release();
outStream.Release();
if (hres != S_OK)
{
if (hres == S_FALSE)
opRes = NExtract::NOperationResult::kDataError;
else if (hres == E_NOTIMPL)
opRes = NExtract::NOperationResult::kUnsupportedMethod;
else
return hres;
}
return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
{
areThereNonZeros = false;
numZeros = 0;
const size_t kBufSize = 1 << 11;
Byte buf[kBufSize];
for (;;)
{
UInt32 size = 0;
HRESULT(stream->Read(buf, kBufSize, &size));
if (size == 0)
return S_OK;
for (UInt32 i = 0; i < size; i++)
if (buf[i] != 0)
{
areThereNonZeros = true;
numZeros += i;
return S_OK;
}
numZeros += size;
if (numZeros > maxSize)
return S_OK;
}
}
}

View File

@@ -0,0 +1,116 @@
// HandlerCont.h
#ifndef __HANDLER_CONT_H
#define __HANDLER_CONT_H
#include "../../Common/MyCom.h"
#include "IArchive.h"
namespace NArchive {
#define INTERFACE_IInArchive_Cont(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; \
class CHandlerCont:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
protected:
CMyComPtr<IInStream> _stream;
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive_Cont(PURE)
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY;
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
// destructor must be virtual for this class
virtual ~CHandlerCont() {}
};
#define INTERFACE_IInArchive_Img(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; \
class CHandlerImg:
public IInStream,
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
protected:
UInt64 _virtPos;
UInt64 _posInArc;
UInt64 _size;
CMyComPtr<IInStream> Stream;
const char *_imgExt;
bool _stream_unavailData;
bool _stream_unsupportedMethod;
bool _stream_dataError;
// bool _stream_UsePackSize;
// UInt64 _stream_PackSize;
void ClearStreamVars()
{
_stream_unavailData = false;
_stream_unsupportedMethod = false;
_stream_dataError = false;
// _stream_UsePackSize = false;
// _stream_PackSize = 0;
}
virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;
virtual void CloseAtError();
public:
MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream)
INTERFACE_IInArchive_Img(PURE)
STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback);
STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) = 0;
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) = 0;
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
CHandlerImg();
// destructor must be virtual for this class
virtual ~CHandlerImg() {}
};
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
}
#endif

View File

@@ -507,7 +507,7 @@ HRESULT CHeaderRec::Parse(const Byte *p)
// LeafRecords = Get32(p + 6); // LeafRecords = Get32(p + 6);
FirstLeafNode = Get32(p + 0xA); FirstLeafNode = Get32(p + 0xA);
// LastLeafNode = Get32(p + 0xE); // LastLeafNode = Get32(p + 0xE);
UInt32 nodeSize = Get16(p + 0x12); const UInt32 nodeSize = Get16(p + 0x12);
unsigned i; unsigned i;
for (i = 9; ((UInt32)1 << i) != nodeSize; i++) for (i = 9; ((UInt32)1 << i) != nodeSize; i++)
@@ -583,9 +583,9 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
for (unsigned i = 0; i < desc.NumRecords; i++) for (unsigned i = 0; i < desc.NumRecords; i++)
{ {
UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; const UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog;
UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
if (offs > nodeSize || offsNext > nodeSize) if (offs > nodeSize || offsNext > nodeSize)
return S_FALSE; return S_FALSE;
UInt32 recSize = offsNext - offs; UInt32 recSize = offsNext - offs;
@@ -727,12 +727,12 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
for (unsigned i = 0; i < desc.NumRecords; i++) for (unsigned i = 0; i < desc.NumRecords; i++)
{ {
UInt32 nodeSize = (1 << hr.NodeSizeLog); const UInt32 nodeSize = (1 << hr.NodeSizeLog);
UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
UInt32 recSize = offsNext - offs; UInt32 recSize = offsNext - offs;
if (offs >= nodeSize if (offs >= nodeSize
|| offsNext >= nodeSize || offsNext > nodeSize
|| offsNext < offs) || offsNext < offs)
return S_FALSE; return S_FALSE;
@@ -876,7 +876,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
// CNodeDescriptor nodeDesc; // CNodeDescriptor nodeDesc;
// nodeDesc.Parse(p); // nodeDesc.Parse(p);
CHeaderRec hr; CHeaderRec hr;
hr.Parse(p + kNodeDescriptor_Size); RINOK(hr.Parse(p + kNodeDescriptor_Size));
// CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);
@@ -898,7 +898,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
return S_FALSE; return S_FALSE;
usedBuf[node] = 1; usedBuf[node] = 1;
size_t nodeOffset = (size_t)node << hr.NodeSizeLog; const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
CNodeDescriptor desc; CNodeDescriptor desc;
desc.Parse(p + nodeOffset); desc.Parse(p + nodeOffset);
if (!desc.CheckNumRecords(hr.NodeSizeLog)) if (!desc.CheckNumRecords(hr.NodeSizeLog))
@@ -908,12 +908,12 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
for (unsigned i = 0; i < desc.NumRecords; i++) for (unsigned i = 0; i < desc.NumRecords; i++)
{ {
UInt32 nodeSize = (1 << hr.NodeSizeLog); const UInt32 nodeSize = (1 << hr.NodeSizeLog);
UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
UInt32 recSize = offsNext - offs; UInt32 recSize = offsNext - offs;
if (offs >= nodeSize if (offs >= nodeSize
|| offs >= nodeSize || offsNext > nodeSize
|| offsNext < offs || offsNext < offs
|| recSize < 6) || recSize < 6)
return S_FALSE; return S_FALSE;
@@ -987,7 +987,9 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
item.GroupID = Get32(r + 0x24); item.GroupID = Get32(r + 0x24);
item.AdminFlags = r[0x28]; item.AdminFlags = r[0x28];
item.OwnerFlags = r[0x29]; item.OwnerFlags = r[0x29];
*/
item.FileMode = Get16(r + 0x2A); item.FileMode = Get16(r + 0x2A);
/*
item.special.iNodeNum = Get16(r + 0x2C); // or .linkCount item.special.iNodeNum = Get16(r + 0x2C); // or .linkCount
item.FileType = Get32(r + 0x30); item.FileType = Get32(r + 0x30);
item.FileCreator = Get32(r + 0x34); item.FileCreator = Get32(r + 0x34);
@@ -1572,6 +1574,9 @@ HRESULT CHandler::ExtractZlibFile(
UInt32 size = GetUi32(tableBuf + i * 8 + 4); UInt32 size = GetUi32(tableBuf + i * 8 + 4);
if (size > buf.Size() || size > kCompressionBlockSize + 1)
return S_FALSE;
RINOK(ReadStream_FALSE(inStream, buf, size)); RINOK(ReadStream_FALSE(inStream, buf, size));
if ((buf[0] & 0xF) == 0xF) if ((buf[0] & 0xF) == 0xF)
@@ -1759,7 +1764,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (rem == 0) if (rem == 0)
{ {
// Here we check that there are no extra (empty) blocks in last extent. // Here we check that there are no extra (empty) blocks in last extent.
if (extentRem >= (UInt64)((UInt32)1 << Header.BlockSizeLog)) if (extentRem >= ((UInt64)1 << Header.BlockSizeLog))
res = NExtract::NOperationResult::kDataError; res = NExtract::NOperationResult::kDataError;
break; break;
} }

View File

@@ -293,12 +293,14 @@ namespace NPropDataType
const UInt32 kMask_ZeroEnd = 1 << 4; const UInt32 kMask_ZeroEnd = 1 << 4;
// const UInt32 kMask_BigEndian = 1 << 5; // const UInt32 kMask_BigEndian = 1 << 5;
const UInt32 kMask_Utf = 1 << 6; const UInt32 kMask_Utf = 1 << 6;
// const UInt32 kMask_Utf8 = kMask_Utf | 0; const UInt32 kMask_Utf8 = kMask_Utf | 0;
const UInt32 kMask_Utf16 = kMask_Utf | 1; const UInt32 kMask_Utf16 = kMask_Utf | 1;
// const UInt32 kMask_Utf32 = kMask_Utf | 2; // const UInt32 kMask_Utf32 = kMask_Utf | 2;
const UInt32 kNotDefined = 0; const UInt32 kNotDefined = 0;
const UInt32 kRaw = 1; const UInt32 kRaw = 1;
const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd;
const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;
}; };
@@ -512,12 +514,26 @@ ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05)
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
*propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \ *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \
struct CStatProp
{
const char *Name;
UInt32 PropID;
VARTYPE vt;
};
namespace NWindows {
namespace NCOM {
// PropVariant.cpp
BSTR AllocBstrFromAscii(const char *s) throw();
}}
#define IMP_IInArchive_GetProp_WITH_NAME(k) \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
const STATPROPSTG &srcItem = k[index]; \ const CStatProp &prop = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; \ *propID = (PROPID)prop.PropID; *varType = prop.vt; \
if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \
#define IMP_IInArchive_Props \ #define IMP_IInArchive_Props \
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \

View File

@@ -30,7 +30,14 @@ static const Byte kProps[] =
kpidIsDir, kpidIsDir,
kpidSize, kpidSize,
kpidPackSize, kpidPackSize,
kpidMTime kpidMTime,
// kpidCTime,
// kpidATime,
kpidPosixAttrib,
// kpidUser,
// kpidGroup,
// kpidLinks,
kpidSymLink
}; };
static const Byte kArcProps[] = static const Byte kArcProps[] =
@@ -213,17 +220,87 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = s; prop = s;
} }
break; break;
case kpidSymLink:
if (_archive.IsSusp)
{
UString s;
UInt32 mode;
if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode))
{
if (((mode >> 12) & 0xF) == 10)
{
AString s8;
if (item.GetSymLink(_archive.SuspSkipSize, s8))
{
s = MultiByteToUnicodeString(s8, CP_OEMCP);
prop = s;
}
}
}
}
break;
case kpidPosixAttrib:
/*
case kpidLinks:
case kpidUser:
case kpidGroup:
*/
{
if (_archive.IsSusp)
{
UInt32 t = 0;
switch (propID)
{
case kpidPosixAttrib: t = k_Px_Mode; break;
/*
case kpidLinks: t = k_Px_Links; break;
case kpidUser: t = k_Px_User; break;
case kpidGroup: t = k_Px_Group; break;
*/
}
UInt32 v;
if (item.GetPx(_archive.SuspSkipSize, t, v))
prop = v;
}
break;
}
case kpidIsDir: prop = item.IsDir(); break; case kpidIsDir: prop = item.IsDir(); break;
case kpidSize: case kpidSize:
case kpidPackSize: case kpidPackSize:
if (!item.IsDir()) if (!item.IsDir())
prop = (UInt64)ref.TotalSize; prop = (UInt64)ref.TotalSize;
break; break;
case kpidMTime: case kpidMTime:
// case kpidCTime:
// case kpidATime:
{ {
FILETIME utc; FILETIME utc;
if (item.DateTime.GetFileTime(utc)) if (/* propID == kpidMTime && */ item.DateTime.GetFileTime(utc))
prop = utc; prop = utc;
/*
else
{
UInt32 t = 0;
switch (propID)
{
case kpidMTime: t = k_Tf_MTime; break;
case kpidCTime: t = k_Tf_CTime; break;
case kpidATime: t = k_Tf_ATime; break;
}
CRecordingDateTime dt;
if (item.GetTf(_archive.SuspSkipSize, t, dt))
{
FILETIME utc;
if (dt.GetFileTime(utc))
prop = utc;
}
}
*/
break; break;
} }
} }
@@ -321,9 +398,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 offset = 0; UInt64 offset = 0;
for (UInt32 e = 0; e < ref.NumExtents; e++) for (UInt32 e = 0; e < ref.NumExtents; e++)
{ {
lps->InSize = lps->OutSize = currentTotalSize + offset;
const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; const CDir &item2 = ref.Dir->_subItems[ref.Index + e];
RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL)); if (item2.Size == 0)
continue;
lps->InSize = lps->OutSize = currentTotalSize + offset;
RINOK(_stream->Seek((UInt64)item2.ExtentLocation * kBlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(item2.Size); streamSpec->Init(item2.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != item2.Size) if (copyCoderSpec->TotalSize != item2.Size)
@@ -336,7 +415,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
else else
{ {
RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek((UInt64)blockIndex * kBlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(currentItemSize); streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != currentItemSize) if (copyCoderSpec->TotalSize != currentItemSize)
@@ -358,7 +437,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
UInt64 blockIndex; UInt64 blockIndex;
UInt64 currentItemSize; UInt64 currentItemSize;
if (index < (UInt32)_archive.Refs.Size()) if (index < _archive.Refs.Size())
{ {
const CRef &ref = _archive.Refs[index]; const CRef &ref = _archive.Refs[index];
const CDir &item = ref.Dir->_subItems[ref.Index]; const CDir &item = ref.Dir->_subItems[ref.Index];
@@ -375,14 +454,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
UInt64 virtOffset = 0; UInt64 virtOffset = 0;
for (UInt32 i = 0; i < ref.NumExtents; i++) for (UInt32 i = 0; i < ref.NumExtents; i++)
{ {
const CDir &item = ref.Dir->_subItems[ref.Index + i]; const CDir &item2 = ref.Dir->_subItems[ref.Index + i];
if (item.Size == 0) if (item2.Size == 0)
continue; continue;
CSeekExtent se; CSeekExtent se;
se.Phy = (UInt64)item.ExtentLocation * _archive.BlockSize; se.Phy = (UInt64)item2.ExtentLocation * kBlockSize;
se.Virt = virtOffset; se.Virt = virtOffset;
extentStreamSpec->Extents.Add(se); extentStreamSpec->Extents.Add(se);
virtOffset += item.Size; virtOffset += item2.Size;
} }
if (virtOffset != ref.TotalSize) if (virtOffset != ref.TotalSize)
return S_FALSE; return S_FALSE;
@@ -394,6 +473,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = extentStream.Detach(); *stream = extentStream.Detach();
return S_OK; return S_OK;
} }
currentItemSize = item.Size; currentItemSize = item.Size;
blockIndex = item.ExtentLocation; blockIndex = item.ExtentLocation;
} }
@@ -405,7 +485,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
blockIndex = be.LoadRBA; blockIndex = be.LoadRBA;
} }
return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); return CreateLimitedInStream(_stream, (UInt64)blockIndex * kBlockSize, currentItemSize, stream);
COM_TRY_END COM_TRY_END
} }

View File

@@ -8,6 +8,8 @@
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "../HandlerCont.h"
#include "IsoIn.h" #include "IsoIn.h"
namespace NArchive { namespace NArchive {
@@ -86,15 +88,15 @@ AString CBootInitialEntry::GetName() const
Byte CInArchive::ReadByte() Byte CInArchive::ReadByte()
{ {
if (m_BufferPos >= BlockSize) if (m_BufferPos >= kBlockSize)
m_BufferPos = 0; m_BufferPos = 0;
if (m_BufferPos == 0) if (m_BufferPos == 0)
{ {
size_t processed = BlockSize; size_t processed = kBlockSize;
HRESULT res = ReadStream(_stream, m_Buffer, &processed); HRESULT res = ReadStream(_stream, m_Buffer, &processed);
if (res != S_OK) if (res != S_OK)
throw CSystemException(res); throw CSystemException(res);
if (processed != BlockSize) if (processed != kBlockSize)
throw CUnexpectedEndException(); throw CUnexpectedEndException();
UInt64 end = _position + processed; UInt64 end = _position + processed;
if (PhySize < end) if (PhySize < end)
@@ -292,7 +294,11 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
d.FileStructureVersion = ReadByte(); // = 1 d.FileStructureVersion = ReadByte(); // = 1
SkipZeros(1); SkipZeros(1);
ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse)); ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
SkipZeros(653);
// Most ISO contains zeros in the following field (reserved for future standardization).
// But some ISO programs write some data to that area.
// So we disable check for zeros.
Skip(653); // SkipZeros(653);
} }
static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };
@@ -509,7 +515,7 @@ HRESULT CInArchive::Open2()
PhySize = _position; PhySize = _position;
m_BufferPos = 0; m_BufferPos = 0;
BlockSize = kBlockSize; // BlockSize = kBlockSize;
for (;;) for (;;)
{ {
@@ -596,24 +602,40 @@ HRESULT CInArchive::Open2()
ReadBootInfo(); ReadBootInfo();
{ {
FOR_VECTOR(i, Refs) FOR_VECTOR (i, Refs)
{ {
const CRef &ref = Refs[i]; const CRef &ref = Refs[i];
for (UInt32 j = 0; j < ref.NumExtents; j++) for (UInt32 j = 0; j < ref.NumExtents; j++)
{ {
const CDir &item = ref.Dir->_subItems[ref.Index + j]; const CDir &item = ref.Dir->_subItems[ref.Index + j];
if (!item.IsDir()) if (!item.IsDir() && item.Size != 0)
UpdatePhySize(item.ExtentLocation, item.Size); UpdatePhySize(item.ExtentLocation, item.Size);
} }
} }
} }
{ {
FOR_VECTOR(i, BootEntries) FOR_VECTOR (i, BootEntries)
{ {
const CBootInitialEntry &be = BootEntries[i]; const CBootInitialEntry &be = BootEntries[i];
UpdatePhySize(be.LoadRBA, GetBootItemSize(i)); UpdatePhySize(be.LoadRBA, GetBootItemSize(i));
} }
} }
if (PhySize < _fileSize)
{
UInt64 rem = _fileSize - PhySize;
const UInt64 kRemMax = 1 << 21;
if (rem <= kRemMax)
{
RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL));
bool areThereNonZeros = false;
UInt64 numZeros = 0;
RINOK(ReadZeroTail(_stream, areThereNonZeros, numZeros, kRemMax));
if (!areThereNonZeros)
PhySize += numZeros;
}
}
return S_OK; return S_OK;
} }

View File

@@ -170,7 +170,7 @@ struct CBootInitialEntry
// Partition Table found in the boot image. // Partition Table found in the boot image.
UInt16 SectorCount; // This is the number of virtual/emulated sectors the system UInt16 SectorCount; // This is the number of virtual/emulated sectors the system
// will store at Load Segment during the initial boot procedure. // will store at Load Segment during the initial boot procedure.
UInt32 LoadRBA; // This is the start address of the virtual disk. CD<EFBFBD>s use UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use
// Relative/Logical block addressing. // Relative/Logical block addressing.
Byte VendorSpec[20]; Byte VendorSpec[20];
@@ -282,7 +282,7 @@ public:
CRecordVector<CRef> Refs; CRecordVector<CRef> Refs;
CObjectVector<CVolumeDescriptor> VolDescs; CObjectVector<CVolumeDescriptor> VolDescs;
int MainVolDescIndex; int MainVolDescIndex;
UInt32 BlockSize; // UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries; CObjectVector<CBootInitialEntry> BootEntries;
bool IsArc; bool IsArc;
@@ -297,8 +297,8 @@ public:
void UpdatePhySize(UInt32 blockIndex, UInt64 size) void UpdatePhySize(UInt32 blockIndex, UInt64 size)
{ {
UInt64 alignedSize = (size + BlockSize - 1) & ~((UInt64)BlockSize - 1); const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);
UInt64 end = blockIndex * BlockSize + alignedSize; const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;
if (PhySize < end) if (PhySize < end)
PhySize = end; PhySize = end;
} }
@@ -315,7 +315,7 @@ public:
size = (1440 << 10); size = (1440 << 10);
else if (be.BootMediaType == NBootMediaType::k2d88Floppy) else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
size = (2880 << 10); size = (2880 << 10);
UInt64 startPos = (UInt64)be.LoadRBA * BlockSize; UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;
if (startPos < _fileSize) if (startPos < _fileSize)
{ {
if (_fileSize - startPos < size) if (_fileSize - startPos < size)

View File

@@ -3,6 +3,8 @@
#ifndef __ARCHIVE_ISO_ITEM_H #ifndef __ARCHIVE_ISO_ITEM_H
#define __ARCHIVE_ISO_ITEM_H #define __ARCHIVE_ISO_ITEM_H
#include "../../../../C/CpuArch.h"
#include "../../../Common/MyString.h" #include "../../../Common/MyString.h"
#include "../../../Common/MyBuffer.h" #include "../../../Common/MyBuffer.h"
@@ -38,6 +40,32 @@ struct CRecordingDateTime
} }
}; };
enum EPx
{
k_Px_Mode,
k_Px_Links,
k_Px_User,
k_Px_Group,
k_Px_SerialNumber
// k_Px_Num
};
/*
enum ETf
{
k_Tf_CTime,
k_Tf_MTime,
k_Tf_ATime,
k_Tf_Attrib,
k_Tf_Backup,
k_Tf_Expiration,
k_Tf_Effective
// k_Tf_Num
};
*/
struct CDirRecord struct CDirRecord
{ {
UInt32 ExtentLocation; UInt32 ExtentLocation;
@@ -69,7 +97,8 @@ struct CDirRecord
return (b == 0 || b == 1); return (b == 0 || b == 1);
} }
const Byte* FindSuspName(unsigned skipSize, unsigned &lenRes) const
const Byte* FindSuspRecord(unsigned skipSize, Byte id0, Byte id1, unsigned &lenRes) const
{ {
lenRes = 0; lenRes = 0;
if (SystemUse.Size() < skipSize) if (SystemUse.Size() < skipSize)
@@ -79,14 +108,14 @@ struct CDirRecord
while (rem >= 5) while (rem >= 5)
{ {
unsigned len = p[2]; unsigned len = p[2];
if (len > rem) if (len < 3 || len > rem)
return 0; return 0;
if (p[0] == 'N' && p[1] == 'M' && p[3] == 1) if (p[0] == id0 && p[1] == id1 && p[3] == 1)
{ {
if (len < 5) if (len < 4)
return 0; // Check it return 0; // Check it
lenRes = len - 5; lenRes = len - 4;
return p + 5; return p + 4;
} }
p += len; p += len;
rem -= len; rem -= len;
@@ -94,17 +123,23 @@ struct CDirRecord
return 0; return 0;
} }
const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const
{ {
const Byte *res = NULL; const Byte *res = NULL;
unsigned len = 0; unsigned len = 0;
if (checkSusp) if (checkSusp)
res = FindSuspName(skipSize, len); res = FindSuspRecord(skipSize, 'N', 'M', len);
if (!res) if (!res || len < 1)
{ {
res = (const Byte *)FileId; res = (const Byte *)FileId;
len = (unsigned)FileId.Size(); len = (unsigned)FileId.Size();
} }
else
{
res++;
len--;
}
unsigned i; unsigned i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if (res[i] == 0) if (res[i] == 0)
@@ -114,6 +149,141 @@ struct CDirRecord
} }
const bool GetSymLink(int skipSize, AString &link) const
{
link.Empty();
const Byte *p = NULL;
unsigned len = 0;
p = FindSuspRecord(skipSize, 'S', 'L', len);
if (!p || len < 1)
return false;
if (*p != 0)
return false;
p++;
len--;
while (len != 0)
{
if (len < 2)
return false;
unsigned flags = p[0];
unsigned cl = p[1];
p += 2;
len -= 2;
if (cl > len)
return false;
bool needSlash = false;
if (flags & (1 << 1)) link += "./";
else if (flags & (1 << 2)) link += "../";
else if (flags & (1 << 3)) link += '/';
else
needSlash = true;
for (unsigned i = 0; i < cl; i++)
{
char c = p[i];
if (c == 0)
{
break;
// return false;
}
link += c;
}
p += cl;
len -= cl;
if (len == 0)
break;
if (needSlash)
link += '/';
}
return true;
}
static const bool GetLe32Be32(const Byte *p, UInt32 &dest)
{
UInt32 v1 = GetUi32(p);
UInt32 v2 = GetBe32(p + 4);
if (v1 == v2)
{
dest = v1;
return true;
}
return false;
}
const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const
{
const Byte *p = NULL;
unsigned len = 0;
p = FindSuspRecord(skipSize, 'P', 'X', len);
if (!p)
return false;
// px.Clear();
if (len < ((unsigned)pxType + 1) * 8)
return false;
return GetLe32Be32(p + pxType * 8, val);
}
/*
const bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const
{
const Byte *p = NULL;
unsigned len = 0;
p = FindSuspRecord(skipSize, 'T', 'F', len);
if (!p)
return false;
if (len < 1)
return false;
Byte flags = *p++;
len--;
unsigned step = 7;
if (flags & 0x80)
{
step = 17;
return false;
}
if ((flags & (1 << pxType)) == 0)
return false;
for (unsigned i = 0; i < pxType; i++)
{
if (len < step)
return false;
if (flags & (1 << i))
{
p += step;
len -= step;
}
}
if (len < step)
return false;
t.Year = p[0];
t.Month = p[1];
t.Day = p[2];
t.Hour = p[3];
t.Minute = p[4];
t.Second = p[5];
t.GmtOffset = (signed char)p[6];
return true;
}
*/
bool CheckSusp(const Byte *p, unsigned &startPos) const bool CheckSusp(const Byte *p, unsigned &startPos) const
{ {
if (p[0] == 'S' && if (p[0] == 'S' &&

View File

@@ -110,7 +110,7 @@ HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
{ {
_filterCoder = new CFilterCoder(false); _filterCoder = new CFilterCoder(false);
CMyComPtr<ICompressCoder> coder = _filterCoder; CMyComPtr<ICompressCoder> coder = _filterCoder;
_filterCoder->Filter = new CBcjCoder(false); _filterCoder->Filter = new NCompress::NBcj::CCoder(false);
_bcjStream = _filterCoder; _bcjStream = _filterCoder;
} }
} }

View File

@@ -40,7 +40,7 @@ namespace NMacho {
#define CPU_SUBTYPE_LIB64 (1 << 31) #define CPU_SUBTYPE_LIB64 (1 << 31)
#define CPU_SUBTYPE_POWERPC_970 100 #define CPU_SUBTYPE_POWERPC_970 100
static const char * const k_PowerPc_SubTypes[] = static const char * const k_PowerPc_SubTypes[] =
{ {
@@ -75,7 +75,7 @@ static const CUInt32PCharPair g_CpuPairs[] =
#define SECT_ATTR_ZEROFILL 1 #define SECT_ATTR_ZEROFILL 1
static const char *g_SectTypes[] = static const char * const g_SectTypes[] =
{ {
"REGULAR" "REGULAR"
, "ZEROFILL" , "ZEROFILL"
@@ -108,7 +108,7 @@ enum EFileType
kType_DSYM kType_DSYM
}; };
static const char *g_FileTypes[] = static const char * const g_FileTypes[] =
{ {
"0" "0"
, "OBJECT" , "OBJECT"
@@ -124,7 +124,7 @@ static const char *g_FileTypes[] =
}; };
static const char *g_ArcFlags[] = static const char * const g_ArcFlags[] =
{ {
"NOUNDEFS" "NOUNDEFS"
, "INCRLINK" , "INCRLINK"

View File

@@ -13,16 +13,13 @@
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/IntToString.h" #include "../../Common/IntToString.h"
#include "../../Common/MyBuffer.h" #include "../../Common/MyBuffer.h"
#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h" #include "HandlerCont.h"
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
#define PRF(x) x #define PRF(x) x
@@ -56,12 +53,15 @@ struct CChs
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
// Chs in some MBRs contains only low bits of "Cyl number". So we disable check.
/*
static int CompareChs(const CChs &c1, const CChs &c2) static int CompareChs(const CChs &c1, const CChs &c2)
{ {
RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));
RINOZ(MyCompare(c1.Head, c2.Head)); RINOZ(MyCompare(c1.Head, c2.Head));
return MyCompare(c1.GetSector(), c2.GetSector()); return MyCompare(c1.GetSector(), c2.GetSector());
} }
*/
static void AddUIntToString(UInt32 val, AString &res) static void AddUIntToString(UInt32 val, AString &res)
{ {
@@ -112,12 +112,11 @@ struct CPartition
return true; return true;
if (Status != 0 && Status != 0x80) if (Status != 0 && Status != 0x80)
return false; return false;
return return BeginChs.Check()
BeginChs.Check() && && EndChs.Check()
EndChs.Check() && // && CompareChs(BeginChs, EndChs) <= 0
CompareChs(BeginChs, EndChs) <= 0 && && NumBlocks > 0
NumBlocks > 0 && && CheckLbaLimits();
CheckLbaLimits();
} }
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
@@ -159,11 +158,13 @@ static const CPartType kPartTypes[] =
{ 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
{ 0x82, 0, "Solaris x86 / Linux swap" }, { 0x82, 0, "Solaris x86 / Linux swap" },
{ 0x83, 0, "Linux" }, { 0x83, 0, "Linux" },
{ 0x8E, "lvm", "Linux LVM" },
{ 0xA5, 0, "BSD slice" },
{ 0xBE, 0, "Solaris 8 boot" }, { 0xBE, 0, "Solaris 8 boot" },
{ 0xBF, 0, "New Solaris x86" }, { 0xBF, 0, "New Solaris x86" },
{ 0xC2, 0, "Linux-Hidden" }, { 0xC2, 0, "Linux-Hidden" },
{ 0xC3, 0, "Linux swap-Hidden" }, { 0xC3, 0, "Linux swap-Hidden" },
{ 0xEE, 0, "EFI-MBR" }, { 0xEE, 0, "GPT" },
{ 0xEE, 0, "EFI" } { 0xEE, 0, "EFI" }
}; };
@@ -183,21 +184,23 @@ struct CItem
CPartition Part; CPartition Part;
}; };
class CHandler: class CHandler: public CHandlerCont
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{ {
CMyComPtr<IInStream> _stream;
CObjectVector<CItem> _items; CObjectVector<CItem> _items;
UInt64 _totalSize; UInt64 _totalSize;
CByteBuffer _buffer; CByteBuffer _buffer;
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
{
const CItem &item = _items[index];
pos = item.Part.GetPos();
size = item.Size;
return NExtract::NOperationResult::kOK;
}
HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level); HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
public: public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive_Cont(;)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
}; };
HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level) HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
@@ -336,15 +339,15 @@ enum
kpidEndChs kpidEndChs
}; };
static const STATPROPSTG kProps[] = static const CStatProp kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI8},
{ NULL, kpidFileSystem, VT_BSTR}, { NULL, kpidFileSystem, VT_BSTR},
{ NULL, kpidOffset, VT_UI8}, { NULL, kpidOffset, VT_UI8},
{ (LPOLESTR)L"Primary", kpidPrimary, VT_BOOL}, { "Primary", kpidPrimary, VT_BOOL},
{ (LPOLESTR)L"Begin CHS", kpidBegChs, VT_BSTR}, { "Begin CHS", kpidBegChs, VT_BSTR},
{ (LPOLESTR)L"End CHS", kpidEndChs, VT_BSTR} { "End CHS", kpidEndChs, VT_BSTR}
}; };
IMP_IInArchive_Props_WITH_NAME IMP_IInArchive_Props_WITH_NAME
@@ -391,7 +394,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CItem &item = _items[index]; const CItem &item = _items[index];
const CPartition &part = item.Part; const CPartition &part = item.Part;
switch(propID) switch (propID)
{ {
case kpidPath: case kpidPath:
{ {
@@ -421,7 +424,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = res; prop = res;
} }
break; break;
case kpidSize: prop = item.Size; break;; case kpidSize:
case kpidPackSize: prop = item.Size; break; case kpidPackSize: prop = item.Size; break;
case kpidOffset: prop = part.GetPos(); break; case kpidOffset: prop = part.GetPos(); break;
case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break; case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;
@@ -433,72 +436,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END COM_TRY_END
} }
STDMETHODIMP 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 (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;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++)
{
lps->InSize = totalSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
const CPartition &part = item.Part;
RINOK(extractCallback->GetStream(index, &outStream, askMode));
totalSize += item.Size;
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL));
streamSpec->Init(item.Size);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release();
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItem &item = _items[index];
return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream);
COM_TRY_END
}
// 3, { 1, 1, 0 }, // 3, { 1, 1, 0 },
// 2, { 0x55, 0x1FF }, // 2, { 0x55, 0x1FF },

View File

@@ -10,12 +10,10 @@
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h" #include "HandlerCont.h"
static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); }
@@ -36,7 +34,7 @@ namespace NMub {
#define MACH_CPU_SUBTYPE_LIB64 (1 << 31) #define MACH_CPU_SUBTYPE_LIB64 (1 << 31)
#define MACH_CPU_SUBTYPE_I386_ALL 3 #define MACH_CPU_SUBTYPE_I386_ALL 3
struct CItem struct CItem
{ {
@@ -49,12 +47,8 @@ struct CItem
static const UInt32 kNumFilesMax = 10; static const UInt32 kNumFilesMax = 10;
class CHandler: class CHandler: public CHandlerCont
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{ {
CMyComPtr<IInStream> _stream;
// UInt64 _startPos; // UInt64 _startPos;
UInt64 _phySize; UInt64 _phySize;
UInt32 _numItems; UInt32 _numItems;
@@ -62,10 +56,17 @@ class CHandler:
CItem _items[kNumFilesMax]; CItem _items[kNumFilesMax];
HRESULT Open2(IInStream *stream); HRESULT Open2(IInStream *stream);
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
{
const CItem &item = _items[index];
pos = item.Offset;
size = item.Size;
return NExtract::NOperationResult::kOK;
}
public: public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive_Cont(;)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
}; };
static const Byte kArcProps[] = static const Byte kArcProps[] =
@@ -223,75 +224,6 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = _numItems;
if (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);
UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++)
{
lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += item.Size;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (testMode)
{
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue;
}
RINOK(_stream->Seek(/* _startPos + */ item.Offset, STREAM_SEEK_SET, NULL));
streamSpec->Init(item.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
realOutStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItem &item = _items[index];
return CreateLimitedInStream(_stream, /* _startPos + */ item.Offset, item.Size, stream);
COM_TRY_END
}
namespace NBe { namespace NBe {
static const Byte k_Signature[] = { static const Byte k_Signature[] = {

View File

@@ -12,7 +12,6 @@
#include "../../Compress/BcjCoder.h" #include "../../Compress/BcjCoder.h"
#include "../../Compress/BZip2Decoder.h" #include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#define Get32(p) GetUi32(p) #define Get32(p) GetUi32(p)
@@ -27,12 +26,16 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
if (Method != _curMethod) if (Method != _curMethod)
Release(); Release();
_curMethod = Method; _curMethod = Method;
if (!_codecInStream) if (!_codecInStream)
{ {
switch (Method) switch (Method)
{ {
// case NMethodType::kCopy: return E_NOTIMPL; // case NMethodType::kCopy: return E_NOTIMPL;
case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break; case NMethodType::kDeflate:
_deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder();
_codecInStream = _deflateDecoder;
break;
case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break; case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
case NMethodType::kLZMA: case NMethodType::kLZMA:
_lzmaDecoder = new NCompress::NLzma::CDecoder(); _lzmaDecoder = new NCompress::NLzma::CDecoder();
@@ -42,6 +45,9 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
} }
} }
if (Method == NMethodType::kDeflate)
_deflateDecoder->SetNsisMode(IsNsisDeflate);
if (FilterFlag) if (FilterFlag)
{ {
Byte flag; Byte flag;
@@ -59,7 +65,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{ {
_filter = new CFilterCoder(false); _filter = new CFilterCoder(false);
_filterInStream = _filter; _filterInStream = _filter;
_filter->Filter = new CBcjCoder(false); _filter->Filter = new NCompress::NBcj::CCoder(false);
} }
RINOK(_filter->SetInStream(_codecInStream)); RINOK(_filter->SetInStream(_codecInStream));
_decoderInStream = _filterInStream; _decoderInStream = _filterInStream;
@@ -199,9 +205,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
if (outBuf) if (outBuf)
{ {
if (!unpackSizeDefined) if (unpackSizeDefined)
return S_FALSE; outBuf->Alloc(unpackSize);
outBuf->Alloc(unpackSize);
} }
UInt64 inSizeStart = 0; UInt64 inSizeStart = 0;
@@ -213,6 +218,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
unpackSize = 0xFFFFFFFF; unpackSize = 0xFFFFFFFF;
UInt32 offset = 0; UInt32 offset = 0;
HRESULT res = S_OK;
for (;;) for (;;)
{ {
size_t rem = unpackSize - offset; size_t rem = unpackSize - offset;
@@ -225,11 +232,25 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
if (size == 0) if (size == 0)
{ {
if (unpackSizeDefined) if (unpackSizeDefined)
return S_FALSE; res = S_FALSE;
break; break;
} }
if (outBuf) if (outBuf)
{
size_t nextSize = offset + size;
if (outBuf->Size() < nextSize)
{
{
const size_t nextSize2 = outBuf->Size() * 2;
if (nextSize < nextSize2)
nextSize = nextSize2;
}
outBuf->ChangeSize_KeepData(nextSize, offset);
}
memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size); memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size);
}
StreamPos += size; StreamPos += size;
offset += (UInt32)size; offset += (UInt32)size;
@@ -243,9 +264,17 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
UInt64 outSize = offset; UInt64 outSize = offset;
RINOK(progress->SetRatioInfo(&inSize, &outSize)); RINOK(progress->SetRatioInfo(&inSize, &outSize));
if (realOutStream) if (realOutStream)
RINOK(WriteStream(realOutStream, Buffer, size)); {
res = WriteStream(realOutStream, Buffer, size);
if (res != S_OK)
break;
}
} }
return S_OK;
if (outBuf && offset != outBuf->Size())
outBuf->ChangeSize_KeepData(offset, offset);
return res;
} }
}} }}

View File

@@ -8,6 +8,7 @@
#include "../../Common/FilterCoder.h" #include "../../Common/FilterCoder.h"
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h" #include "../../Compress/LzmaDecoder.h"
namespace NArchive { namespace NArchive {
@@ -37,6 +38,7 @@ class CDecoder
CMyComPtr<ISequentialInStream> _codecInStream; CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream; CMyComPtr<ISequentialInStream> _decoderInStream;
NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoder;
NCompress::NLzma::CDecoder *_lzmaDecoder; NCompress::NLzma::CDecoder *_lzmaDecoder;
public: public:
@@ -46,9 +48,16 @@ public:
NMethodType::EEnum Method; NMethodType::EEnum Method;
bool FilterFlag; bool FilterFlag;
bool Solid; bool Solid;
bool IsNsisDeflate;
CByteBuffer Buffer; // temp buf. CByteBuffer Buffer; // temp buf.
CDecoder():
FilterFlag(false),
Solid(true),
IsNsisDeflate(true)
{}
void Release() void Release()
{ {
_filterInStream.Release(); _filterInStream.Release();

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