Compare commits

...

3 Commits
9.17 ... 9.20

Author SHA1 Message Date
Igor Pavlov
de4f8c22fe 9.20 2016-05-28 00:16:05 +01:00
Igor Pavlov
b75af1bba6 9.19 2016-05-28 00:16:04 +01:00
Igor Pavlov
c65230d858 9.18 2016-05-28 00:16:04 +01:00
115 changed files with 5053 additions and 800 deletions

View File

@@ -1,7 +1,6 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#include <stdlib.h>
#include "7zAlloc.h" #include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */ /* #define _SZ_ALLOC_DEBUG */

View File

@@ -1,14 +1,10 @@
/* 7zAlloc.h -- Allocation functions /* 7zAlloc.h -- Allocation functions
2009-02-07 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H #ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H #define __7Z_ALLOC_H
#include <stddef.h> #include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
void *SzAlloc(void *p, size_t size); void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address); void SzFree(void *p, void *address);
@@ -16,8 +12,4 @@ void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size); void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address); void SzFreeTemp(void *p, void *address);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2010-03-15 : Igor Pavlov : Public domain */ 2010-11-02 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -18,9 +18,13 @@
#define k_Copy 0 #define k_Copy 0
#define k_LZMA2 0x21 #define k_LZMA2 0x21
#define k_LZMA 0x30101 #define k_LZMA 0x30101
#define k_BCJ 0x03030103 #define k_BCJ 0x03030103
#define k_BCJ2 0x0303011B #define k_PPC 0x03030205
#define k_ARM 0x03030501
#define k_ARMT 0x03030701
#define k_SPARC 0x03030805
#define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
@@ -260,7 +264,6 @@ static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
IS_MAIN_METHOD((UInt32)c->MethodID); IS_MAIN_METHOD((UInt32)c->MethodID);
} }
#define IS_BCJ(c) ((c)->MethodID == k_BCJ && (c)->NumInStreams == 1 && (c)->NumOutStreams == 1)
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f) static SRes CheckSupportedFolder(const CSzFolder *f)
@@ -277,11 +280,24 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
} }
if (f->NumCoders == 2) if (f->NumCoders == 2)
{ {
if (!IS_BCJ(&f->Coders[1]) || CSzCoderInfo *c = &f->Coders[1];
f->NumPackStreams != 1 || f->PackStreams[0] != 0 || if (c->MethodID > (UInt32)0xFFFFFFFF ||
c->NumInStreams != 1 ||
c->NumOutStreams != 1 ||
f->NumPackStreams != 1 ||
f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 || f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) f->BindPairs[0].InIndex != 1 ||
f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
case k_BCJ:
case k_ARM:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK; return SZ_OK;
} }
if (f->NumCoders == 4) if (f->NumCoders == 4)
@@ -314,6 +330,8 @@ static UInt64 GetSum(const UInt64 *values, UInt32 index)
return sum; return sum;
} }
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
@@ -391,14 +409,6 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
#endif #endif
} }
} }
else if (coder->MethodID == k_BCJ)
{
UInt32 state;
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
}
else if (coder->MethodID == k_BCJ2) else if (coder->MethodID == k_BCJ2)
{ {
UInt64 offset = GetSum(packSizes, 1); UInt64 offset = GetSum(packSizes, 1);
@@ -425,7 +435,23 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
RINOK(res) RINOK(res)
} }
else else
return SZ_ERROR_UNSUPPORTED; {
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
switch(coder->MethodID)
{
case k_BCJ:
{
UInt32 state;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
break;
}
CASE_BRA_CONV(ARM)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
} }
return SZ_OK; return SZ_OK;
} }

View File

@@ -1,5 +1,5 @@
/* 7zIn.c -- 7z Input functions /* 7zIn.c -- 7z Input functions
2010-03-11 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -1218,12 +1218,16 @@ static SRes SzArEx_Open2(
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
Byte header[k7zStartHeaderSize]; Byte header[k7zStartHeaderSize];
Int64 startArcPos;
UInt64 nextHeaderOffset, nextHeaderSize; UInt64 nextHeaderOffset, nextHeaderSize;
size_t nextHeaderSizeT; size_t nextHeaderSizeT;
UInt32 nextHeaderCRC; UInt32 nextHeaderCRC;
CBuf buffer; CBuf buffer;
SRes res; SRes res;
startArcPos = 0;
RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
if (!TestSignatureCandidate(header)) if (!TestSignatureCandidate(header))
@@ -1235,7 +1239,7 @@ static SRes SzArEx_Open2(
nextHeaderSize = GetUi64(header + 20); nextHeaderSize = GetUi64(header + 20);
nextHeaderCRC = GetUi32(header + 28); nextHeaderCRC = GetUi32(header + 28);
p->startPosAfterHeader = k7zStartHeaderSize; p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
return SZ_ERROR_CRC; return SZ_ERROR_CRC;
@@ -1252,13 +1256,13 @@ static SRes SzArEx_Open2(
{ {
Int64 pos = 0; Int64 pos = 0;
RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
if ((UInt64)pos < nextHeaderOffset || if ((UInt64)pos < startArcPos + nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
} }
RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 17 #define MY_VER_MINOR 20
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.17 beta" #define MY_VERSION "9.20"
#define MY_DATE "2010-10-04" #define MY_DATE "2010-11-18"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2009-12-12: Igor Pavlov : Public domain */ 2010-10-26: Igor Pavlov : Public domain */
#include "CpuArch.h" #include "CpuArch.h"
@@ -72,13 +72,13 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
"cpuid" "cpuid"
: "=a" (*a) , : "=a" (*a) ,
"=b" (*b) , "=b" (*b) ,
"=c" (*c) , "=c" (*c) ,
"=d" (*d) "=d" (*d)
: "0" (function)) ; : "0" (function)) ;
#endif #endif

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2010-05-20: Igor Pavlov : Public domain */ 2010-10-26: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -40,14 +40,26 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_ARM_LE #define MY_CPU_ARM_LE
#endif #endif
#if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE
#endif
#if defined(MY_CPU_X86_OR_AMD64) #if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) #if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
#define MY_CPU_LE #define MY_CPU_LE
#endif #endif
#if defined(__BIG_ENDIAN__)
#define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian
#endif
#ifdef MY_CPU_LE_UNALIGN #ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi16(p) (*(const UInt16 *)(p))

View File

@@ -1,5 +1,5 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2010-04-16 : Igor Pavlov : Public domain */ 2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@@ -233,6 +233,22 @@ typedef struct
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a) #define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
EXTERN_C_END EXTERN_C_END
#endif #endif

View File

@@ -92,6 +92,14 @@ SOURCE=..\..\7z.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\7zAlloc.c
# End Source File
# Begin Source File
SOURCE=..\..\7zAlloc.h
# End Source File
# Begin Source File
SOURCE=..\..\7zBuf.c SOURCE=..\..\7zBuf.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -141,6 +149,10 @@ SOURCE=..\..\Bcj2.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Bra.c
# End Source File
# Begin Source File
SOURCE=..\..\Bra.h SOURCE=..\..\Bra.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -196,14 +208,6 @@ SOURCE=..\..\Types.h
# End Group # End Group
# Begin Source File # Begin Source File
SOURCE=.\7zAlloc.c
# End Source File
# Begin Source File
SOURCE=.\7zAlloc.h
# End Source File
# Begin Source File
SOURCE=.\7zMain.c SOURCE=.\7zMain.c
# End Source File # End Source File
# End Target # End Target

View File

@@ -1,16 +1,15 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2010-09-20 : Igor Pavlov : Public domain */ 2010-10-28 : Igor Pavlov : Public domain */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../../7z.h" #include "../../7z.h"
#include "../../7zAlloc.h"
#include "../../7zCrc.h" #include "../../7zCrc.h"
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../7zVersion.h" #include "../../7zVersion.h"
#include "7zAlloc.h"
#ifndef USE_WINDOWS_FILE #ifndef USE_WINDOWS_FILE
/* for mkdir */ /* for mkdir */
#ifdef _WIN32 #ifdef _WIN32
@@ -21,12 +20,6 @@
#endif #endif
#endif #endif
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#else
#define CHAR_PATH_SEPARATOR '/'
#endif
static ISzAlloc g_Alloc = { SzAlloc, SzFree }; static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static int Buf_EnsureSize(CBuf *dest, size_t size) static int Buf_EnsureSize(CBuf *dest, size_t size)
@@ -117,7 +110,14 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)
{ {
char defaultChar = '_'; char defaultChar = '_';
BOOL defUsed; BOOL defUsed;
int numChars = WideCharToMultiByte(fileMode ? (AreFileApisANSI() ? CP_ACP : CP_OEMCP) : CP_OEMCP, int numChars = WideCharToMultiByte(fileMode ?
(
#ifdef UNDER_CE
CP_ACP
#else
AreFileApisANSI() ? CP_ACP : CP_OEMCP
#endif
) : CP_OEMCP,
0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);
if (numChars == 0 || numChars >= size) if (numChars == 0 || numChars >= size)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;

View File

@@ -4,6 +4,7 @@ CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT
PROG = 7zDec.exe PROG = 7zDec.exe
C_OBJS = \ C_OBJS = \
$O\7zAlloc.obj \
$O\7zBuf.obj \ $O\7zBuf.obj \
$O\7zBuf2.obj \ $O\7zBuf2.obj \
$O\7zCrc.obj \ $O\7zCrc.obj \
@@ -13,6 +14,7 @@ C_OBJS = \
$O\7zIn.obj \ $O\7zIn.obj \
$O\7zStream.obj \ $O\7zStream.obj \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
@@ -21,7 +23,6 @@ C_OBJS = \
$O\Ppmd7Dec.obj \ $O\Ppmd7Dec.obj \
7Z_OBJS = \ 7Z_OBJS = \
$O\7zAlloc.obj \
$O\7zMain.obj \ $O\7zMain.obj \
OBJS = \ OBJS = \

View File

@@ -4,7 +4,7 @@ LIB =
RM = rm -f RM = rm -f
CFLAGS = -c -O2 -Wall CFLAGS = -c -O2 -Wall
OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
all: $(PROG) all: $(PROG)
@@ -15,7 +15,7 @@ $(PROG): $(OBJS)
$(CXX) $(CFLAGS) 7zMain.c $(CXX) $(CFLAGS) 7zMain.c
7zAlloc.o: 7zAlloc.c 7zAlloc.o: 7zAlloc.c
$(CXX) $(CFLAGS) 7zAlloc.c $(CXX) $(CFLAGS) ../../7zAlloc.c
7zBuf.o: ../../7zBuf.c 7zBuf.o: ../../7zBuf.c
$(CXX) $(CFLAGS) ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c
@@ -44,6 +44,9 @@ LzmaDec.o: ../../LzmaDec.c
Lzma2Dec.o: ../../Lzma2Dec.c Lzma2Dec.o: ../../Lzma2Dec.c
$(CXX) $(CFLAGS) ../../Lzma2Dec.c $(CXX) $(CFLAGS) ../../Lzma2Dec.c
Bra.o: ../../Bra.c
$(CXX) $(CFLAGS) ../../Bra.c
Bra86.o: ../../Bra86.c Bra86.o: ../../Bra86.c
$(CXX) $(CFLAGS) ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c

592
C/Util/SfxSetup/SfxSetup.c Executable file
View File

@@ -0,0 +1,592 @@
/* SfxSetup.c - 7z SFX Setup
2010-11-11 : Igor Pavlov : Public domain */
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#ifdef _CONSOLE
#include <stdio.h>
#endif
#include "../../7z.h"
#include "../../7zAlloc.h"
#include "../../7zCrc.h"
#include "../../7zFile.h"
#include "../../CpuArch.h"
#define k_EXE_ExtIndex 1
static const char *kExts[] =
{
"bat",
"exe",
"inf",
"msi",
#ifdef UNDER_CE
"cab",
#endif
"html",
"htm"
};
static const char *kNames[] =
{
"setup",
"install",
"run",
"start"
};
static unsigned FindExt(const wchar_t *s, unsigned *extLen)
{
unsigned len = (unsigned)wcslen(s);
unsigned i;
for (i = len; i > 0; i--)
{
if (s[i - 1] == '.')
{
*extLen = len - i;
return i - 1;
}
}
*extLen = 0;
return len;
}
#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)
{
unsigned i;
for (i = 0; i < num; i++)
{
const char *item = items[i];
unsigned itemLen = (unsigned)strlen(item);
unsigned j;
if (len != itemLen)
continue;
for (j = 0; j < len; j++)
{
unsigned c = item[j];
if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])
break;
}
if (j == len)
return i;
}
return i;
}
#ifdef _CONSOLE
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
{
ctrlType = ctrlType;
return TRUE;
}
#endif
static void PrintErrorMessage(const char *message)
{
#ifdef _CONSOLE
printf("\n7-Zip Error: %s\n", message);
#else
#ifdef UNDER_CE
WCHAR messageW[256 + 4];
unsigned i;
for (i = 0; i < 256 && message[i] != 0; i++)
messageW[i] = message[i];
messageW[i] = 0;
MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR);
#else
MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR);
#endif
#endif
}
static WRes MyCreateDir(const WCHAR *name)
{
return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
}
#ifdef UNDER_CE
#define kBufferSize (1 << 13)
#else
#define kBufferSize (1 << 15)
#endif
#define kSignatureSearchLimit (1 << 22)
static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
{
Byte buf[kBufferSize];
size_t numPrevBytes = 0;
*resPos = 0;
for (;;)
{
size_t numTests, pos;
if (*resPos > kSignatureSearchLimit)
return False;
do
{
size_t processed = kBufferSize - numPrevBytes;
if (File_Read(stream, buf + numPrevBytes, &processed) != 0)
return False;
if (processed == 0)
return False;
numPrevBytes += processed;
}
while (numPrevBytes <= k7zStartHeaderSize);
numTests = numPrevBytes - k7zStartHeaderSize;
for (pos = 0; pos < numTests; pos++)
{
for (; buf[pos] != '7' && pos < numTests; pos++);
if (pos == numTests)
break;
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))
{
*resPos += pos;
return True;
}
}
*resPos += numTests;
numPrevBytes -= numTests;
memmove(buf, buf + numTests, numPrevBytes);
}
}
static Bool DoesFileOrDirExist(const WCHAR *path)
{
WIN32_FIND_DATAW fd;
HANDLE handle;
handle = FindFirstFileW(path, &fd);
if (handle == INVALID_HANDLE_VALUE)
return False;
FindClose(handle);
return True;
}
static WRes RemoveDirWithSubItems(WCHAR *path)
{
WIN32_FIND_DATAW fd;
HANDLE handle;
WRes res = 0;
size_t len = wcslen(path);
wcscpy(path + len, L"*");
handle = FindFirstFileW(path, &fd);
path[len] = L'\0';
if (handle == INVALID_HANDLE_VALUE)
return GetLastError();
for (;;)
{
if (wcscmp(fd.cFileName, L".") != 0 &&
wcscmp(fd.cFileName, L"..") != 0)
{
wcscpy(path + len, fd.cFileName);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
wcscat(path, L"\\");
res = RemoveDirWithSubItems(path);
}
else
{
SetFileAttributesW(path, 0);
if (DeleteFileW(path) == 0)
res = GetLastError();
}
if (res != 0)
break;
}
if (!FindNextFileW(handle, &fd))
{
res = GetLastError();
if (res == ERROR_NO_MORE_FILES)
res = 0;
break;
}
}
path[len] = L'\0';
FindClose(handle);
if (res == 0)
{
if (!RemoveDirectoryW(path))
res = GetLastError();
}
return res;
}
#ifdef _CONSOLE
int MY_CDECL main()
#else
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#ifdef UNDER_CE
LPWSTR
#else
LPSTR
#endif
lpCmdLine, int nCmdShow)
#endif
{
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
SRes res = SZ_OK;
ISzAlloc allocImp;
ISzAlloc allocTempImp;
WCHAR sfxPath[MAX_PATH + 2];
WCHAR path[MAX_PATH * 3 + 2];
size_t pathLen;
DWORD winRes;
const wchar_t *cmdLineParams;
const char *errorMessage = NULL;
Bool useShellExecute = True;
#ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
#else
hInstance = hInstance;
hPrevInstance = hPrevInstance;
lpCmdLine = lpCmdLine;
nCmdShow = nCmdShow;
#endif
CrcGenerateTable();
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False);
winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
if (winRes == 0 || winRes > MAX_PATH)
return 1;
{
cmdLineParams = GetCommandLineW();
#ifndef UNDER_CE
{
Bool quoteMode = False;
for (;; cmdLineParams++)
{
wchar_t c = *cmdLineParams;
if (c == L'\"')
quoteMode = !quoteMode;
else if (c == 0 || (c == L' ' && !quoteMode))
break;
}
}
#endif
}
{
unsigned i;
DWORD d;
winRes = GetTempPathW(MAX_PATH, path);
if (winRes == 0 || winRes > MAX_PATH)
return 1;
pathLen = wcslen(path);
d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
for (i = 0;; i++, d += GetTickCount())
{
if (i >= 100)
{
res = SZ_ERROR_FAIL;
break;
}
wcscpy(path + pathLen, L"7z");
{
wchar_t *s = path + wcslen(path);
UInt32 value = d;
unsigned k;
for (k = 0; k < 8; k++)
{
unsigned t = value & 0xF;
value >>= 4;
s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[k] = '\0';
}
if (DoesFileOrDirExist(path))
continue;
if (CreateDirectoryW(path, NULL))
{
wcscat(path, L"\\");
pathLen = wcslen(path);
break;
}
if (GetLastError() != ERROR_ALREADY_EXISTS)
{
res = SZ_ERROR_FAIL;
break;
}
}
if (res != SZ_OK)
errorMessage = "Can't create temp folder";
}
if (res != SZ_OK)
{
if (!errorMessage)
errorMessage = "Error";
PrintErrorMessage(errorMessage);
return 1;
}
if (InFile_OpenW(&archiveStream.file, sfxPath) != 0)
{
errorMessage = "can not open input file";
res = SZ_ERROR_FAIL;
}
else
{
UInt64 pos = 0;
if (!FindSignature(&archiveStream.file, &pos))
res = SZ_ERROR_FAIL;
else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0)
res = SZ_ERROR_FAIL;
if (res != 0)
errorMessage = "Can't find 7z archive";
}
if (res == SZ_OK)
{
lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream);
}
SzArEx_Init(&db);
if (res == SZ_OK)
{
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
}
if (res == SZ_OK)
{
UInt32 executeFileIndex = (UInt32)(Int32)-1;
UInt32 minPrice = 1 << 30;
UInt32 i;
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
for (i = 0; i < db.db.NumFiles; i++)
{
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem *f = db.db.Files + i;
size_t len;
WCHAR *temp;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (len >= MAX_PATH)
{
res = SZ_ERROR_FAIL;
break;
}
temp = path + pathLen;
SzArEx_GetFileNameUtf16(&db, i, temp);
{
res = SzArEx_Extract(&db, &lookStream.s, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK)
break;
}
{
CSzFile outFile;
size_t processedSize;
size_t j;
size_t nameStartPos = 0;
for (j = 0; temp[j] != 0; j++)
{
if (temp[j] == '/')
{
temp[j] = 0;
MyCreateDir(path);
temp[j] = CHAR_PATH_SEPARATOR;
nameStartPos = j + 1;
}
}
if (f->IsDir)
{
MyCreateDir(path);
continue;
}
else
{
unsigned extLen;
const WCHAR *name = temp + nameStartPos;
unsigned len = (unsigned)wcslen(name);
unsigned nameLen = FindExt(temp + nameStartPos, &extLen);
unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen);
unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen);
unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12));
if (minPrice > price)
{
minPrice = price;
executeFileIndex = i;
useShellExecute = (extPrice != k_EXE_ExtIndex);
}
if (DoesFileOrDirExist(path))
{
errorMessage = "Duplicate file";
res = SZ_ERROR_FAIL;
break;
}
if (OutFile_OpenW(&outFile, path))
{
errorMessage = "Can't open output file";
res = SZ_ERROR_FAIL;
break;
}
}
processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
{
errorMessage = "Can't write output file";
res = SZ_ERROR_FAIL;
}
#ifdef USE_WINDOWS_FILE
if (f->MTimeDefined)
{
FILETIME mTime;
mTime.dwLowDateTime = f->MTime.Low;
mTime.dwHighDateTime = f->MTime.High;
SetFileTime(outFile.handle, NULL, NULL, &mTime);
}
#endif
{
SRes res2 = File_Close(&outFile);
if (res != SZ_OK)
break;
if (res2 != SZ_OK)
{
res = res2;
break;
}
}
#ifdef USE_WINDOWS_FILE
if (f->AttribDefined)
SetFileAttributesW(path, f->Attrib);
#endif
}
}
if (res == SZ_OK)
{
if (executeFileIndex == (UInt32)(Int32)-1)
{
errorMessage = "There is no file to execute";
res = SZ_ERROR_FAIL;
}
else
{
WCHAR *temp = path + pathLen;
UInt32 j;
SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp);
for (j = 0; temp[j] != 0; j++)
if (temp[j] == '/')
temp[j] = CHAR_PATH_SEPARATOR;
}
}
IAlloc_Free(&allocImp, outBuffer);
}
SzArEx_Free(&db, &allocImp);
File_Close(&archiveStream.file);
if (res == SZ_OK)
{
HANDLE hProcess = 0;
if (useShellExecute)
{
SHELLEXECUTEINFO ei;
UINT32 executeRes;
BOOL success;
memset(&ei, 0, sizeof(ei));
ei.cbSize = sizeof(ei);
ei.lpFile = path;
ei.fMask = SEE_MASK_NOCLOSEPROCESS
#ifndef UNDER_CE
| SEE_MASK_FLAG_DDEWAIT
#endif
/* | SEE_MASK_NO_CONSOLE */
;
if (wcslen(cmdLineParams) != 0)
ei.lpParameters = cmdLineParams;
ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */
success = ShellExecuteEx(&ei);
executeRes = (UINT32)(UINT_PTR)ei.hInstApp;
if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */
res = SZ_ERROR_FAIL;
else
hProcess = ei.hProcess;
}
else
{
STARTUPINFOW si;
PROCESS_INFORMATION pi;
WCHAR cmdLine[MAX_PATH * 3];
wcscpy(cmdLine, path);
wcscat(cmdLine, cmdLineParams);
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0)
res = SZ_ERROR_FAIL;
else
{
CloseHandle(pi.hThread);
hProcess = pi.hProcess;
}
}
if (hProcess != 0)
{
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
}
}
path[pathLen] = L'\0';
RemoveDirWithSubItems(path);
if (res == SZ_OK)
return 0;
{
if (res == SZ_ERROR_UNSUPPORTED)
errorMessage = "Decoder doesn't support this archive";
else if (res == SZ_ERROR_MEM)
errorMessage = "Can't allocate required memory";
else if (res == SZ_ERROR_CRC)
errorMessage = "CRC error";
else
{
if (!errorMessage)
errorMessage = "ERROR";
}
if (errorMessage)
PrintErrorMessage(errorMessage);
}
return 1;
}

198
C/Util/SfxSetup/SfxSetup.dsp Executable file
View File

@@ -0,0 +1,198 @@
# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=SfxSetup - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "SfxSetup.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "SfxSetup - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "SfxSetup - Win32 Release"
# Name "SfxSetup - Win32 Debug"
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\7z.h
# End Source File
# Begin Source File
SOURCE=..\..\7zAlloc.c
# End Source File
# Begin Source File
SOURCE=..\..\7zAlloc.h
# End Source File
# Begin Source File
SOURCE=..\..\7zBuf.c
# End Source File
# Begin Source File
SOURCE=..\..\7zBuf.h
# End Source File
# Begin Source File
SOURCE=..\..\7zCrc.c
# End Source File
# Begin Source File
SOURCE=..\..\7zCrc.h
# End Source File
# Begin Source File
SOURCE=..\..\7zCrcOpt.c
# End Source File
# Begin Source File
SOURCE=..\..\7zDec.c
# End Source File
# Begin Source File
SOURCE=..\..\7zFile.c
# End Source File
# Begin Source File
SOURCE=..\..\7zFile.h
# End Source File
# Begin Source File
SOURCE=..\..\7zIn.c
# End Source File
# Begin Source File
SOURCE=..\..\7zStream.c
# End Source File
# Begin Source File
SOURCE=..\..\Bcj2.c
# End Source File
# Begin Source File
SOURCE=..\..\Bcj2.h
# End Source File
# Begin Source File
SOURCE=..\..\Bra.c
# End Source File
# Begin Source File
SOURCE=..\..\Bra.h
# End Source File
# Begin Source File
SOURCE=..\..\Bra86.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\LzmaDec.c
# End Source File
# Begin Source File
SOURCE=..\..\LzmaDec.h
# End Source File
# Begin Source File
SOURCE=..\..\Types.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\SfxSetup.c
# End Source File
# End Target
# End Project

29
C/Util/SfxSetup/SfxSetup.dsw Executable file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

35
C/Util/SfxSetup/makefile Executable file
View File

@@ -0,0 +1,35 @@
PROG = 7zS2.sfx
LIBS = $(LIBS)
CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE
C_OBJS = \
$O\7zAlloc.obj \
$O\7zBuf.obj \
$O\7zBuf2.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \
$O\7zDec.obj \
$O\7zIn.obj \
$O\7zStream.obj \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\CpuArch.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
7Z_OBJS = \
$O\SfxSetup.obj \
OBJS = \
$(7Z_OBJS) \
$(C_OBJS) \
$O\resource.res
!include "../../../CPP/Build.mak"
$(7Z_OBJS): $(*B).c
$(COMPL_O1)
$(C_OBJS): ../../$(*B).c
$(COMPL_O1)

35
C/Util/SfxSetup/makefile_con Executable file
View File

@@ -0,0 +1,35 @@
PROG = 7zS2con.sfx
LIBS = $(LIBS)
CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE
C_OBJS = \
$O\7zAlloc.obj \
$O\7zBuf.obj \
$O\7zBuf2.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \
$O\7zDec.obj \
$O\7zIn.obj \
$O\7zStream.obj \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\CpuArch.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
7Z_OBJS = \
$O\SfxSetup.obj \
OBJS = \
$(7Z_OBJS) \
$(C_OBJS) \
$O\resource.res
!include "../../../CPP/Build.mak"
$(7Z_OBJS): $(*B).c
$(COMPL_O1)
$(C_OBJS): ../../$(*B).c
$(COMPL_O1)

6
C/Util/SfxSetup/resource.rc Executable file
View File

@@ -0,0 +1,6 @@
#include "../../../CPP/7zip/MyVersionInfo.rc"
MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx")
1 ICON "setup.ico"

BIN
C/Util/SfxSetup/setup.ico Executable file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -193,11 +193,9 @@ HRESULT CEncoder::Encode(
// UInt64 outStreamStartPos; // UInt64 outStreamStartPos;
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
new CSequentialOutStreamSizeCount;
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
inStreamSizeCountSpec->Init(inStream); inStreamSizeCountSpec->Init(inStream);
@@ -226,13 +224,11 @@ HRESULT CEncoder::Encode(
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
if (writeCoderProperties != NULL) if (writeCoderProperties != NULL)
{ {
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init(); outStreamSpec->Init();
writeCoderProperties->WriteCoderProperties(outStream); writeCoderProperties->WriteCoderProperties(outStream);
size_t size = outStreamSpec->GetSize(); outStreamSpec->CopyToBuffer(encodingInfo.Props);
encodingInfo.Props.SetCapacity(size);
memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size);
} }
} }
@@ -250,8 +246,7 @@ HRESULT CEncoder::Encode(
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
folderItem);
packSizes.Add(outStreamSizeCountSpec->GetSize()); packSizes.Add(outStreamSizeCountSpec->GetSize());

View File

@@ -280,28 +280,46 @@ void CInByte2::ReadString(UString &s)
_pos += rem + 2; _pos += rem + 2;
} }
static inline bool TestSignatureCandidate(const Byte *p) static inline bool TestSignature(const Byte *p)
{ {
for (int i = 0; i < kSignatureSize; i++) for (int i = 0; i < kSignatureSize; i++)
if (p[i] != kSignature[i]) if (p[i] != kSignature[i])
return false; return false;
return (p[0x1A] == 0 && p[0x1B] == 0); return CrcCalc(p + 12, 20) == GetUi32(p + 8);
} }
#ifdef FORMAT_7Z_RECOVERY
static inline bool TestSignature2(const Byte *p)
{
int i;
for (i = 0; i < kSignatureSize; i++)
if (p[i] != kSignature[i])
return false;
if (CrcCalc(p + 12, 20) == GetUi32(p + 8))
return true;
for (i = 8; i < kHeaderSize; i++)
if (p[i] != 0)
return false;
return (p[6] != 0 || p[7] != 0);
}
#else
#define TestSignature2(p) TestSignature(p)
#endif
HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{ {
RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));
if (TestSignatureCandidate(_header)) if (TestSignature2(_header))
return S_OK; return S_OK;
CByteBuffer byteBuffer; CByteBuffer byteBuffer;
const UInt32 kBufferSize = (1 << 16); const UInt32 kBufferSize = (1 << 16);
byteBuffer.SetCapacity(kBufferSize); byteBuffer.SetCapacity(kBufferSize);
Byte *buffer = byteBuffer; Byte *buffer = byteBuffer;
UInt32 numPrevBytes = kHeaderSize - 1; UInt32 numPrevBytes = kHeaderSize;
memcpy(buffer, _header + 1, numPrevBytes); memcpy(buffer, _header, kHeaderSize);
UInt64 curTestPos = _arhiveBeginStreamPosition + 1; UInt64 curTestPos = _arhiveBeginStreamPosition;
for (;;) for (;;)
{ {
if (searchHeaderSizeLimit != NULL) if (searchHeaderSizeLimit != NULL)
@@ -316,14 +334,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (processedSize == 0) if (processedSize == 0)
return S_FALSE; return S_FALSE;
} }
while (numPrevBytes < kHeaderSize); while (numPrevBytes <= kHeaderSize);
UInt32 numTests = numPrevBytes - kHeaderSize + 1; UInt32 numTests = numPrevBytes - kHeaderSize;
for (UInt32 pos = 0; pos < numTests; pos++) for (UInt32 pos = 0; pos < numTests; pos++)
{ {
for (; buffer[pos] != '7' && pos < numTests; pos++); for (; buffer[pos] != '7' && pos < numTests; pos++);
if (pos == numTests) if (pos == numTests)
break; break;
if (TestSignatureCandidate(buffer + pos)) if (TestSignature(buffer + pos))
{ {
memcpy(_header, buffer + pos, kHeaderSize); memcpy(_header, buffer + pos, kHeaderSize);
curTestPos += pos; curTestPos += pos;
@@ -812,7 +830,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
ThrowUnsupported(); ThrowUnsupported();
data.SetCapacity(unpackSize); data.SetCapacity(unpackSize);
CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init(data, unpackSize); outStreamSpec->Init(data, unpackSize);
@@ -1164,23 +1182,24 @@ HRESULT CInArchive::ReadDatabase2(
nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
} }
else
#endif #endif
{
#ifdef FORMAT_7Z_RECOVERY if (crc != crcFromArchive)
crcFromArchive = crc; ThrowIncorrect();
#endif }
db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
if (crc != crcFromArchive)
ThrowIncorrect();
if (nextHeaderSize == 0) if (nextHeaderSize == 0)
return S_OK; return S_OK;
if (nextHeaderSize > (UInt64)0xFFFFFFFF) if (nextHeaderSize > (UInt64)0xFFFFFFFF)
return S_FALSE; return S_FALSE;
if ((Int64)nextHeaderOffset < 0)
return S_FALSE;
RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
CByteBuffer buffer2; CByteBuffer buffer2;

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/Types.h"
#include "ItemNameUtils.h" #include "ItemNameUtils.h"
namespace NArchive { namespace NArchive {

View File

@@ -6,72 +6,61 @@
STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
if(processedSize != NULL) if (processedSize)
*processedSize = 0; *processedSize = 0;
while(_streamIndex < Streams.Size() && size > 0) if (size == 0)
return S_OK;
if (_pos >= _totalLength)
return (_pos == _totalLength) ? S_OK : E_FAIL;
{ {
CSubStreamInfo &s = Streams[_streamIndex]; int left = 0, mid = _streamIndex, right = Streams.Size();
if (_pos == s.Size) for (;;)
{ {
_streamIndex++; CSubStreamInfo &m = Streams[mid];
_pos = 0; if (_pos < m.GlobalOffset)
continue; right = mid;
else if (_pos >= m.GlobalOffset + m.Size)
left = mid + 1;
else
{
_streamIndex = mid;
break;
}
mid = (left + right) / 2;
} }
RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); _streamIndex = mid;
UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
UInt32 realProcessed;
HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
if(processedSize != NULL)
*processedSize += realProcessed;
_pos += realProcessed;
_seekPos += realProcessed;
RINOK(result);
break;
} }
return S_OK;
CSubStreamInfo &s = Streams[_streamIndex];
UInt64 localPos = _pos - s.GlobalOffset;
if (localPos != s.LocalPos)
{
RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
}
UInt64 rem = s.Size - localPos;
if (size > rem)
size = (UInt32)rem;
HRESULT result = s.Stream->Read(data, size, &size);
_pos += size;
s.LocalPos += size;
if (processedSize)
*processedSize = size;
return result;
} }
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
UInt64 *newPosition)
{ {
UInt64 newPos;
switch(seekOrigin) switch(seekOrigin)
{ {
case STREAM_SEEK_SET: case STREAM_SEEK_SET: _pos = offset; break;
newPos = offset; case STREAM_SEEK_CUR: _pos = _pos + offset; break;
break; case STREAM_SEEK_END: _pos = _totalLength + offset; break;
case STREAM_SEEK_CUR: default: return STG_E_INVALIDFUNCTION;
newPos = _seekPos + offset;
break;
case STREAM_SEEK_END:
newPos = _totalLength + offset;
break;
default:
return STG_E_INVALIDFUNCTION;
} }
_seekPos = 0; if (newPosition != 0)
for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) *newPosition = _pos;
{ return S_OK;
UInt64 size = Streams[_streamIndex].Size;
if (newPos < _seekPos + size)
{
_pos = newPos - _seekPos;
_seekPos += _pos;
if (newPosition != 0)
*newPosition = newPos;
return S_OK;
}
_seekPos += size;
}
if (newPos == _seekPos)
{
if (newPosition != 0)
*newPosition = newPos;
return S_OK;
}
return E_FAIL;
} }

View File

@@ -1,36 +1,44 @@
// MultiStream.h // MultiStream.h
#ifndef __MULTISTREAM_H #ifndef __MULTI_STREAM_H
#define __MULTISTREAM_H #define __MULTI_STREAM_H
#include "../../../Common/MyCom.h" #include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h" #include "../../../Common/MyVector.h"
#include "../../Archive/IArchive.h"
#include "../../IStream.h"
class CMultiStream: class CMultiStream:
public IInStream, public IInStream,
public CMyUnknownImp public CMyUnknownImp
{ {
int _streamIndex;
UInt64 _pos; UInt64 _pos;
UInt64 _seekPos;
UInt64 _totalLength; UInt64 _totalLength;
int _streamIndex;
public: public:
struct CSubStreamInfo struct CSubStreamInfo
{ {
CMyComPtr<IInStream> Stream; CMyComPtr<IInStream> Stream;
UInt64 Pos;
UInt64 Size; UInt64 Size;
UInt64 GlobalOffset;
UInt64 LocalPos;
}; };
CObjectVector<CSubStreamInfo> Streams; CObjectVector<CSubStreamInfo> Streams;
void Init()
HRESULT Init()
{ {
_streamIndex = 0; UInt64 total = 0;
_pos = 0;
_seekPos = 0;
_totalLength = 0;
for (int i = 0; i < Streams.Size(); i++) for (int i = 0; i < Streams.Size(); i++)
_totalLength += Streams[i].Size; {
CSubStreamInfo &s = Streams[i];
s.GlobalOffset = total;
total += Streams[i].Size;
RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));
}
_totalLength = total;
_pos = 0;
_streamIndex = 0;
return S_OK;
} }
MY_UNKNOWN_IMP1(IInStream) MY_UNKNOWN_IMP1(IInStream)

View File

@@ -0,0 +1,644 @@
// CramfsHandler.cpp
#include "StdAfx.h"
#include "../../../C/7zCrc.h"
#include "../../../C/CpuArch.h"
#include "../../../C/Alloc.h"
#include "Common/ComTry.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariantUtils.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
#include "../Compress/ZlibDecoder.h"
namespace NArchive {
namespace NCramfs {
#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
static const UInt32 kSignatureSize = 16;
static const char kSignature[kSignatureSize] = SIGNATURE;
static const UInt32 kArcSizeMax = (256 + 16) << 20;
static const UInt32 kNumFilesMax = (1 << 19);
static const unsigned kNumDirLevelsMax = (1 << 8);
static const UInt32 kHeaderSize = 0x40;
static const unsigned kHeaderNameSize = 16;
static const UInt32 kNodeSize = 12;
static const UInt32 kFlag_FsVer2 = (1 << 0);
static const CUInt32PCharPair k_Flags[] =
{
{ 0, "Ver2" },
{ 1, "SortedDirs" },
{ 8, "Holes" },
{ 9, "WrongSignature" },
{ 10, "ShiftedRootOffset" }
};
static const unsigned kBlockSizeLog = 12;
static const UInt32 kBlockSize = 1 << kBlockSizeLog;
/*
struct CNode
{
UInt16 Mode;
UInt16 Uid;
UInt32 Size;
Byte Gid;
UInt32 NameLen;
UInt32 Offset;
void Parse(const Byte *p)
{
Mode = GetUi16(p);
Uid = GetUi16(p + 2);
Size = Get32(p + 4) & 0xFFFFFF;
Gid = p[7];
NameLen = p[8] & 0x3F;
Offset = Get32(p + 8) >> 6;
}
};
*/
#define Get32(p) (be ? GetBe32(p) : GetUi32(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 UInt32 GetSize(const Byte *p, bool be)
{
if (be)
return GetBe32(p + 4) >> 8;
else
return GetUi32(p + 4) & 0xFFFFFF;
}
static UInt32 GetNameLen(const Byte *p, bool be)
{
if (be)
return (p[8] & 0xFC);
else
return (p[8] & 0x3F) << 2;
}
static UInt32 GetOffset(const Byte *p, bool be)
{
if (be)
return (GetBe32(p + 8) & 0x03FFFFFF) << 2;
else
return GetUi32(p + 8) >> 6 << 2;
}
struct CItem
{
UInt32 Offset;
int Parent;
};
struct CHeader
{
bool be;
UInt32 Size;
UInt32 Flags;
// UInt32 Future;
UInt32 Crc;
// UInt32 Edition;
UInt32 NumBlocks;
UInt32 NumFiles;
char Name[kHeaderNameSize];
bool Parse(const Byte *p)
{
if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
return false;
switch(GetUi32(p))
{
case 0x28CD3D45: be = false; break;
case 0x453DCD28: be = true; break;
default: return false;
}
Size = Get32(p + 4);
Flags = Get32(p + 8);
// Future = Get32(p + 0xC);
Crc = Get32(p + 0x20);
// Edition = Get32(p + 0x24);
NumBlocks = Get32(p + 0x28);
NumFiles = Get32(p + 0x2C);
memcpy(Name, p + 0x30, kHeaderNameSize);
return true;
}
bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }
};
class CHandler:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
CRecordVector<CItem> _items;
CMyComPtr<IInStream> _stream;
Byte *_data;
UInt32 _size;
UInt32 _headersSize;
AString _errorMessage;
CHeader _h;
// Current file
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
CMyComPtr<ICompressCoder> _zlibDecoder;
CBufInStream *_inStreamSpec;
CMyComPtr<ISequentialInStream> _inStream;
CBufPtrSeqOutStream *_outStreamSpec;
CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _curBlocksOffset;
UInt32 _curNumBlocks;
HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);
HRESULT Open2(IInStream *inStream);
AString GetPath(int index) const;
bool GetPackSize(int index, UInt32 &res) const;
void Free();
public:
CHandler(): _data(0) {}
~CHandler() { Free(); }
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
};
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI4},
{ NULL, kpidPackSize, VT_UI4},
{ NULL, kpidPosixAttrib, VT_UI4}
// { NULL, kpidOffset, VT_UI4}
};
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidName, VT_BSTR},
{ NULL, kpidBigEndian, VT_BOOL},
{ NULL, kpidCharacts, VT_BSTR},
{ NULL, kpidPhySize, VT_UI4},
{ NULL, kpidHeadersSize, VT_UI4},
{ NULL, kpidNumSubFiles, VT_UI4},
{ NULL, kpidNumBlocks, VT_UI4}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
{
const Byte *p = _data + baseOffset;
bool be = _h.be;
if (!IsDir(p, be))
return S_OK;
UInt32 offset = GetOffset(p, be);
UInt32 size = GetSize(p, be);
if (offset == 0 && size == 0)
return S_OK;
UInt32 end = offset + size;
if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)
return S_FALSE;
if (end > _headersSize)
_headersSize = end;
int startIndex = _items.Size();
while (size != 0)
{
if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)
return S_FALSE;
CItem item;
item.Parent = parent;
item.Offset = offset;
_items.Add(item);
UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);
if (size < nodeLen)
return S_FALSE;
offset += nodeLen;
size -= nodeLen;
}
int endIndex = _items.Size();
for (int i = startIndex; i < endIndex; i++)
{
RINOK(OpenDir(i, _items[i].Offset, level + 1));
}
return S_OK;
}
HRESULT CHandler::Open2(IInStream *inStream)
{
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
if (!_h.Parse(buf))
return S_FALSE;
if (_h.IsVer2())
{
if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)
return S_FALSE;
}
else
{
UInt64 size;
RINOK(inStream->Seek(0, STREAM_SEEK_END, &size));
if (size > kArcSizeMax)
return S_FALSE;
_h.Size = (UInt32)size;
RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
}
_data = (Byte *)MidAlloc(_h.Size);
if (_data == 0)
return E_OUTOFMEMORY;
memcpy(_data, buf, kHeaderSize);
size_t processed = _h.Size - kHeaderSize;
RINOK(ReadStream(inStream, _data + kHeaderSize, &processed));
if (processed < kNodeSize)
return S_FALSE;
_size = kHeaderSize + (UInt32)processed;
if (_size != _h.Size)
_errorMessage = "Unexpected end of archive";
else
{
SetUi32(_data + 0x20, 0);
if (_h.IsVer2())
if (CrcCalc(_data, _h.Size) != _h.Crc)
_errorMessage = "CRC error";
}
if (_h.IsVer2())
_items.Reserve(_h.NumFiles - 1);
return OpenDir(-1, kHeaderSize, 0);
}
AString CHandler::GetPath(int index) const
{
unsigned len = 0;
int indexMem = index;
do
{
const CItem &item = _items[index];
index = item.Parent;
const Byte *p = _data + item.Offset;
unsigned size = GetNameLen(p, _h.be);
p += kNodeSize;
unsigned i;
for (i = 0; i < size && p[i]; i++);
len += i + 1;
}
while (index >= 0);
len--;
AString path;
char *dest = path.GetBuffer(len) + len;
index = indexMem;
for (;;)
{
const CItem &item = _items[index];
index = item.Parent;
const Byte *p = _data + item.Offset;
unsigned size = GetNameLen(p, _h.be);
p += kNodeSize;
unsigned i;
for (i = 0; i < size && p[i]; i++);
dest -= i;
memcpy(dest, p, i);
if (index < 0)
break;
*(--dest) = CHAR_PATH_SEPARATOR;
}
path.ReleaseBuffer(len);
return path;
}
bool CHandler::GetPackSize(int index, UInt32 &res) const
{
const CItem &item = _items[index];
const Byte *p = _data + item.Offset;
bool be = _h.be;
UInt32 offset = GetOffset(p, be);
if (offset < kHeaderSize)
return false;
UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog;
UInt32 start = offset + numBlocks * 4;
if (start > _size)
return false;
UInt32 end = Get32(_data + start - 4);
if (end < start)
return false;
res = end - start;
return true;
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */)
{
COM_TRY_BEGIN
{
Close();
RINOK(Open2(stream));
_stream = stream;
}
return S_OK;
COM_TRY_END
}
void CHandler::Free()
{
MidFree(_data);
_data = 0;
}
STDMETHODIMP CHandler::Close()
{
_headersSize = 0;
_items.Clear();
_stream.Release();
_errorMessage.Empty();
Free();
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _items.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidName:
{
char dest[kHeaderNameSize + 4];
memcpy(dest, _h.Name, kHeaderNameSize);
dest[kHeaderNameSize] = 0;
prop = dest;
break;
}
case kpidBigEndian: prop = _h.be; break;
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;
case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;
case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break;
case kpidHeadersSize: prop = _headersSize; break;
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
const CItem &item = _items[index];
const Byte *p = _data + item.Offset;
bool be = _h.be;
bool isDir = IsDir(p, be);
switch(propID)
{
case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
case kpidIsDir: prop = isDir; break;
// case kpidOffset: prop = (UInt32)GetOffset(p, be); break;
case kpidSize: if (!isDir) prop = GetSize(p, be); break;
case kpidPackSize:
if (!isDir)
{
UInt32 size;
if (GetPackSize(index, size))
prop = size;
}
break;
case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
class CCramfsInStream: public CCachedInStream
{
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
public:
CHandler *Handler;
};
HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
{
return Handler->ReadBlock(blockIndex, dest, blockSize);
}
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
{
if (!_zlibDecoder)
{
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
_zlibDecoder = _zlibDecoderSpec;
}
if (!_inStream)
{
_inStreamSpec = new CBufInStream();
_inStream = _inStreamSpec;
}
if (!_outStream)
{
_outStreamSpec = new CBufPtrSeqOutStream();
_outStream = _outStreamSpec;
}
bool be = _h.be;
const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));
UInt32 end = Get32(p);
if (end < start || end > _size)
return S_FALSE;
UInt32 inSize = end - start;
_inStreamSpec->Init(_data + start, inSize);
_outStreamSpec->Init(dest, blockSize);
RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL));
return (_zlibDecoderSpec->GetInputProcessedSize() == inSize &&
_outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = _items.Size();
if (numItems == 0)
return S_OK;
bool be = _h.be;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;
if (!IsDir(p, be))
totalSize += GetSize(p, be);
}
extractCallback->SetTotal(totalSize);
UInt64 totalPackSize;
totalSize = totalPackSize = 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 = totalPackSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &outStream, askMode));
const Byte *p = _data + item.Offset;
if (IsDir(p, be))
{
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue;
}
UInt32 curSize = GetSize(p, be);
totalSize += curSize;
UInt32 packSize;
if (GetPackSize(index, packSize))
totalPackSize += packSize;
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
UInt32 offset = GetOffset(p, be);
if (offset < kHeaderSize)
curSize = 0;
int res = NExtract::NOperationResult::kDataError;
{
CMyComPtr<ISequentialInStream> inSeqStream;
CMyComPtr<IInStream> inStream;
HRESULT hres = GetStream(index, &inSeqStream);
if (inSeqStream)
inSeqStream.QueryInterface(IID_IInStream, &inStream);
if (hres == E_OUTOFMEMORY)
return E_OUTOFMEMORY;
if (hres == S_FALSE || !inStream)
res = NExtract::NOperationResult::kUnSupportedMethod;
else
{
RINOK(hres);
if (inStream)
{
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
if (hres != S_OK && hres != S_FALSE)
{
RINOK(hres);
}
if (copyCoderSpec->TotalSize == curSize && hres == S_OK)
res = NExtract::NOperationResult::kOK;
}
}
}
RINOK(extractCallback->SetOperationResult(res));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItem &item = _items[index];
const Byte *p = _data + item.Offset;
bool be = _h.be;
if (IsDir(p, be))
return E_FAIL;
UInt32 size = GetSize(p, be);
UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog;
UInt32 offset = GetOffset(p, be);
if (offset < kHeaderSize)
{
if (offset != 0)
return S_FALSE;
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
streamSpec->Init(NULL, 0);
*stream = streamTemp.Detach();
return S_OK;
}
if (offset + numBlocks * 4 > _size)
return S_FALSE;
UInt32 prev = offset;
for (UInt32 i = 0; i < numBlocks; i++)
{
UInt32 next = Get32(_data + offset + i * 4);
if (next < prev || next > _size)
return S_FALSE;
prev = next;
}
CCramfsInStream *streamSpec = new CCramfsInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
_curNumBlocks = numBlocks;
_curBlocksOffset = offset;
streamSpec->Handler = this;
if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog))
return E_OUTOFMEMORY;
streamSpec->Init(size);
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
}
static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; }
static CArcInfo g_ArcInfo =
{ L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
REGISTER_ARC(Cramfs)
}}

View File

@@ -277,9 +277,9 @@ static const CUInt32PCharPair g_AbiOS[] =
static const CUInt32PCharPair g_SegmentFlags[] = static const CUInt32PCharPair g_SegmentFlags[] =
{ {
{ 1 << 0, "Execute" }, { 0, "Execute" },
{ 1 << 1, "Write" }, { 1, "Write" },
{ 1 << 2, "Read" } { 2, "Read" }
}; };
static const char *g_Types[] = static const char *g_Types[] =

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -24,7 +24,7 @@ using namespace NTime;
namespace NArchive { namespace NArchive {
namespace NIso { namespace NIso {
static STATPROPSTG kProps[] = static const STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
@@ -33,8 +33,17 @@ static STATPROPSTG kProps[] =
{ NULL, kpidMTime, VT_FILETIME} { NULL, kpidMTime, VT_FILETIME}
}; };
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidMTime, VT_FILETIME}
// { NULL, kpidPhySize, VT_UI8},
// { NULL, kpidHeadersSize, VT_UI8}
};
IMP_IInArchive_Props IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */, const UInt64 * /* maxCheckStartPosition */,
@@ -66,6 +75,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
static void AddString(AString &s, const char *name, const Byte *p, int size)
{
int i;
for (i = 0; i < size && p[i]; i++);
for (; i > 0 && p[i - 1] == ' '; i--);
if (i != 0)
{
AString d;
memcpy(d.GetBuffer(i), p, i);
d.ReleaseBuffer(i);
s += '\n';
s += name;
s += ": ";
s += d;
}
}
#define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v))
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex];
switch(propID)
{
case kpidComment:
{
AString s;
ADD_STRING("System", SystemId);
ADD_STRING("Volume", VolumeId);
ADD_STRING("VolumeSet", VolumeSetId);
ADD_STRING("Publisher", PublisherId);
ADD_STRING("Preparer", DataPreparerId);
ADD_STRING("Application", ApplicationId);
ADD_STRING("Copyright", CopyrightFileId);
ADD_STRING("Abstract", AbstractFileId);
ADD_STRING("Bib", BibFileId);
prop = s;
break;
}
case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; }
case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; }
// case kpidPhySize: break;
// case kpidHeadersSize: break;
case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
@@ -87,9 +148,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = (const wchar_t *)s; prop = (const wchar_t *)s;
break; break;
} }
case kpidIsDir: case kpidIsDir: prop = false; break;
prop = false;
break;
case kpidSize: case kpidSize:
case kpidPackSize: case kpidPackSize:
prop = (UInt64)_archive.GetBootItemSize(index); prop = (UInt64)_archive.GetBootItemSize(index);
@@ -121,9 +180,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = (const wchar_t *)NItemName::GetOSName2(s); prop = (const wchar_t *)NItemName::GetOSName2(s);
} }
break; break;
case kpidIsDir: case kpidIsDir: prop = item.IsDir(); break;
prop = item.IsDir();
break;
case kpidSize: case kpidSize:
case kpidPackSize: case kpidPackSize:
if (!item.IsDir()) if (!item.IsDir())
@@ -131,16 +188,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break; break;
case kpidMTime: case kpidMTime:
{ {
FILETIME utcFileTime; FILETIME utc;
if (item.DateTime.GetFileTime(utcFileTime)) if (item.DateTime.GetFileTime(utc))
prop = utcFileTime; prop = utc;
/*
else
{
utcFileTime.dwLowDateTime = 0;
utcFileTime.dwHighDateTime = 0;
}
*/
break; break;
} }
} }

View File

@@ -65,7 +65,7 @@ UInt16 CInArchive::ReadUInt16()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
if (b[i] != b[3 - i]) if (b[i] != b[3 - i])
throw 1; IncorrectBigEndian = true;
value |= ((UInt16)(b[i]) << (8 * i)); value |= ((UInt16)(b[i]) << (8 * i));
} }
return (UInt16)value; return (UInt16)value;
@@ -440,6 +440,7 @@ HRESULT CInArchive::Open(IInStream *inStream)
void CInArchive::Clear() void CInArchive::Clear()
{ {
IncorrectBigEndian = false;
Refs.Clear(); Refs.Clear();
_rootDir.Clear(); _rootDir.Clear();
VolDescs.Clear(); VolDescs.Clear();

View File

@@ -111,6 +111,20 @@ struct CDateTime
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
bool GetFileTime(FILETIME &ft) const
{
UInt64 value;
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
if (res)
{
value -= (UInt64)((Int64)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
ft.dwHighDateTime = (DWORD)(value >> 32);
return res;
}
}; };
struct CBootRecordDescriptor struct CBootRecordDescriptor
@@ -268,6 +282,7 @@ public:
int MainVolDescIndex; int MainVolDescIndex;
UInt32 BlockSize; UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries; CObjectVector<CBootInitialEntry> BootEntries;
bool IncorrectBigEndian;
bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }

View File

@@ -266,7 +266,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
return (startHeader[0] == 0) ? S_OK: S_FALSE; return (startHeader[0] == 0) ? S_OK: S_FALSE;
const Byte *p = header; const Byte *p = header;
memmove(item.Method, p, kMethodIdSize); memcpy(item.Method, p, kMethodIdSize);
if (!item.IsValidMethod()) if (!item.IsValidMethod())
return S_OK; return S_OK;
p += kMethodIdSize; p += kMethodIdSize;

View File

@@ -77,16 +77,16 @@ static const char *g_FileTypes[] =
static const CUInt32PCharPair g_Flags[] = static const CUInt32PCharPair g_Flags[] =
{ {
{ (UInt32)1 << 31, "PURE_INSTRUCTIONS" }, { 31, "PURE_INSTRUCTIONS" },
{ 1 << 30, "NO_TOC" }, { 30, "NO_TOC" },
{ 1 << 29, "STRIP_STATIC_SYMS" }, { 29, "STRIP_STATIC_SYMS" },
{ 1 << 28, "NO_DEAD_STRIP" }, { 28, "NO_DEAD_STRIP" },
{ 1 << 27, "LIVE_SUPPORT" }, { 27, "LIVE_SUPPORT" },
{ 1 << 26, "SELF_MODIFYING_CODE" }, { 26, "SELF_MODIFYING_CODE" },
{ 1 << 25, "DEBUG" }, { 25, "DEBUG" },
{ 1 << 10, "SOME_INSTRUCTIONS" }, { 10, "SOME_INSTRUCTIONS" },
{ 1 << 9, "EXT_RELOC" }, { 9, "EXT_RELOC" },
{ 1 << 8, "LOC_RELOC" } { 8, "LOC_RELOC" }
}; };
static const CUInt32PCharPair g_MachinePairs[] = static const CUInt32PCharPair g_MachinePairs[] =

View File

@@ -300,53 +300,53 @@ void CSection::Parse(const Byte *p)
static const CUInt32PCharPair g_HeaderCharacts[] = static const CUInt32PCharPair g_HeaderCharacts[] =
{ {
{ 1 << 1, "Executable" }, { 1, "Executable" },
{ 1 << 13, "DLL" }, { 13, "DLL" },
{ 1 << 8, "32-bit" }, { 8, "32-bit" },
{ 1 << 5, "LargeAddress" }, { 5, "LargeAddress" },
{ 1 << 0, "NoRelocs" }, { 0, "NoRelocs" },
{ 1 << 2, "NoLineNums" }, { 2, "NoLineNums" },
{ 1 << 3, "NoLocalSyms" }, { 3, "NoLocalSyms" },
{ 1 << 4, "AggressiveWsTrim" }, { 4, "AggressiveWsTrim" },
{ 1 << 9, "NoDebugInfo" }, { 9, "NoDebugInfo" },
{ 1 << 10, "RemovableRun" }, { 10, "RemovableRun" },
{ 1 << 11, "NetRun" }, { 11, "NetRun" },
{ 1 << 12, "System" }, { 12, "System" },
{ 1 << 14, "UniCPU" }, { 14, "UniCPU" },
{ 1 << 7, "Little-Endian" }, { 7, "Little-Endian" },
{ 1 << 15, "Big-Endian" } { 15, "Big-Endian" }
}; };
static const CUInt32PCharPair g_DllCharacts[] = static const CUInt32PCharPair g_DllCharacts[] =
{ {
{ 1 << 6, "Relocated" }, { 6, "Relocated" },
{ 1 << 7, "Integrity" }, { 7, "Integrity" },
{ 1 << 8, "NX-Compatible" }, { 8, "NX-Compatible" },
{ 1 << 9, "NoIsolation" }, { 9, "NoIsolation" },
{ 1 << 10, "NoSEH" }, { 10, "NoSEH" },
{ 1 << 11, "NoBind" }, { 11, "NoBind" },
{ 1 << 13, "WDM" }, { 13, "WDM" },
{ 1 << 15, "TerminalServerAware" } { 15, "TerminalServerAware" }
}; };
static const CUInt32PCharPair g_SectFlags[] = static const CUInt32PCharPair g_SectFlags[] =
{ {
{ 1 << 3, "NoPad" }, { 3, "NoPad" },
{ 1 << 5, "Code" }, { 5, "Code" },
{ 1 << 6, "InitializedData" }, { 6, "InitializedData" },
{ 1 << 7, "UninitializedData" }, { 7, "UninitializedData" },
{ 1 << 9, "Comments" }, { 9, "Comments" },
{ 1 << 11, "Remove" }, { 11, "Remove" },
{ 1 << 12, "COMDAT" }, { 12, "COMDAT" },
{ 1 << 15, "GP" }, { 15, "GP" },
{ 1 << 24, "ExtendedRelocations" }, { 24, "ExtendedRelocations" },
{ 1 << 25, "Discardable" }, { 25, "Discardable" },
{ 1 << 26, "NotCached" }, { 26, "NotCached" },
{ 1 << 27, "NotPaged" }, { 27, "NotPaged" },
{ 1 << 28, "Shared" }, { 28, "Shared" },
{ 1 << 29, "Execute" }, { 29, "Execute" },
{ 1 << 30, "Read" }, { 30, "Read" },
{ (UInt32)1 << 31, "Write" } { 31, "Write" }
}; };
static const CUInt32PCharPair g_MachinePairs[] = static const CUInt32PCharPair g_MachinePairs[] =
@@ -1723,6 +1723,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
size_t offset = item.Offset - sect.Va; size_t offset = item.Offset - sect.Va;
if (!CheckItem(sect, item, offset)) if (!CheckItem(sect, item, offset))
return S_FALSE; return S_FALSE;
if (item.HeaderSize == 0)
{
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<IInStream> streamTemp2 = streamSpec;
streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);
*stream = streamTemp2.Detach();
return S_OK;
}
referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size); referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size);
memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);

View File

@@ -7,6 +7,7 @@
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
#include "Windows/PropVariantUtils.h"
#include "Windows/Time.h" #include "Windows/Time.h"
#include "../../IPassword.h" #include "../../IPassword.h"
@@ -46,7 +47,21 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
static const wchar_t *kUnknownOS = L"Unknown"; static const wchar_t *kUnknownOS = L"Unknown";
STATPROPSTG kProps[] = static const CUInt32PCharPair k_Flags[] =
{
{ 0, "Volume" },
{ 1, "Comment" },
{ 2, "Lock" },
{ 3, "Solid" },
{ 4, "NewVolName" }, // pack_comment in old versuons
{ 5, "Authenticity" },
{ 6, "Recovery" },
{ 7, "BlockEncryption" },
{ 8, "FirstVolume" },
{ 9, "EncryptVer" }
};
static const STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
@@ -68,8 +83,9 @@ STATPROPSTG kProps[] =
{ NULL, kpidUnpackVer, VT_UI1} { NULL, kpidUnpackVer, VT_UI1}
}; };
STATPROPSTG kArcProps[] = static const STATPROPSTG kArcProps[] =
{ {
{ NULL, kpidCharacts, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL}, { NULL, kpidSolid, VT_BOOL},
{ NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidNumBlocks, VT_UI4},
// { NULL, kpidEncrypted, VT_BOOL}, // { NULL, kpidEncrypted, VT_BOOL},
@@ -93,11 +109,12 @@ UInt64 CHandler::GetPackSize(int refIndex) const
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 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 kpidSolid: prop = _archiveInfo.IsSolid(); break; case kpidSolid: prop = _archiveInfo.IsSolid(); break;
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _archiveInfo.Flags, prop); break;
// case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names. // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names.
case kpidIsVolume: prop = _archiveInfo.IsVolume(); break; case kpidIsVolume: prop = _archiveInfo.IsVolume(); break;
case kpidNumVolumes: prop = (UInt32)_archives.Size(); break; case kpidNumVolumes: prop = (UInt32)_archives.Size(); break;
@@ -112,10 +129,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = (UInt32)numBlocks; prop = (UInt32)numBlocks;
break; break;
} }
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
// COM_TRY_END COM_TRY_END
} }
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
@@ -324,19 +342,19 @@ public:
HRESULT CHandler::Open2(IInStream *stream, HRESULT CHandler::Open2(IInStream *stream,
const UInt64 *maxCheckStartPosition, const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback) IArchiveOpenCallback *openCallback)
{ {
{ {
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
CMyComPtr<ICryptoGetTextPassword> getTextPassword; CMyComPtr<ICryptoGetTextPassword> getTextPassword;
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
CVolumeName seqName; CVolumeName seqName;
UInt64 totalBytes = 0; UInt64 totalBytes = 0;
UInt64 curBytes = 0; UInt64 curBytes = 0;
if (openArchiveCallback != NULL) if (openCallback)
{ {
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
@@ -378,12 +396,12 @@ HRESULT CHandler::Open2(IInStream *stream,
inStream = stream; inStream = stream;
UInt64 endPos = 0; UInt64 endPos = 0;
if (openArchiveCallback != NULL) RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
if (openCallback)
{ {
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
totalBytes += endPos; totalBytes += endPos;
RINOK(openArchiveCallback->SetTotal(NULL, &totalBytes)); RINOK(openCallback->SetTotal(NULL, &totalBytes));
} }
NArchive::NRar::CInArchive archive; NArchive::NRar::CInArchive archive;
@@ -395,8 +413,16 @@ HRESULT CHandler::Open2(IInStream *stream,
CItemEx item; CItemEx item;
for (;;) for (;;)
{ {
if (archive.m_Position > endPos)
{
AddErrorMessage("Unexpected end of archive");
break;
}
bool decryptionError; bool decryptionError;
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError); AString errorMessageLoc;
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);
if (errorMessageLoc)
AddErrorMessage(errorMessageLoc);
if (result == S_FALSE) if (result == S_FALSE)
{ {
if (decryptionError && _items.IsEmpty()) if (decryptionError && _items.IsEmpty())
@@ -426,11 +452,11 @@ HRESULT CHandler::Open2(IInStream *stream,
_refItems.Add(refItem); _refItems.Add(refItem);
} }
_items.Add(item); _items.Add(item);
if (openArchiveCallback != NULL && _items.Size() % 100 == 0) if (openCallback && _items.Size() % 100 == 0)
{ {
UInt64 numFiles = _items.Size(); UInt64 numFiles = _items.Size();
UInt64 numBytes = curBytes + item.Position; UInt64 numBytes = curBytes + item.Position;
RINOK(openArchiveCallback->SetCompleted(&numFiles, &numBytes)); RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
} }
} }
curBytes += endPos; curBytes += endPos;
@@ -442,13 +468,13 @@ HRESULT CHandler::Open2(IInStream *stream,
STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 *maxCheckStartPosition, const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback) IArchiveOpenCallback *openCallback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
Close(); Close();
try try
{ {
HRESULT res = Open2(stream, maxCheckStartPosition, openArchiveCallback); HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);
if (res != S_OK) if (res != S_OK)
Close(); Close();
return res; return res;
@@ -461,6 +487,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
STDMETHODIMP CHandler::Close() STDMETHODIMP CHandler::Close()
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
_errorMessage.Empty();
_refItems.Clear(); _refItems.Clear();
_items.Clear(); _items.Clear();
_archives.Clear(); _archives.Clear();

View File

@@ -4,11 +4,12 @@
#define __RAR_HANDLER_H #define __RAR_HANDLER_H
#include "../IArchive.h" #include "../IArchive.h"
#include "RarIn.h"
#include "RarVolumeInStream.h"
#include "../../Common/CreateCoder.h" #include "../../Common/CreateCoder.h"
#include "RarIn.h"
#include "RarVolumeInStream.h"
namespace NArchive { namespace NArchive {
namespace NRar { namespace NRar {
@@ -17,26 +18,15 @@ class CHandler:
PUBLIC_ISetCompressCodecsInfo PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp public CMyUnknownImp
{ {
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
DECL_ISetCompressCodecsInfo
private:
CRecordVector<CRefItem> _refItems; CRecordVector<CRefItem> _refItems;
CObjectVector<CItemEx> _items; CObjectVector<CItemEx> _items;
CObjectVector<CInArchive> _archives; CObjectVector<CInArchive> _archives;
NArchive::NRar::CInArchiveInfo _archiveInfo; NArchive::NRar::CInArchiveInfo _archiveInfo;
AString _errorMessage;
DECL_EXTERNAL_CODECS_VARS DECL_EXTERNAL_CODECS_VARS
UInt64 GetPackSize(int refIndex) const; UInt64 GetPackSize(int refIndex) const;
// NArchive::NRar::CInArchive _archive;
bool IsSolid(int refIndex) bool IsSolid(int refIndex)
{ {
@@ -49,10 +39,26 @@ private:
} }
return item.IsSolid(); return item.IsSolid();
} }
void AddErrorMessage(const AString &s)
{
if (!_errorMessage.IsEmpty())
_errorMessage += '\n';
_errorMessage += s;
}
HRESULT Open2(IInStream *stream, HRESULT Open2(IInStream *stream,
const UInt64 *maxCheckStartPosition, const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback); IArchiveOpenCallback *openCallback);
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
DECL_ISetCompressCodecsInfo
}; };
}} }}

View File

@@ -5,9 +5,9 @@
#include "Common/Types.h" #include "Common/Types.h"
namespace NArchive{ namespace NArchive {
namespace NRar{ namespace NRar {
namespace NHeader{ namespace NHeader {
const int kMarkerSize = 7; const int kMarkerSize = 7;
extern Byte kMarker[kMarkerSize]; extern Byte kMarker[kMarkerSize];
@@ -18,16 +18,16 @@ namespace NBlockType
{ {
enum EBlockType enum EBlockType
{ {
kMarker = 0x72, kMarker = 0x72,
kArchiveHeader = 0x73, kArchiveHeader,
kFileHeader = 0x74, kFileHeader,
kCommentHeader = 0x75, kCommentHeader,
kOldAuthenticity = 0x76, kOldAuthenticity,
kSubBlock = 0x77, kOldSubBlock,
kRecoveryRecord = 0x78, kRecoveryRecord,
kAuthenticity = 0x79, kAuthenticity,
kSubBlock,
kEndOfArchive = 0x7B // Is not safe kEndOfArchive
}; };
} }
@@ -46,29 +46,10 @@ namespace NArchive
const int kHeaderSizeMin = 7; const int kHeaderSizeMin = 7;
struct CBlock
{
UInt16 CRC;
Byte Type;
UInt16 Flags;
UInt16 Size;
UInt16 Reserved1;
UInt32 Reserved2;
// UInt16 GetRealCRC() const;
};
const int kArchiveHeaderSize = 13; const int kArchiveHeaderSize = 13;
const int kBlockHeadersAreEncrypted = 0x80; const int kBlockHeadersAreEncrypted = 0x80;
struct CHeader360: public CBlock
{
Byte EncryptVersion;
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
UInt32 GetBaseSize() const { return kArchiveHeaderSize + (IsEncryptOld() ? 0 : 1); }
};
} }
namespace NFile namespace NFile

View File

@@ -3,6 +3,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/7zCrc.h" #include "../../../../C/7zCrc.h"
#include "../../../../C/CpuArch.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Common/UTFConvert.h" #include "Common/UTFConvert.h"
@@ -14,9 +15,16 @@
#include "RarIn.h" #include "RarIn.h"
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
namespace NArchive { namespace NArchive {
namespace NRar { namespace NRar {
static const char *k_UnexpectedEnd = "Unexpected end of archive";
static const char *k_DecryptionError = "Decryption Error";
void CInArchive::ThrowExceptionWithCode( void CInArchive::ThrowExceptionWithCode(
CInArchiveException::CCauseType cause) CInArchiveException::CCauseType cause)
{ {
@@ -42,140 +50,80 @@ void CInArchive::Close()
m_Stream.Release(); m_Stream.Release();
} }
HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
static inline bool TestMarkerCandidate(const void *aTestBytes)
{ {
for (UInt32 i = 0; i < NHeader::kMarkerSize; i++) if (m_CryptoMode)
if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i]) {
return false; size_t size = *resSize;
return true; *resSize = 0;
} const Byte *bufData = m_DecryptedDataAligned;
UInt32 bufSize = m_DecryptedDataSize;
HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit) size_t i;
{ for (i = 0; i < size && m_CryptoPos < bufSize; i++)
RINOK(FindSignatureInStream(stream, ((Byte *)data)[i] = bufData[m_CryptoPos++];
NHeader::kMarker, NHeader::kMarkerSize, *resSize = i;
searchHeaderSizeLimit, m_ArchiveStartPosition)); return S_OK;
m_Stream = stream; }
m_Position = m_ArchiveStartPosition + NHeader::kMarkerSize; return ReadStream(m_Stream, data, resSize);
return m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL);
}
void CInArchive::ThrowUnexpectedEndOfArchiveException()
{
ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);
} }
bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
{ {
if (m_CryptoMode) size_t processed = size;
{ if (ReadBytesSpec(data, &processed) != S_OK)
const Byte *bufData = m_DecryptedDataAligned; return false;
UInt32 bufSize = m_DecryptedDataSize; return processed == size;
UInt32 i;
for (i = 0; i < size && m_CryptoPos < bufSize; i++)
((Byte *)data)[i] = bufData[m_CryptoPos++];
return (i == size);
}
return (ReadStream_FALSE(m_Stream, data, size) == S_OK);
} }
void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size)
{
if(!ReadBytesAndTestSize(data,size))
ThrowUnexpectedEndOfArchiveException();
}
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
{
size_t realProcessedSize = size;
HRESULT result = ReadStream(m_Stream, data, &realProcessedSize);
if (processedSize != NULL)
*processedSize = (UInt32)realProcessedSize;
AddToSeekValue(realProcessedSize);
return result;
}
static UInt32 CrcUpdateUInt16(UInt32 crc, UInt16 v)
{
crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
return crc;
}
static UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 v)
{
crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 16) & 0xFF));
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 24) & 0xFF));
return crc;
}
HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit) HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{ {
m_CryptoMode = false; m_CryptoMode = false;
RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition)); RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
m_Position = m_StreamStartPosition; m_Position = m_StreamStartPosition;
RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit)); UInt64 arcStartPos;
RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
searchHeaderSizeLimit, arcStartPos));
m_Position = arcStartPos + NHeader::kMarkerSize;
RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
Byte buf[NHeader::NArchive::kArchiveHeaderSize]; RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
UInt32 processedSize; AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
ReadBytes(buf, sizeof(buf), &processedSize);
if (processedSize != sizeof(buf))
return S_FALSE;
m_CurData = buf;
m_CurPos = 0;
m_PosLimit = sizeof(buf);
m_ArchiveHeader.CRC = ReadUInt16();
m_ArchiveHeader.Type = ReadByte();
m_ArchiveHeader.Flags = ReadUInt16();
m_ArchiveHeader.Size = ReadUInt16();
m_ArchiveHeader.Reserved1 = ReadUInt16();
m_ArchiveHeader.Reserved2 = ReadUInt32();
m_ArchiveHeader.EncryptVersion = 0;
UInt32 crc = CRC_INIT_VAL; UInt32 blockSize = Get16(buf + 5);
crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.Type);
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Flags);
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Size);
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Reserved1);
crc = CrcUpdateUInt32(crc, m_ArchiveHeader.Reserved2);
if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize) _header.EncryptVersion = 0;
_header.Flags = Get16(buf + 3);
UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
if (_header.IsThereEncryptVer())
{ {
ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize); if (blockSize <= headerSize)
if (processedSize != 1)
return S_FALSE; return S_FALSE;
crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.EncryptVersion); RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
AddToSeekValue(1);
_header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
headerSize += 1;
} }
if (blockSize < headerSize ||
if(m_ArchiveHeader.CRC != (CRC_GET_DIGEST(crc) & 0xFFFF)) buf[2] != NHeader::NBlockType::kArchiveHeader ||
ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError); (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
return S_FALSE; return S_FALSE;
m_ArchiveCommentPosition = m_Position;
m_SeekOnArchiveComment = true;
return S_OK;
}
void CInArchive::SkipArchiveComment() size_t commentSize = blockSize - headerSize;
{ _comment.SetCapacity(commentSize);
if (!m_SeekOnArchiveComment) RINOK(ReadStream_FALSE(stream, _comment, commentSize));
return; AddToSeekValue(commentSize);
AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize()); m_Stream = stream;
m_SeekOnArchiveComment = false; _header.StartPosition = arcStartPos;
return S_OK;
} }
void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
{ {
archiveInfo.StartPosition = m_ArchiveStartPosition; archiveInfo = _header;
archiveInfo.Flags = m_ArchiveHeader.Flags;
archiveInfo.CommentPosition = m_ArchiveCommentPosition;
archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
} }
static void DecodeUnicodeFileName(const char *name, const Byte *encName, static void DecodeUnicodeFileName(const char *name, const Byte *encName,
@@ -372,29 +320,24 @@ void CInArchive::AddToSeekValue(UInt64 addValue)
m_Position += addValue; m_Position += addValue;
} }
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError) HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
{ {
decryptionError = false; decryptionError = false;
if (m_SeekOnArchiveComment)
SkipArchiveComment();
for (;;) for (;;)
{ {
if(!SeekInArchive(m_Position)) SeekInArchive(m_Position);
return S_FALSE; if (!m_CryptoMode && (_header.Flags &
if (!m_CryptoMode && (m_ArchiveHeader.Flags &
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0) NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
{ {
m_CryptoMode = false; m_CryptoMode = false;
if (getTextPassword == 0) if (getTextPassword == 0)
return S_FALSE; return S_FALSE;
if(!SeekInArchive(m_Position))
return S_FALSE;
if (!m_RarAES) if (!m_RarAES)
{ {
m_RarAESSpec = new NCrypto::NRar29::CDecoder; m_RarAESSpec = new NCrypto::NRar29::CDecoder;
m_RarAES = m_RarAESSpec; m_RarAES = m_RarAESSpec;
} }
m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld()); m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
// Salt // Salt
const UInt32 kSaltSize = 8; const UInt32 kSaltSize = 8;
@@ -438,8 +381,14 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
} }
m_FileHeaderData.EnsureCapacity(7); m_FileHeaderData.EnsureCapacity(7);
if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7)) size_t processed = 7;
RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
if (processed != 7)
{
if (processed != 0)
errorMessage = k_UnexpectedEnd;
return S_FALSE; return S_FALSE;
}
m_CurData = (Byte *)m_FileHeaderData; m_CurData = (Byte *)m_FileHeaderData;
m_CurPos = 0; m_CurPos = 0;
@@ -460,7 +409,12 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize); m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
m_CurData = (Byte *)m_FileHeaderData; m_CurData = (Byte *)m_FileHeaderData;
m_PosLimit = m_BlockHeader.HeadSize; m_PosLimit = m_BlockHeader.HeadSize;
ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7); if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))
{
errorMessage = k_UnexpectedEnd;
return S_FALSE;
}
ReadHeaderReal(item); ReadHeaderReal(item);
if ((CrcCalc(m_CurData + 2, if ((CrcCalc(m_CurData + 2,
m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC) m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
@@ -475,19 +429,25 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10)) if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
{ {
decryptionError = true; decryptionError = true;
errorMessage = k_DecryptionError;
return S_FALSE; return S_FALSE;
} }
if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
{ {
m_FileHeaderData.EnsureCapacity(7 + 4); m_FileHeaderData.EnsureCapacity(7 + 4);
m_CurData = (Byte *)m_FileHeaderData; m_CurData = (Byte *)m_FileHeaderData;
ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4))
{
errorMessage = k_UnexpectedEnd;
return S_FALSE;
}
m_PosLimit = 7 + 4; m_PosLimit = 7 + 4;
UInt32 dataSize = ReadUInt32(); UInt32 dataSize = ReadUInt32();
AddToSeekValue(dataSize); AddToSeekValue(dataSize);
if (m_CryptoMode && dataSize > (1 << 27)) if (m_CryptoMode && dataSize > (1 << 27))
{ {
decryptionError = true; decryptionError = true;
errorMessage = k_DecryptionError;
return S_FALSE; return S_FALSE;
} }
m_CryptoPos = m_BlockHeader.HeadSize; m_CryptoPos = m_BlockHeader.HeadSize;
@@ -500,11 +460,9 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
} }
} }
bool CInArchive::SeekInArchive(UInt64 position) void CInArchive::SeekInArchive(UInt64 position)
{ {
UInt64 newPosition; m_Stream->Seek(position, STREAM_SEEK_SET, NULL);
m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);
return newPosition == position;
} }
ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)

View File

@@ -33,18 +33,20 @@ public:
CInArchiveException(CCauseType cause) : Cause(cause) {} CInArchiveException(CCauseType cause) : Cause(cause) {}
}; };
class CInArchiveInfo
struct CInArchiveInfo
{ {
public: UInt32 Flags;
Byte EncryptVersion;
UInt64 StartPosition; UInt64 StartPosition;
UInt16 Flags;
UInt64 CommentPosition;
UInt16 CommentSize;
bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
}; };
class CInArchive class CInArchive
@@ -52,23 +54,19 @@ class CInArchive
CMyComPtr<IInStream> m_Stream; CMyComPtr<IInStream> m_Stream;
UInt64 m_StreamStartPosition; UInt64 m_StreamStartPosition;
UInt64 m_Position;
UInt64 m_ArchiveStartPosition;
NHeader::NArchive::CHeader360 m_ArchiveHeader; CInArchiveInfo _header;
CDynamicBuffer<char> m_NameBuffer; CDynamicBuffer<char> m_NameBuffer;
CDynamicBuffer<wchar_t> _unicodeNameBuffer; CDynamicBuffer<wchar_t> _unicodeNameBuffer;
bool m_SeekOnArchiveComment;
UInt64 m_ArchiveCommentPosition; CByteBuffer _comment;
void ReadName(CItemEx &item, int nameSize); void ReadName(CItemEx &item, int nameSize);
void ReadHeaderReal(CItemEx &item); void ReadHeaderReal(CItemEx &item);
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *aProcessedSize); HRESULT ReadBytesSpec(void *data, size_t *size);
bool ReadBytesAndTestSize(void *data, UInt32 size); bool ReadBytesAndTestSize(void *data, UInt32 size);
void ReadBytesAndTestResult(void *data, UInt32 size);
HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit); HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ThrowExceptionWithCode(CInArchiveException::CCauseType cause); void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);
@@ -108,15 +106,15 @@ class CInArchive
} }
public: public:
UInt64 m_Position;
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
void Close(); void Close();
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError); HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);
void SkipArchiveComment();
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const; void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
bool SeekInArchive(UInt64 position); void SeekInArchive(UInt64 position);
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
}; };

View File

@@ -79,7 +79,7 @@ static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
char dat[kCSigHeaderSigSize]; char dat[kCSigHeaderSigSize];
char *cur = dat; char *cur = dat;
RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize)); RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize));
memmove(h.Magic, cur, 4); memcpy(h.Magic, cur, 4);
cur += 4; cur += 4;
cur += 4; cur += 4;
h.IndexLen = Get32(cur); h.IndexLen = Get32(cur);
@@ -95,7 +95,7 @@ HRESULT OpenArchive(IInStream *inStream)
char *cur = leadData; char *cur = leadData;
CLead lead; CLead lead;
RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize)); RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize));
memmove(lead.Magic, cur, 4); memcpy(lead.Magic, cur, 4);
cur += 4; cur += 4;
lead.Major = *cur++; lead.Major = *cur++;
lead.Minor = *cur++; lead.Minor = *cur++;
@@ -103,7 +103,7 @@ HRESULT OpenArchive(IInStream *inStream)
cur += 2; cur += 2;
lead.ArchNum = Get16(cur); lead.ArchNum = Get16(cur);
cur += 2; cur += 2;
memmove(lead.Name, cur, sizeof(lead.Name)); memcpy(lead.Name, cur, sizeof(lead.Name));
cur += sizeof(lead.Name); cur += sizeof(lead.Name);
lead.OSNum = Get16(cur); lead.OSNum = Get16(cur);
cur += 2; cur += 2;

View File

@@ -347,7 +347,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{ {
CMultiStream::CSubStreamInfo subStreamInfo; CMultiStream::CSubStreamInfo subStreamInfo;
subStreamInfo.Stream = _streams[i]; subStreamInfo.Stream = _streams[i];
subStreamInfo.Pos = 0;
subStreamInfo.Size = _sizes[i]; subStreamInfo.Size = _sizes[i];
streamSpec->Streams.Add(subStreamInfo); streamSpec->Streams.Add(subStreamInfo);
} }

View File

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,8 @@
#include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
#include "../Common/ItemNameUtils.h" #include "../Common/ItemNameUtils.h"
@@ -21,7 +23,9 @@ using namespace NWindows;
namespace NArchive { namespace NArchive {
namespace NTar { namespace NTar {
static STATPROPSTG kProps[] = static const char *kUnexpectedEnd = "Unexpected end of archive";
static const STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
@@ -34,8 +38,14 @@ static STATPROPSTG kProps[] =
{ NULL, kpidLink, VT_BSTR} { NULL, kpidLink, VT_BSTR}
}; };
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidPhySize, VT_UI8},
{ NULL, kpidHeadersSize, VT_UI8}
};
IMP_IInArchive_Props IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{ {
@@ -43,11 +53,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
switch(propID) switch(propID)
{ {
case kpidPhySize: if (_phySizeDefined) prop = _phySize; break; case kpidPhySize: if (_phySizeDefined) prop = _phySize; break;
case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break;
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
} }
HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item)
{
item.HeaderPos = _phySize;
RINOK(ReadItem(stream, filled, item, _errorMessage));
_phySize += item.HeaderSize;
_headersSize += item.HeaderSize;
return S_OK;
}
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{ {
UInt64 endPos = 0; UInt64 endPos = 0;
@@ -56,26 +77,29 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
} }
_isGood = true; _phySizeDefined = true;
UInt64 pos = 0;
for (;;) for (;;)
{ {
CItemEx item; CItemEx item;
bool filled; bool filled;
item.HeaderPosition = pos; RINOK(ReadItem2(stream, filled, item));
RINOK(ReadItem(stream, filled, item));
if (!filled) if (!filled)
break; break;
_items.Add(item); _items.Add(item);
RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));
if (pos > endPos) if (_phySize > endPos)
return S_FALSE;
if (pos == endPos)
{ {
_isGood = false; _errorMessage = kUnexpectedEnd;
break; break;
} }
/*
if (_phySize == endPos)
{
_errorMessage = "There are no trailing zero-filled records";
break;
}
*/
if (callback != NULL) if (callback != NULL)
{ {
if (_items.Size() == 1) if (_items.Size() == 1)
@@ -85,7 +109,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (_items.Size() % 100 == 0) if (_items.Size() % 100 == 0)
{ {
UInt64 numFiles = _items.Size(); UInt64 numFiles = _items.Size();
RINOK(callback->SetCompleted(&numFiles, &pos)); RINOK(callback->SetCompleted(&numFiles, &_phySize));
} }
} }
} }
@@ -132,7 +156,10 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
STDMETHODIMP CHandler::Close() STDMETHODIMP CHandler::Close()
{ {
_errorMessage.Empty();
_phySizeDefined = false; _phySizeDefined = false;
_phySize = 0;
_headersSize = 0;
_curIndex = 0; _curIndex = 0;
_latestIsRead = false; _latestIsRead = false;
_items.Clear(); _items.Clear();
@@ -161,16 +188,24 @@ HRESULT CHandler::SkipTo(UInt32 index)
{ {
UInt64 packSize = _latestItem.GetPackSize(); UInt64 packSize = _latestItem.GetPackSize();
RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));
_phySize += copyCoderSpec->TotalSize;
if (copyCoderSpec->TotalSize != packSize)
{
_errorMessage = kUnexpectedEnd;
return S_FALSE;
}
_latestIsRead = false; _latestIsRead = false;
_curIndex++; _curIndex++;
} }
else else
{ {
bool filled; bool filled;
// item.HeaderPosition = pos; RINOK(ReadItem2(_seqStream, filled, _latestItem));
RINOK(ReadItem(_seqStream, filled, _latestItem));
if (!filled) if (!filled)
{
_phySizeDefined = true;
return E_INVALIDARG; return E_INVALIDARG;
}
_latestIsRead = true; _latestIsRead = true;
} }
} }
@@ -203,10 +238,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
switch(propID) switch(propID)
{ {
case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
case kpidIsDir: prop = item->IsDir(); break; case kpidIsDir: prop = item->IsDir(); break;
case kpidSize: prop = item->Size; break; case kpidSize: prop = item->GetUnpackSize(); break;
case kpidPackSize: prop = item->GetPackSize(); break; case kpidPackSize: prop = item->GetPackSize(); break;
case kpidMTime: case kpidMTime:
if (item->MTime != 0) if (item->MTime != 0)
{ {
@@ -216,9 +251,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
} }
break; break;
case kpidPosixAttrib: prop = item->Mode; break; case kpidPosixAttrib: prop = item->Mode; break;
case kpidUser: prop = TarStringToUnicode(item->User); break; case kpidUser: prop = TarStringToUnicode(item->User); break;
case kpidGroup: prop = TarStringToUnicode(item->Group); break; case kpidGroup: prop = TarStringToUnicode(item->Group); break;
case kpidLink: prop = TarStringToUnicode(item->LinkName); break; case kpidLink: prop = TarStringToUnicode(item->LinkName); break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
@@ -242,7 +277,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 totalSize = 0; UInt64 totalSize = 0;
UInt32 i; UInt32 i;
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
totalSize += _items[allFilesMode ? i : indices[i]].Size; totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize();
extractCallback->SetTotal(totalSize); extractCallback->SetTotal(totalSize);
UInt64 totalPackSize; UInt64 totalPackSize;
@@ -282,7 +317,8 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
item = &_items[index]; item = &_items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
totalSize += item->Size; UInt64 unpackSize = item->GetUnpackSize();
totalSize += unpackSize;
totalPackSize += item->GetPackSize(); totalPackSize += item->GetPackSize();
if (item->IsDir()) if (item->IsDir())
{ {
@@ -302,14 +338,21 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->SetStream(realOutStream); outStreamSpec->SetStream(realOutStream);
realOutStream.Release(); realOutStream.Release();
outStreamSpec->Init(skipMode ? 0 : item->Size, true); outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
if (!seqMode) if (item->IsLink())
{ {
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
}
else
{
if (!seqMode)
{
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
}
streamSpec->Init(item->GetPackSize());
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
} }
streamSpec->Init(item->GetPackSize());
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
if (seqMode) if (seqMode)
{ {
_latestIsRead = false; _latestIsRead = false;
@@ -328,6 +371,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
const CItemEx &item = _items[index]; const CItemEx &item = _items[index];
if (item.IsLink())
{
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this);
*stream = streamTemp.Detach();
return S_OK;
}
return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
COM_TRY_END COM_TRY_END
} }

View File

@@ -23,18 +23,20 @@ class CHandler:
CObjectVector<CItemEx> _items; CObjectVector<CItemEx> _items;
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream; CMyComPtr<ISequentialInStream> _seqStream;
bool _isGood;
UInt32 _curIndex; UInt32 _curIndex;
bool _latestIsRead; bool _latestIsRead;
CItemEx _latestItem; CItemEx _latestItem;
UInt64 _phySize; UInt64 _phySize;
UInt64 _headersSize;
bool _phySizeDefined; bool _phySizeDefined;
AString _errorMessage;
NCompress::CCopyCoder *copyCoderSpec; NCompress::CCopyCoder *copyCoderSpec;
CMyComPtr<ICompressCoder> copyCoder; CMyComPtr<ICompressCoder> copyCoder;
HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
HRESULT SkipTo(UInt32 index); HRESULT SkipTo(UInt32 index);

View File

@@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
IArchiveUpdateCallback *callback) IArchiveUpdateCallback *callback)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
if ((_stream && !_isGood) || _seqStream) if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
return E_NOTIMPL; return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems; CObjectVector<CUpdateItem> updateItems;
for (UInt32 i = 0; i < numItems; i++) for (UInt32 i = 0; i < numItems; i++)

View File

@@ -63,29 +63,40 @@ static void ReadString(const char *s, int size, AString &result)
result = temp; result = temp;
} }
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, size_t &processedSize) static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
{ {
item.LongLinkSize = 0;
char buf[NFileHeader::kRecordSize]; char buf[NFileHeader::kRecordSize];
char *p = buf; char *p = buf;
error.Empty();
filled = false; filled = false;
bool thereAreEmptyRecords = false; bool thereAreEmptyRecords = false;
for (;;) for (;;)
{ {
processedSize = NFileHeader::kRecordSize; size_t processedSize = NFileHeader::kRecordSize;
RINOK(ReadStream(stream, buf, &processedSize)); RINOK(ReadStream(stream, buf, &processedSize));
if (processedSize == 0) if (processedSize == 0)
{
if (!thereAreEmptyRecords )
error = "There are no trailing zero-filled records";
return S_OK; return S_OK;
}
if (processedSize != NFileHeader::kRecordSize) if (processedSize != NFileHeader::kRecordSize)
return S_FALSE; {
error = "There is no correct record at the end of archive";
return S_OK;
}
item.HeaderSize += NFileHeader::kRecordSize;
if (!IsRecordLast(buf)) if (!IsRecordLast(buf))
break; break;
thereAreEmptyRecords = true; thereAreEmptyRecords = true;
} }
if (thereAreEmptyRecords) if (thereAreEmptyRecords)
return S_FALSE; {
error = "There are data after end of archive";
return S_OK;
}
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
@@ -143,59 +154,54 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
return S_OK; return S_OK;
} }
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item) HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
{ {
size_t processedSize; item.HeaderSize = 0;
RINOK(GetNextItemReal(stream, filled, item, processedSize)); bool flagL = false;
if (!filled) bool flagK = false;
return S_OK; AString nameL;
// GNUtar extension AString nameK;
if (item.LinkFlag == 'L' || // NEXT file has a long name for (;;)
item.LinkFlag == 'K') // NEXT file has a long linkname
{ {
if (item.Name.Compare(NFileHeader::kLongLink) != 0) RINOK(GetNextItemReal(stream, filled, item, error));
if (item.Name.Compare(NFileHeader::kLongLink2) != 0) if (!filled)
return S_OK;
if (item.LinkFlag == 'L' || // NEXT file has a long name
item.LinkFlag == 'K') // NEXT file has a long linkname
{
AString *name;
if (item.LinkFlag == 'L')
{ if (flagL) return S_FALSE; flagL = true; name = &nameL; }
else
{ if (flagK) return S_FALSE; flagK = true; name = &nameK; }
if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&
item.Name.Compare(NFileHeader::kLongLink2) != 0)
return S_FALSE; return S_FALSE;
if (item.Size > (1 << 14))
AString fullName; return S_FALSE;
if (item.Size > (1 << 15)) int packSize = (int)item.GetPackSize();
char *buf = name->GetBuffer(packSize);
RINOK(ReadStream_FALSE(stream, buf, packSize));
item.HeaderSize += packSize;
buf[(size_t)item.Size] = '\0';
name->ReleaseBuffer();
continue;
}
if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
{
// pax Extended Header
}
else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
{
// GNU Extensions to the Archive Format
}
else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
return S_FALSE; return S_FALSE;
int packSize = (int)item.GetPackSize(); if (flagL) item.Name = nameL;
char *buffer = fullName.GetBuffer(packSize + 1); if (flagK) item.LinkName = nameK;
RINOK(ReadStream_FALSE(stream, buffer, packSize));
processedSize += packSize;
buffer[item.Size] = '\0';
fullName.ReleaseBuffer();
UInt64 headerPosition = item.HeaderPosition;
if (item.LinkFlag == 'L')
{
size_t processedSize2;
RINOK(GetNextItemReal(stream, filled, item, processedSize2));
item.LongLinkSize = (unsigned)processedSize;
}
else
{
item.LongLinkSize = (unsigned)processedSize - NFileHeader::kRecordSize;
item.Size = 0;
}
item.Name = fullName;
item.HeaderPosition = headerPosition;
}
else if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
{
// pax Extended Header
return S_OK; return S_OK;
} }
else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
{
// GNU Extensions to the Archive Format
return S_OK;
}
else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
return S_FALSE;
return S_OK;
} }
}} }}

View File

@@ -1,9 +1,8 @@
// Archive/TarIn.h // TarIn.h
#ifndef __ARCHIVE_TAR_IN_H #ifndef __ARCHIVE_TAR_IN_H
#define __ARCHIVE_TAR_IN_H #define __ARCHIVE_TAR_IN_H
#include "Common/MyCom.h"
#include "../../IStream.h" #include "../../IStream.h"
#include "TarItem.h" #include "TarItem.h"
@@ -11,7 +10,7 @@
namespace NArchive { namespace NArchive {
namespace NTar { namespace NTar {
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo); HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error);
}} }}

View File

@@ -31,6 +31,9 @@ struct CItem
bool DeviceMajorDefined; bool DeviceMajorDefined;
bool DeviceMinorDefined; bool DeviceMinorDefined;
bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }
UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }
bool IsDir() const bool IsDir() const
{ {
switch(LinkFlag) switch(LinkFlag)
@@ -58,10 +61,10 @@ struct CItem
struct CItemEx: public CItem struct CItemEx: public CItem
{ {
UInt64 HeaderPosition; UInt64 HeaderPos;
unsigned LongLinkSize; unsigned HeaderSize;
UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; } UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; } UInt64 GetFullSize() const { return HeaderSize + Size; }
}; };
}} }}

View File

@@ -111,25 +111,25 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
} }
else else
{ {
const CItemEx &existItemInfo = inputItems[ui.IndexInArchive]; const CItemEx &existItem = inputItems[ui.IndexInArchive];
UInt64 size; UInt64 size;
if (ui.NewProps) if (ui.NewProps)
{ {
RINOK(outArchive.WriteHeader(item)); RINOK(outArchive.WriteHeader(item));
RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL)); RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
size = existItemInfo.Size; size = existItem.Size;
} }
else else
{ {
RINOK(inStream->Seek(existItemInfo.HeaderPosition, STREAM_SEEK_SET, NULL)); RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
size = existItemInfo.GetFullSize(); size = existItem.GetFullSize();
} }
streamSpec->Init(size); streamSpec->Init(size);
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != size) if (copyCoderSpec->TotalSize != size)
return E_FAIL; return E_FAIL;
RINOK(outArchive.FillDataResidual(existItemInfo.Size)); RINOK(outArchive.FillDataResidual(existItem.Size));
complexity += size; complexity += size;
} }
} }

View File

@@ -323,25 +323,13 @@ static void AddTagUInt64(AString &s, const char *name, UInt64 value)
AddTag(s, name, temp); AddTag(s, name, temp);
} }
static void ConvertUInt32ToHex(UInt32 value, char *s)
{
for (int i = 0; i < 8; i++)
{
int t = value & 0xF;
value >>= 4;
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[8] = '\0';
}
static AString TimeToXml(FILETIME &ft) static AString TimeToXml(FILETIME &ft)
{ {
AString res; AString res;
char temp[16] = { '0', 'x' }; char temp[16] = { '0', 'x' };
ConvertUInt32ToHex(ft.dwHighDateTime, temp + 2); ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2);
AddTag(res, "HIGHPART", temp); AddTag(res, "HIGHPART", temp);
ConvertUInt32ToHex(ft.dwLowDateTime, temp + 2); ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2);
AddTag(res, "LOWPART", temp); AddTag(res, "LOWPART", temp);
return res; return res;
} }

View File

@@ -240,7 +240,7 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l
buf.Free(); buf.Free();
buf.SetCapacity(size); buf.SetCapacity(size);
CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2(); CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream();
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init((Byte *)buf, size); outStreamSpec->Init((Byte *)buf, size);

View File

@@ -268,7 +268,7 @@ HRESULT CHandler::Open2(IInStream *stream)
inStreamLimSpec->SetStream(stream); inStreamLimSpec->SetStream(stream);
inStreamLimSpec->Init(packSize); inStreamLimSpec->Init(packSize);
CSequentialOutStreamImp2 *outStreamLimSpec = new CSequentialOutStreamImp2; CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec); CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);
outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize); outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);

View File

@@ -53,18 +53,17 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN
EncoderSpec = new NCompress::NLzma::CEncoder; EncoderSpec = new NCompress::NLzma::CEncoder;
Encoder = EncoderSpec; Encoder = EncoderSpec;
} }
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init(); outStreamSpec->Init(Header + 4, kLzmaPropsSize);
RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps)); RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
RINOK(EncoderSpec->WriteCoderProperties(outStream)); RINOK(EncoderSpec->WriteCoderProperties(outStream));
if (outStreamSpec->GetSize() != kLzmaPropsSize) if (outStreamSpec->GetPos() != kLzmaPropsSize)
return E_FAIL; return E_FAIL;
Header[0] = MY_VER_MAJOR; Header[0] = MY_VER_MAJOR;
Header[1] = MY_VER_MINOR; Header[1] = MY_VER_MINOR;
Header[2] = kLzmaPropsSize; Header[2] = kLzmaPropsSize;
Header[3] = 0; Header[3] = 0;
memcpy(Header + 4, outStreamSpec->GetBuffer(), kLzmaPropsSize);
return S_OK; return S_OK;
} }

View File

@@ -70,8 +70,8 @@ static const char *kMethods[] =
"Shrink", "Shrink",
"Reduced1", "Reduced1",
"Reduced2", "Reduced2",
"Reduced2",
"Reduced3", "Reduced3",
"Reduced4",
"Implode", "Implode",
"Tokenizing", "Tokenizing",
"Deflate", "Deflate",

View File

@@ -160,6 +160,7 @@ AR_OBJS = \
$O\ArjHandler.obj \ $O\ArjHandler.obj \
$O\Bz2Handler.obj \ $O\Bz2Handler.obj \
$O\CpioHandler.obj \ $O\CpioHandler.obj \
$O\CramfsHandler.obj \
$O\DebHandler.obj \ $O\DebHandler.obj \
$O\DeflateProps.obj \ $O\DeflateProps.obj \
$O\DmgHandler.obj \ $O\DmgHandler.obj \
@@ -178,6 +179,7 @@ AR_OBJS = \
$O\PpmdHandler.obj \ $O\PpmdHandler.obj \
$O\RpmHandler.obj \ $O\RpmHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\SquashfsHandler.obj \
$O\SwfHandler.obj \ $O\SwfHandler.obj \
$O\VhdHandler.obj \ $O\VhdHandler.obj \
$O\XarHandler.obj \ $O\XarHandler.obj \

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 1 # PROP Ignore_Export_Lib 1
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAcs /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /Yu"StdAfx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD BASE RSC /l 0x419 /d "NDEBUG"
@@ -164,6 +164,10 @@ SOURCE=..\..\Archive\Icons\split.ico
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Archive\Icons\squashfs.ico
# End Source File
# Begin Source File
SOURCE=..\..\Archive\Icons\tar.ico SOURCE=..\..\Archive\Icons\tar.ico
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2330,6 +2334,10 @@ SOURCE=..\..\Archive\CpioHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Archive\CramfsHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\DebHandler.cpp SOURCE=..\..\Archive\DebHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2420,6 +2428,10 @@ SOURCE=..\..\Archive\SplitHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Archive\SquashfsHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\SwfHandler.cpp SOURCE=..\..\Archive\SwfHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -58,6 +58,7 @@ AR_OBJS = \
$O\ArjHandler.obj \ $O\ArjHandler.obj \
$O\Bz2Handler.obj \ $O\Bz2Handler.obj \
$O\CpioHandler.obj \ $O\CpioHandler.obj \
$O\CramfsHandler.obj \
$O\DebHandler.obj \ $O\DebHandler.obj \
$O\DeflateProps.obj \ $O\DeflateProps.obj \
$O\DmgHandler.obj \ $O\DmgHandler.obj \
@@ -77,6 +78,7 @@ AR_OBJS = \
$O\RpmHandler.obj \ $O\RpmHandler.obj \
$O\SplitHandler.obj \ $O\SplitHandler.obj \
$O\SwfHandler.obj \ $O\SwfHandler.obj \
$O\SquashfsHandler.obj \
$O\VhdHandler.obj \ $O\VhdHandler.obj \
$O\XarHandler.obj \ $O\XarHandler.obj \
$O\XzHandler.obj \ $O\XzHandler.obj \

View File

@@ -27,10 +27,11 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
21 ICON "../../Archive/Icons/fat.ico" 21 ICON "../../Archive/Icons/fat.ico"
22 ICON "../../Archive/Icons/ntfs.ico" 22 ICON "../../Archive/Icons/ntfs.ico"
23 ICON "../../Archive/Icons/xz.ico" 23 ICON "../../Archive/Icons/xz.ico"
24 ICON "../../Archive/Icons/squashfs.ico"
STRINGTABLE STRINGTABLE
BEGIN BEGIN
100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23" 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24"
END END

View File

@@ -17,6 +17,7 @@ class CLimitedSequentialInStream:
bool _wasFinished; bool _wasFinished;
public: public:
void SetStream(ISequentialInStream *stream) { _stream = stream; } void SetStream(ISequentialInStream *stream) { _stream = stream; }
void ReleaseStream() { _stream.Release(); }
void Init(UInt64 streamSize) void Init(UInt64 streamSize)
{ {
_size = streamSize; _size = streamSize;

View File

@@ -2,20 +2,24 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "StreamObjects.h" #include "StreamObjects.h"
STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
if (processedSize != NULL) if (processedSize)
*processedSize = 0; *processedSize = 0;
if (size == 0)
return S_OK;
if (_pos > _size) if (_pos > _size)
return E_FAIL; return E_FAIL;
size_t rem = _size - (size_t)_pos; size_t rem = _size - (size_t)_pos;
if (size < rem) if (rem > size)
rem = (size_t)size; rem = (size_t)size;
memcpy(data, _data + (size_t)_pos, rem); memcpy(data, _data + (size_t)_pos, rem);
_pos += rem; _pos += rem;
if (processedSize != NULL) if (processedSize)
*processedSize = (UInt32)rem; *processedSize = (UInt32)rem;
return S_OK; return S_OK;
} }
@@ -34,43 +38,75 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi
return S_OK; return S_OK;
} }
void CByteDynBuffer::Free()
void CWriteBuffer::Write(const void *data, size_t size)
{ {
size_t newCapacity = _size + size; free(_buf);
_buffer.EnsureCapacity(newCapacity); _buf = 0;
memcpy(_buffer + _size, data, size); _capacity = 0;
_size += size;
} }
STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) bool CByteDynBuffer::EnsureCapacity(size_t cap)
{ {
_writeBuffer.Write(data, (size_t)size); if (cap <= _capacity)
if(processedSize != NULL) return true;
size_t delta;
if (_capacity > 64)
delta = _capacity / 4;
else if (_capacity > 8)
delta = 16;
else
delta = 4;
cap = MyMax(_capacity + delta, cap);
Byte *buf = (Byte *)realloc(_buf, cap);
if (!buf)
return false;
_buf = buf;
_capacity = cap;
return true;
}
Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
{
addSize += _size;
if (addSize < _size)
return NULL;
if (!_buffer.EnsureCapacity(addSize))
return NULL;
return (Byte *)_buffer + _size;
}
void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
{
dest.SetCapacity(_size);
memcpy(dest, _buffer, _size);
}
STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
if (size == 0)
return S_OK;
Byte *buf = GetBufPtrForWriting(size);
if (!buf)
return E_OUTOFMEMORY;
memcpy(buf, data, size);
UpdateSize(size);
if (processedSize)
*processedSize = size; *processedSize = size;
return S_OK; return S_OK;
} }
STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
size_t rem = _size - _pos; size_t rem = _size - _pos;
if (size < rem) if (rem > size)
rem = (size_t)size; rem = (size_t)size;
memcpy(_buffer + _pos, data, rem); memcpy(_buffer + _pos, data, rem);
_pos += rem; _pos += rem;
if (processedSize != NULL) if (processedSize)
*processedSize = (UInt32)rem; *processedSize = (UInt32)rem;
return (rem == size ? S_OK : E_FAIL); return (rem != 0 || size == 0) ? S_OK : E_FAIL;
}
STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
if (processedSize != 0)
*processedSize = realProcessedSize;
return result;
} }
STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
@@ -78,7 +114,108 @@ STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size,
UInt32 realProcessedSize; UInt32 realProcessedSize;
HRESULT result = _stream->Write(data, size, &realProcessedSize); HRESULT result = _stream->Write(data, size, &realProcessedSize);
_size += realProcessedSize; _size += realProcessedSize;
if (processedSize != 0) if (processedSize)
*processedSize = realProcessedSize; *processedSize = realProcessedSize;
return result; return result;
} }
static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
void CCachedInStream::Free()
{
MyFree(_tags);
_tags = 0;
MidFree(_data);
_data = 0;
}
bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog)
{
unsigned sizeLog = blockSizeLog + numBlocksLog;
if (sizeLog >= sizeof(size_t) * 8)
return false;
size_t dataSize = (size_t)1 << sizeLog;
if (_data == 0 || dataSize != _dataSize)
{
MidFree(_data);
_data = (Byte *)MidAlloc(dataSize);
if (_data == 0)
return false;
_dataSize = dataSize;
}
if (_tags == 0 || numBlocksLog != _numBlocksLog)
{
MyFree(_tags);
_tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
if (_tags == 0)
return false;
_numBlocksLog = numBlocksLog;
}
_blockSizeLog = blockSizeLog;
return true;
}
void CCachedInStream::Init(UInt64 size)
{
_size = size;
_pos = 0;
size_t numBlocks = (size_t)1 << _numBlocksLog;
for (size_t i = 0; i < numBlocks; i++)
_tags[i] = kEmptyTag;
}
STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
if (size == 0)
return S_OK;
if (_pos > _size)
return E_FAIL;
{
UInt64 rem = _size - _pos;
if (size > rem)
size = (UInt32)rem;
}
while (size != 0)
{
UInt64 cacheTag = _pos >> _blockSizeLog;
size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
Byte *p = _data + (cacheIndex << _blockSizeLog);
if (_tags[cacheIndex] != cacheTag)
{
UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
size_t blockSize = (size_t)1 << _blockSizeLog;
if (blockSize > remInBlock)
blockSize = (size_t)remInBlock;
RINOK(ReadBlock(cacheTag, p, blockSize));
_tags[cacheIndex] = cacheTag;
}
size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);
UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);
memcpy(data, p + offset, cur);
if (processedSize)
*processedSize += cur;
data = (void *)((const Byte *)data + cur);
_pos += cur;
size -= cur;
}
return S_OK;
}
STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch(seekOrigin)
{
case STREAM_SEEK_SET: _pos = offset; break;
case STREAM_SEEK_CUR: _pos = _pos + offset; break;
case STREAM_SEEK_END: _pos = _size + offset; break;
default: return STG_E_INVALIDFUNCTION;
}
if (newPosition != 0)
*newPosition = _pos;
return S_OK;
}

View File

@@ -3,7 +3,7 @@
#ifndef __STREAM_OBJECTS_H #ifndef __STREAM_OBJECTS_H
#define __STREAM_OBJECTS_H #define __STREAM_OBJECTS_H
#include "../../Common/DynamicBuffer.h" #include "../../Common/Buffer.h"
#include "../../Common/MyCom.h" #include "../../Common/MyCom.h"
#include "../IStream.h" #include "../IStream.h"
@@ -34,39 +34,45 @@ public:
void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); } void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); }
MY_UNKNOWN_IMP1(IInStream) MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
}; };
class CWriteBuffer class CByteDynBuffer
{ {
CByteDynamicBuffer _buffer; size_t _capacity;
size_t _size; Byte *_buf;
public: public:
CWriteBuffer(): _size(0) {} CByteDynBuffer(): _capacity(0), _buf(0) {};
void Init() { _size = 0; } // there is no copy constructor. So don't copy this object.
void Write(const void *data, size_t size); ~CByteDynBuffer() { Free(); }
size_t GetSize() const { return _size; } void Free();
const CByteDynamicBuffer& GetBuffer() const { return _buffer; } size_t GetCapacity() const { return _capacity; }
operator Byte*() const { return _buf; };
operator const Byte*() const { return _buf; };
bool EnsureCapacity(size_t capacity);
}; };
class CSequentialOutStreamImp: class CDynBufSeqOutStream:
public ISequentialOutStream, public ISequentialOutStream,
public CMyUnknownImp public CMyUnknownImp
{ {
CWriteBuffer _writeBuffer; CByteDynBuffer _buffer;
size_t _size;
public: public:
void Init() { _writeBuffer.Init(); } CDynBufSeqOutStream(): _size(0) {}
size_t GetSize() const { return _writeBuffer.GetSize(); } void Init() { _size = 0; }
const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } size_t GetSize() const { return _size; }
const Byte *GetBuffer() const { return _buffer; }
void CopyToBuffer(CByteBuffer &dest) const;
Byte *GetBufPtrForWriting(size_t addSize);
void UpdateSize(size_t addSize) { _size += addSize; }
MY_UNKNOWN_IMP MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
}; };
class CSequentialOutStreamImp2: class CBufPtrSeqOutStream:
public ISequentialOutStream, public ISequentialOutStream,
public CMyUnknownImp public CMyUnknownImp
{ {
@@ -74,40 +80,18 @@ class CSequentialOutStreamImp2:
size_t _size; size_t _size;
size_t _pos; size_t _pos;
public: public:
void Init(Byte *buffer, size_t size) void Init(Byte *buffer, size_t size)
{ {
_buffer = buffer; _buffer = buffer;
_pos = 0; _pos = 0;
_size = size; _size = size;
} }
size_t GetPos() const { return _pos; } size_t GetPos() const { return _pos; }
MY_UNKNOWN_IMP MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
}; };
class CSequentialInStreamSizeCount:
public ISequentialInStream,
public CMyUnknownImp
{
CMyComPtr<ISequentialInStream> _stream;
UInt64 _size;
public:
void Init(ISequentialInStream *stream)
{
_stream = stream;
_size = 0;
}
UInt64 GetSize() const { return _size; }
MY_UNKNOWN_IMP
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
class CSequentialOutStreamSizeCount: class CSequentialOutStreamSizeCount:
public ISequentialOutStream, public ISequentialOutStream,
public CMyUnknownImp public CMyUnknownImp
@@ -120,8 +104,32 @@ public:
UInt64 GetSize() const { return _size; } UInt64 GetSize() const { return _size; }
MY_UNKNOWN_IMP MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
}; };
class CCachedInStream:
public IInStream,
public CMyUnknownImp
{
UInt64 *_tags;
Byte *_data;
size_t _dataSize;
unsigned _blockSizeLog;
unsigned _numBlocksLog;
UInt64 _size;
UInt64 _pos;
protected:
virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;
public:
CCachedInStream(): _tags(0), _data(0) {}
virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!
void Free();
bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog);
void Init(UInt64 size);
MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
#endif #endif

View File

@@ -108,7 +108,7 @@ HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *
if (_outSizeDefined) if (_outSizeDefined)
{ {
const UInt64 rem = _outSize - _outSizeProcessed; const UInt64 rem = _outSize - _outSizeProcessed;
if (rem < curSize) if (rem <= curSize)
{ {
curSize = (SizeT)rem; curSize = (SizeT)rem;
if (FinishStream) if (FinishStream)

View File

@@ -128,6 +128,8 @@ Handler GUIDs:
0C xz 0C xz
0D ppmd 0D ppmd
D2 SquashFS
D3 CramFS
D4 APM D4 APM
D5 Mslz D5 Mslz
D6 Flv D6 Flv

View File

@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 17 #define MY_VER_MINOR 20
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "9.17 beta" #define MY_VERSION "9.20"
#define MY_7ZIP_VERSION "7-Zip 9.17 beta" #define MY_7ZIP_VERSION "7-Zip 9.20"
#define MY_DATE "2010-10-04" #define MY_DATE "2010-11-18"
#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov" #define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE

View File

@@ -60,6 +60,7 @@ enum
kpidSectorSize, kpidSectorSize,
kpidPosixAttrib, kpidPosixAttrib,
kpidLink, kpidLink,
kpidError,
kpidTotalSize = 0x1100, kpidTotalSize = 0x1100,
kpidFreeSpace, kpidFreeSpace,

View File

@@ -609,7 +609,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
CArc &arc = _archiveLink.Arcs[level]; CArc &arc = _archiveLink.Arcs[level];
switch(propID) switch(propID)
{ {
case kpidType: prop = _codecs->Formats[arc.FormatIndex].Name; break; case kpidType: prop = GetTypeOfArc(arc); break;
case kpidPath: prop = arc.Path; break; case kpidPath: prop = arc.Path; break;
default: return arc.Archive->GetArchiveProperty(propID, value); default: return arc.Archive->GetArchiveProperty(propID, value);
} }

View File

@@ -206,6 +206,27 @@ public:
const CArc &GetArc() { return _archiveLink.Arcs.Back(); } const CArc &GetArc() { return _archiveLink.Arcs.Back(); }
IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; } bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; }
UString GetTypeOfArc(const CArc &arc) const { return _codecs->Formats[arc.FormatIndex].Name; }
UString GetErrorMessage() const
{
UString s;
for (int i = _archiveLink.Arcs.Size() - 1; i >= 0; i--)
{
const CArc &arc = _archiveLink.Arcs[i];
if (arc.ErrorMessage.IsEmpty())
continue;
if (!s.IsEmpty())
s += L"--------------------\n";
s += arc.ErrorMessage;
s += L"\n\n[";
s += GetTypeOfArc(arc);
s += L"] ";
s += arc.Path;
s += L"\n";
}
return s;
}
}; };
#ifdef NEW_FOLDER_INTERFACE #ifdef NEW_FOLDER_INTERFACE

View File

@@ -187,6 +187,7 @@ static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfil
static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line";
static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kTerminalOutError = "I won't write compressed data to a terminal";
static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";
static const char *kEmptyFilePath = "Empty file path";
static void ThrowException(const char *errorMessage) static void ThrowException(const char *errorMessage)
{ {
@@ -301,6 +302,8 @@ static void AddToCensorFromNonSwitchesStrings(
for (int i = startIndex; i < nonSwitchStrings.Size(); i++) for (int i = startIndex; i < nonSwitchStrings.Size(); i++)
{ {
const UString &s = nonSwitchStrings[i]; const UString &s = nonSwitchStrings[i];
if (s.IsEmpty())
throw kEmptyFilePath;
if (s[0] == kFileListID) if (s[0] == kFileListID)
AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);
else else
@@ -861,6 +864,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
if (curCommandIndex >= numNonSwitchStrings) if (curCommandIndex >= numNonSwitchStrings)
ThrowUserErrorException(); ThrowUserErrorException();
options.ArchiveName = nonSwitchStrings[curCommandIndex++]; options.ArchiveName = nonSwitchStrings[curCommandIndex++];
if (options.ArchiveName.IsEmpty())
ThrowUserErrorException();
} }
AddToCensorFromNonSwitchesStrings( AddToCensorFromNonSwitchesStrings(

View File

@@ -228,6 +228,15 @@ HRESULT DecompressArchives(
} }
#endif #endif
for (int v = 0; v < archiveLink.Arcs.Size(); v++)
{
const UString &s = archiveLink.Arcs[v].ErrorMessage;
if (!s.IsEmpty())
{
RINOK(extractCallback->MessageError(s));
}
}
CArc &arc = archiveLink.Arcs.Back(); CArc &arc = archiveLink.Arcs.Back();
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
arc.MTime = fi.MTime; arc.MTime = fi.MTime;

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/Types.h"
#include "Common/Wildcard.h" #include "Common/Wildcard.h"
#include "ExtractingFilePath.h" #include "ExtractingFilePath.h"

View File

@@ -111,6 +111,7 @@ HRESULT CArc::OpenStream(
IArchiveOpenCallback *callback) IArchiveOpenCallback *callback)
{ {
Archive.Release(); Archive.Release();
ErrorMessage.Empty();
const UString fileName = ExtractFileNameFromPath(Path); const UString fileName = ExtractFileNameFromPath(Path);
UString extension; UString extension;
{ {
@@ -299,6 +300,13 @@ HRESULT CArc::OpenStream(
continue; continue;
RINOK(result); RINOK(result);
{
NCOM::CPropVariant prop;
archive->GetArchiveProperty(kpidError, &prop);
if (prop.vt != VT_EMPTY)
ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";
}
Archive = archive; Archive = archive;
const CArcInfoEx &format = codecs->Formats[FormatIndex]; const CArcInfoEx &format = codecs->Formats[FormatIndex];
if (format.Exts.Size() == 0) if (format.Exts.Size() == 0)

View File

@@ -24,6 +24,7 @@ struct CArc
int SubfileIndex; int SubfileIndex;
FILETIME MTime; FILETIME MTime;
bool MTimeDefined; bool MTimeDefined;
UString ErrorMessage;
CArc(): MTimeDefined(false) {} CArc(): MTimeDefined(false) {}

View File

@@ -45,6 +45,7 @@ static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";
16 VIRTUAL 16 VIRTUAL
*/ */
static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; #define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';
UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)
@@ -92,17 +93,21 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful
UString res; UString res;
UInt32 a = prop.ulVal; UInt32 a = prop.ulVal;
wchar_t temp[16]; wchar_t temp[16];
temp[0] = MY_ATTR_CHAR(a, 14, L'd');
temp[0] = kPosixTypes[(a >> 12) & 0xF];
for (int i = 6; i >= 0; i -= 3) for (int i = 6; i >= 0; i -= 3)
{ {
temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r'); temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r');
temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w'); temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w');
temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x'); temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x');
} }
if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S');
if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S');
if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T');
temp[10] = 0; temp[10] = 0;
res = temp; res = temp;
a &= ~0x1FF;
a &= ~0xC000; a &= ~(UInt32)0xFFFF;
if (a != 0) if (a != 0)
{ {
ConvertUInt32ToHex(a, temp); ConvertUInt32ToHex(a, temp);

View File

@@ -387,12 +387,11 @@ static HRESULT Compress(
CMyComPtr<ISequentialOutStream> outStream; CMyComPtr<ISequentialOutStream> outStream;
const UString &archiveName = archivePath.GetFinalPath();
if (!stdOutMode) if (!stdOutMode)
{ {
UString resultPath; UString resultPath;
int pos; int pos;
if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))
throw 1417161; throw 1417161;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
} }
@@ -676,35 +675,38 @@ HRESULT UpdateArchive(
} }
} }
const UString archiveName = options.ArchivePath.GetFinalPath();
CArchiveLink archiveLink; CArchiveLink arcLink;
NFind::CFileInfoW archiveFileInfo; const UString arcPath = options.ArchivePath.GetFinalPath();
if (archiveFileInfo.Find(archiveName)) if (!options.ArchivePath.OriginalPath.IsEmpty())
{ {
if (archiveFileInfo.IsDir()) NFind::CFileInfoW fi;
throw "there is no such archive"; if (fi.Find(arcPath))
if (options.VolumesSizes.Size() > 0)
return E_NOTIMPL;
CIntVector formatIndices;
if (options.MethodMode.FormatIndex >= 0)
formatIndices.Add(options.MethodMode.FormatIndex);
HRESULT result = archiveLink.Open2(codecs, formatIndices, false, NULL, archiveName, openCallback);
if (result == E_ABORT)
return result;
RINOK(callback->OpenResult(archiveName, result));
RINOK(result);
if (archiveLink.VolumePaths.Size() > 1)
{ {
errorInfo.SystemError = (DWORD)E_NOTIMPL; if (fi.IsDir())
errorInfo.Message = L"Updating for multivolume archives is not implemented"; throw "there is no such archive";
return E_NOTIMPL; if (options.VolumesSizes.Size() > 0)
} return E_NOTIMPL;
CIntVector formatIndices;
if (options.MethodMode.FormatIndex >= 0)
formatIndices.Add(options.MethodMode.FormatIndex);
HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);
if (result == E_ABORT)
return result;
RINOK(callback->OpenResult(arcPath, result));
RINOK(result);
if (arcLink.VolumePaths.Size() > 1)
{
errorInfo.SystemError = (DWORD)E_NOTIMPL;
errorInfo.Message = L"Updating for multivolume archives is not implemented";
return E_NOTIMPL;
}
CArc &arc = archiveLink.Arcs.Back(); CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = !archiveFileInfo.IsDevice; arc.MTimeDefined = !fi.IsDevice;
arc.MTime = archiveFileInfo.MTime; arc.MTime = fi.MTime;
}
} }
else else
{ {
@@ -771,7 +773,7 @@ HRESULT UpdateArchive(
bool createTempFile = false; bool createTempFile = false;
bool thereIsInArchive = archiveLink.IsOpen; bool thereIsInArchive = arcLink.IsOpen;
if (!options.StdOutMode && options.UpdateArchiveItself) if (!options.StdOutMode && options.UpdateArchiveItself)
{ {
@@ -800,7 +802,8 @@ HRESULT UpdateArchive(
// ap.Temp = true; // ap.Temp = true;
// ap.TempPrefix = tempDirPrefix; // ap.TempPrefix = tempDirPrefix;
} }
if (i > 0 || !createTempFile) if (!options.StdOutMode &&
(i > 0 || !createTempFile))
{ {
const UString &path = ap.GetFinalPath(); const UString &path = ap.GetFinalPath();
if (NFind::DoesFileOrDirExist(path)) if (NFind::DoesFileOrDirExist(path))
@@ -816,18 +819,18 @@ HRESULT UpdateArchive(
CObjectVector<CArcItem> arcItems; CObjectVector<CArcItem> arcItems;
if (thereIsInArchive) if (thereIsInArchive)
{ {
RINOK(EnumerateInArchiveItems(censor, archiveLink.Arcs.Back(), arcItems)); RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));
} }
RINOK(UpdateWithItemLists(codecs, options, RINOK(UpdateWithItemLists(codecs, options,
thereIsInArchive ? archiveLink.GetArchive() : 0, thereIsInArchive ? arcLink.GetArchive() : 0,
arcItems, dirItems, arcItems, dirItems,
tempFiles, errorInfo, callback)); tempFiles, errorInfo, callback));
if (thereIsInArchive) if (thereIsInArchive)
{ {
RINOK(archiveLink.Close()); RINOK(arcLink.Close());
archiveLink.Release(); arcLink.Release();
} }
tempFiles.Paths.Clear(); tempFiles.Paths.Clear();
@@ -838,19 +841,19 @@ HRESULT UpdateArchive(
CArchivePath &ap = options.Commands[0].ArchivePath; CArchivePath &ap = options.Commands[0].ArchivePath;
const UString &tempPath = ap.GetTempPath(); const UString &tempPath = ap.GetTempPath();
if (thereIsInArchive) if (thereIsInArchive)
if (!NDirectory::DeleteFileAlways(archiveName)) if (!NDirectory::DeleteFileAlways(arcPath))
{ {
errorInfo.SystemError = ::GetLastError(); errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot delete the file"; errorInfo.Message = L"7-Zip cannot delete the file";
errorInfo.FileName = archiveName; errorInfo.FileName = arcPath;
return E_FAIL; return E_FAIL;
} }
if (!NDirectory::MyMoveFile(tempPath, archiveName)) if (!NDirectory::MyMoveFile(tempPath, arcPath))
{ {
errorInfo.SystemError = ::GetLastError(); errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot move the file"; errorInfo.Message = L"7-Zip cannot move the file";
errorInfo.FileName = tempPath; errorInfo.FileName = tempPath;
errorInfo.FileName2 = archiveName; errorInfo.FileName2 = arcPath;
return E_FAIL; return E_FAIL;
} }
} }

View File

@@ -1,20 +1,20 @@
// Update.h // Update.h
#ifndef __UPDATE_H #ifndef __COMMON_UPDATE_H
#define __UPDATE_H #define __COMMON_UPDATE_H
#include "Common/Wildcard.h" #include "Common/Wildcard.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "UpdateAction.h"
#include "ArchiveOpenCallback.h" #include "ArchiveOpenCallback.h"
#include "UpdateCallback.h"
#include "Property.h"
#include "LoadCodecs.h" #include "LoadCodecs.h"
#include "Property.h"
#include "UpdateAction.h"
#include "UpdateCallback.h"
struct CArchivePath struct CArchivePath
{ {
UString OriginalPath;
UString Prefix; // path(folder) prefix including slash UString Prefix; // path(folder) prefix including slash
UString Name; // base name UString Name; // base name
UString BaseExtension; // archive type extension or "exe" extension UString BaseExtension; // archive type extension or "exe" extension
@@ -28,11 +28,11 @@ struct CArchivePath
void ParseFromPath(const UString &path) void ParseFromPath(const UString &path)
{ {
OriginalPath = path;
SplitPathToParts(path, Prefix, Name); SplitPathToParts(path, Prefix, Name);
if (Name.IsEmpty())
return;
int dotPos = Name.ReverseFind(L'.'); int dotPos = Name.ReverseFind(L'.');
if (dotPos <= 0) if (dotPos < 0)
return; return;
if (dotPos == Name.Length() - 1) if (dotPos == Name.Length() - 1)
{ {

View File

@@ -29,7 +29,7 @@ struct CPropIdToName
const wchar_t *Name; const wchar_t *Name;
}; };
static CPropIdToName kPropIdToName[] = static const CPropIdToName kPropIdToName[] =
{ {
{ kpidPath, L"Path" }, { kpidPath, L"Path" },
{ kpidName, L"Name" }, { kpidName, L"Name" },
@@ -82,6 +82,7 @@ static CPropIdToName kPropIdToName[] =
{ kpidSectorSize, L"Sector Size" }, { kpidSectorSize, L"Sector Size" },
{ kpidPosixAttrib, L"Mode" }, { kpidPosixAttrib, L"Mode" },
{ kpidLink, L"Link" }, { kpidLink, L"Link" },
{ kpidError, L"Error" },
{ kpidTotalSize, L"Total Size" }, { kpidTotalSize, L"Total Size" },
{ kpidFreeSpace, L"Free Space" }, { kpidFreeSpace, L"Free Space" },
@@ -505,6 +506,8 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
g_StdOut << "--\n"; g_StdOut << "--\n";
PrintPropPair(L"Path", arc.Path); PrintPropPair(L"Path", arc.Path);
PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);
if (!arc.ErrorMessage.IsEmpty())
PrintPropPair(L"Error", arc.ErrorMessage);
UInt32 numProps; UInt32 numProps;
IInArchive *archive = arc.Archive; IInArchive *archive = arc.Archive;
if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)

View File

@@ -26,7 +26,6 @@
#ifdef EXTERNAL_CODECS #ifdef EXTERNAL_CODECS
#include "../Common/LoadCodecs.h" #include "../Common/LoadCodecs.h"
#endif #endif
#include "../Common/PropIDUtils.h"
#include "BenchCon.h" #include "BenchCon.h"
#include "ExtractCallbackConsole.h" #include "ExtractCallbackConsole.h"
@@ -457,8 +456,8 @@ int Main2(
<< "Compressed: " << stat.PackSize << endl; << "Compressed: " << stat.PackSize << endl;
if (options.CalcCrc) if (options.CalcCrc)
{ {
wchar_t s[16]; char s[16];
ConvertUInt32ToHex(stat.CrcSum, s); ConvertUInt32ToHexWithZeros(stat.CrcSum, s);
stdStream << "CRC: " << s << endl; stdStream << "CRC: " << s << endl;
} }
} }

View File

@@ -53,9 +53,35 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
} }
} }
#ifdef _WIN32
#ifndef UNDER_CE
#define MY_DISABLE_ECHO
#endif
#endif
UString GetPassword(CStdOutStream *outStream) UString GetPassword(CStdOutStream *outStream)
{ {
(*outStream) << "\nEnter password:"; (*outStream) << "\nEnter password"
#ifdef MY_DISABLE_ECHO
" (will not be echoed)"
#endif
":";
outStream->Flush(); outStream->Flush();
#ifdef MY_DISABLE_ECHO
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
bool wasChanged = false;
DWORD mode = 0;
if (console != INVALID_HANDLE_VALUE && console != 0)
if (GetConsoleMode(console, &mode))
wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);
UString res = g_StdIn.ScanUStringUntilNewLine();
if (wasChanged)
SetConsoleMode(console, mode);
(*outStream) << "\n";
outStream->Flush();
return res;
#else
return g_StdIn.ScanUStringUntilNewLine(); return g_StdIn.ScanUStringUntilNewLine();
#endif
} }

View File

@@ -53,7 +53,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far2\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none # SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Far - Win32 Debug" !ELSEIF "$(CFG)" == "Far - Win32 Debug"
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far2\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept
!ENDIF !ENDIF

View File

@@ -61,7 +61,7 @@ struct PluginPanelItem
char **CustomColumnData; char **CustomColumnData;
int CustomColumnNumber; int CustomColumnNumber;
DWORD_PTR UserData; DWORD_PTR UserData;
DWORD CRC32; DWORD CRC32;
DWORD_PTR Reserved[2]; DWORD_PTR Reserved[2];
}; };
@@ -484,34 +484,34 @@ enum OPERATION_MODES {
/* /*
EXTERN_C_BEGIN EXTERN_C_BEGIN
void WINAPI _export ClosePluginW(HANDLE hPlugin); void WINAPI _export ClosePluginW(HANDLE hPlugin);
int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode);
int WINAPI _export ConfigureW(int ItemNumber); int WINAPI _export ConfigureW(int ItemNumber);
int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
void WINAPI _export ExitFARW(void); void WINAPI _export ExitFARW(void);
void WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); void WINAPI _export FreeFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber);
void WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber); void WINAPI _export FreeVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber);
int WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); int WINAPI _export GetFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode);
int WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); int WINAPI _export GetFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode);
int WINAPI _export GetMinFarVersionW(void); int WINAPI _export GetMinFarVersionW(void);
void WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info); void WINAPI _export GetOpenPluginInfoW(HANDLE hPlugin,struct OpenPluginInfo *Info);
void WINAPI _export GetPluginInfoW(struct PluginInfo *Info); void WINAPI _export GetPluginInfoW(struct PluginInfo *Info);
int WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); int WINAPI _export GetVirtualFindDataW(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path);
int WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode); int WINAPI _export MakeDirectoryW(HANDLE hPlugin,const wchar_t **Name,int OpMode);
HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode); HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode);
HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item); HANDLE WINAPI _export OpenPluginW(int OpenFrom,INT_PTR Item);
int WINAPI _export ProcessDialogEventW(int Event,void *Param); int WINAPI _export ProcessDialogEventW(int Event,void *Param);
int WINAPI _export ProcessEditorEventW(int Event,void *Param); int WINAPI _export ProcessEditorEventW(int Event,void *Param);
int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec); int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec);
int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param); int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param);
int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState); int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState);
int WINAPI _export ProcessSynchroEventW(int Event,void *Param); int WINAPI _export ProcessSynchroEventW(int Event,void *Param);
int WINAPI _export ProcessViewerEventW(int Event,void *Param); int WINAPI _export ProcessViewerEventW(int Event,void *Param);
int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode);
int WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode); int WINAPI _export SetDirectoryW(HANDLE hPlugin,const wchar_t *Dir,int OpMode);
int WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber); int WINAPI _export SetFindListW(HANDLE hPlugin,const struct PluginPanelItem *PanelItem,int ItemsNumber);
void WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info); void WINAPI _export SetStartupInfoW(const struct PluginStartupInfo *Info);
EXTERN_C_END EXTERN_C_END
*/ */

View File

@@ -366,7 +366,8 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name)
// ::OutputDebugStringA("before OpenArchive\n"); // ::OutputDebugStringA("before OpenArchive\n");
archiveHandler = new CAgent; CAgent *agent = new CAgent;
archiveHandler = agent;
CMyComBSTR archiveType; CMyComBSTR archiveType;
HRESULT result = archiveHandler->Open(NULL, HRESULT result = archiveHandler->Open(NULL,
GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback); GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, openArchiveCallback);
@@ -381,6 +382,10 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name)
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
UString errorMessage = agent->GetErrorMessage();
if (!errorMessage.IsEmpty())
PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP));
// ::OutputDebugStringA("after OpenArchive\n"); // ::OutputDebugStringA("after OpenArchive\n");
CPlugin *plugin = new CPlugin( CPlugin *plugin = new CPlugin(

View File

@@ -326,6 +326,7 @@ static CPROPIDToName kPROPIDToName[] =
{ kpidSectorSize, NMessageID::kSectorSize }, { kpidSectorSize, NMessageID::kSectorSize },
{ kpidPosixAttrib, NMessageID::kPosixAttrib }, { kpidPosixAttrib, NMessageID::kPosixAttrib },
{ kpidLink, NMessageID::kLink }, { kpidLink, NMessageID::kLink },
{ kpidError, NMessageID::kError },
{ kpidTotalSize, NMessageID::kTotalSize }, { kpidTotalSize, NMessageID::kTotalSize },
{ kpidFreeSpace, NMessageID::kFreeSpace }, { kpidFreeSpace, NMessageID::kFreeSpace },
@@ -628,17 +629,20 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
if (getProps->GetArcNumProps(level, &numProps) == S_OK) if (getProps->GetArcNumProps(level, &numProps) == S_OK)
{ {
InsertSeparator(m_InfoLines, numItems); InsertSeparator(m_InfoLines, numItems);
for (Int32 i = -2; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)
{ {
CMyComBSTR name; CMyComBSTR name;
PROPID propID; PROPID propID;
VARTYPE vt; VARTYPE vt;
if (i == -2) switch (i)
propID = kpidPath; {
else if (i == -1) case -3: propID = kpidPath; break;
propID = kpidType; case -2: propID = kpidType; break;
else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) case -1: propID = kpidError; break;
continue; default:
if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)
continue;
}
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
if (getProps->GetArcProp(level, propID, &prop) != S_OK) if (getProps->GetArcProp(level, propID, &prop) != S_OK)
continue; continue;

View File

@@ -103,7 +103,7 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(/* m_ArchiveHandler, */ &progressBox); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
result = outArchive->DeleteItems( result = outArchive->DeleteItems(

View File

@@ -234,7 +234,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(/* m_ArchiveHandler, */ &progressBox); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
return NFileOperationReturnCode::kError; return NFileOperationReturnCode::kError;
@@ -742,7 +742,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(/* archiveHandler, */ &progressBox); updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer);
RINOK(SetOutProperties(outArchive, compressionInfo.Level)); RINOK(SetOutProperties(outArchive, compressionInfo.Level));

View File

@@ -125,6 +125,8 @@ bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
} }
case 'A': case 'A':
{ {
// probably that code is unused ?
/*
bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
if (ctrl) if (ctrl)
{ {
@@ -133,6 +135,7 @@ bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
_listView.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); _listView.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
return true; return true;
} }
*/
} }
} }
} }

View File

@@ -9,6 +9,7 @@
#include "Windows/FileDir.h" #include "Windows/FileDir.h"
#include "Windows/FileFind.h" #include "Windows/FileFind.h"
#include "Windows/Process.h" #include "Windows/Process.h"
#include "Windows/PropVariant.h"
#include "Windows/Thread.h" #include "Windows/Thread.h"
#include "../Common/ExtractingFilePath.h" #include "../Common/ExtractingFilePath.h"
@@ -113,6 +114,46 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
_flatMode = _flatModeForArc; _flatMode = _flatModeForArc;
CMyComPtr<IGetFolderArcProps> getFolderArcProps;
_folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
if (getFolderArcProps)
{
CMyComPtr<IFolderArcProps> arcProps;
getFolderArcProps->GetFolderArcProps(&arcProps);
if (arcProps)
{
UString s;
UInt32 numLevels;
if (arcProps->GetArcNumLevels(&numLevels) != S_OK)
numLevels = 0;
for (UInt32 level2 = 0; level2 < numLevels; level2++)
{
UInt32 level = numLevels - 1 - level2;
PROPID propIDs[] = { kpidError, kpidPath, kpidType } ;
UString values[3];
for (Int32 i = 0; i < 3; i++)
{
CMyComBSTR name;
NCOM::CPropVariant prop;
if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK)
continue;
if (prop.vt != VT_EMPTY)
values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?";
}
if (!values[0].IsEmpty())
{
if (!s.IsEmpty())
s += L"--------------------\n";
s += values[0]; s += L"\n\n[";
s += values[2]; s += L"] ";
s += values[1]; s += L"\n";
}
}
if (!s.IsEmpty())
MessageBox(s);
}
}
return S_OK; return S_OK;
} }
@@ -169,9 +210,9 @@ static const char *kStartExtensions =
#endif #endif
" exe bat com" " exe bat com"
" chm" " chm"
" msi doc xls ppt pps wps wpt wks xlr wdb vsd" " msi doc xls ppt pps wps wpt wks xlr wdb vsd pub"
" docx docm dotx dotm xlsx xlsm xltx xltm xlsb" " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps"
" xlam pptx pptm potx potm ppam ppsx ppsm xsn" " xlam pptx pptm potx potm ppam ppsx ppsm xsn"
" mpp" " mpp"
" msg" " msg"

View File

@@ -439,6 +439,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
{ {
if (focusedPos >= _listView.GetItemCount()) if (focusedPos >= _listView.GetItemCount())
focusedPos = _listView.GetItemCount() - 1; focusedPos = _listView.GetItemCount() - 1;
// we select item only in showDots mode.
SetFocusedSelectedItem(focusedPos, showDots); SetFocusedSelectedItem(focusedPos, showDots);
} }
// m_RedrawEnabled = true; // m_RedrawEnabled = true;
@@ -484,7 +485,7 @@ void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
{ {
int realIndex = GetRealItemIndex(focusedItem); int realIndex = GetRealItemIndex(focusedItem);
if (realIndex != kParentIndex) if (realIndex != kParentIndex)
indices.Add(realIndex); indices.Add(realIndex);
} }
} }
} }

View File

@@ -188,17 +188,20 @@ void CPanel::Properties()
if (getProps->GetArcNumProps(level, &numProps) == S_OK) if (getProps->GetArcNumProps(level, &numProps) == S_OK)
{ {
message += kSeparator; message += kSeparator;
for (Int32 i = -2; i < (Int32)numProps; i++) for (Int32 i = -3; i < (Int32)numProps; i++)
{ {
CMyComBSTR name; CMyComBSTR name;
PROPID propID; PROPID propID;
VARTYPE vt; VARTYPE vt;
if (i == -2) switch (i)
propID = kpidPath; {
else if (i == -1) case -3: propID = kpidPath; break;
propID = kpidType; case -2: propID = kpidType; break;
else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK) case -1: propID = kpidError; break;
continue; default:
if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)
continue;
}
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
if (getProps->GetArcProp(level, propID, &prop) != S_OK) if (getProps->GetArcProp(level, propID, &prop) != S_OK)
continue; continue;

View File

@@ -245,7 +245,14 @@ void CPanel::KillSelection()
{ {
int focused = _listView.GetFocusedItem(); int focused = _listView.GetFocusedItem();
if (focused >= 0) if (focused >= 0)
{
// CPanel::OnItemChanged notify for LVIS_SELECTED change doesn't work here. Why?
// so we change _selectedStatusVector[realIndex] here.
int realIndex = GetRealItemIndex(focused);
if (realIndex != kParentIndex)
_selectedStatusVector[realIndex] = true;
_listView.SetItemState(focused, LVIS_SELECTED, LVIS_SELECTED); _listView.SetItemState(focused, LVIS_SELECTED, LVIS_SELECTED);
}
} }
} }
@@ -297,4 +304,3 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
} }
return; return;
} }

View File

@@ -61,17 +61,19 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
// PROPID propID = panel->_properties[panel->_sortIndex].ID; // PROPID propID = panel->_properties[panel->_sortIndex].ID;
PROPID propID = panel->_sortID; PROPID propID = panel->_sortID;
NCOM::CPropVariant propVariant1, propVariant2; NCOM::CPropVariant prop1, prop2;
// Name must be first property // Name must be first property
panel->_folder->GetProperty((UINT32)lParam1, propID, &propVariant1); panel->_folder->GetProperty((UINT32)lParam1, propID, &prop1);
panel->_folder->GetProperty((UINT32)lParam2, propID, &propVariant2); panel->_folder->GetProperty((UINT32)lParam2, propID, &prop2);
if (propVariant1.vt != propVariant2.vt) if (prop1.vt != prop2.vt)
return 0; // It means some BUG
if (propVariant1.vt == VT_BSTR)
{ {
return _wcsicmp(propVariant1.bstrVal, propVariant2.bstrVal); return MyCompare(prop1.vt, prop2.vt);
} }
return propVariant1.Compare(propVariant2); if (prop1.vt == VT_BSTR)
{
return _wcsicmp(prop1.bstrVal, prop2.bstrVal);
}
return prop1.Compare(prop2);
// return 0; // return 0;
} }

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/Types.h"
#include "ProgramLocation.h" #include "ProgramLocation.h"
#include "Windows/DLL.h" #include "Windows/DLL.h"
@@ -20,4 +22,3 @@ bool GetProgramFolderPath(UString &folder)
folder = folder.Left(pos + 1); folder = folder.Left(pos + 1);
return true; return true;
} }

View File

@@ -75,6 +75,7 @@ static CPropertyIDNamePair kPropertyIDNamePairs[] =
{ kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 }, { kpidSectorSize, IDS_PROP_SECTOR_SIZE, 0x02000234 },
{ kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 }, { kpidPosixAttrib, IDS_PROP_POSIX_ATTRIB, 0x02000235 },
{ kpidLink, IDS_PROP_LINK, 0x02000236 }, { kpidLink, IDS_PROP_LINK, 0x02000236 },
{ kpidError, IDS_PROP_ERROR, 0x02000605 },
{ kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 }, { kpidTotalSize, IDS_PROP_TOTAL_SIZE, 0x03031100 },
{ kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 }, { kpidFreeSpace, IDS_PROP_FREE_SPACE, 0x03031101 },

View File

@@ -56,4 +56,5 @@ BEGIN
IDS_PROP_SECTOR_SIZE "Sector Size" IDS_PROP_SECTOR_SIZE "Sector Size"
IDS_PROP_POSIX_ATTRIB "Mode" IDS_PROP_POSIX_ATTRIB "Mode"
IDS_PROP_LINK "Link" IDS_PROP_LINK "Link"
IDS_PROP_ERROR "Error"
END END

View File

@@ -50,3 +50,4 @@
#define IDS_PROP_SECTOR_SIZE 52 #define IDS_PROP_SECTOR_SIZE 52
#define IDS_PROP_POSIX_ATTRIB 53 #define IDS_PROP_POSIX_ATTRIB 53
#define IDS_PROP_LINK 54 #define IDS_PROP_LINK 54
#define IDS_PROP_ERROR 55

View File

@@ -1038,7 +1038,13 @@ void CCompressDialog::SetDictionary()
if (i == 20 && j > 0) if (i == 20 && j > 0)
continue; continue;
UInt32 dictionary = (1 << i) + (j << (i - 1)); UInt32 dictionary = (1 << i) + (j << (i - 1));
if (dictionary > (1 << 30)) if (dictionary >
#ifdef _WIN64
(1 << 30)
#else
(1 << 29)
#endif
)
continue; continue;
AddDictionarySize(dictionary); AddDictionarySize(dictionary);
UInt64 decomprSize; UInt64 decomprSize;

View File

@@ -6,7 +6,7 @@
namespace NCommandLineParser { namespace NCommandLineParser {
void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
{ {
dest1.Empty(); dest1.Empty();
dest2.Empty(); dest2.Empty();
@@ -15,17 +15,17 @@ void SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
for (i = 0; i < src.Length(); i++) for (i = 0; i < src.Length(); i++)
{ {
wchar_t c = src[i]; wchar_t c = src[i];
if (c == L' ' && !quoteMode)
{
dest2 = src.Mid(i + 1);
return i != 0;
}
if (c == L'\"') if (c == L'\"')
quoteMode = !quoteMode; quoteMode = !quoteMode;
else if (c == L' ' && !quoteMode)
{
i++;
break;
}
else else
dest1 += c; dest1 += c;
} }
dest2 = src.Mid(i); return i != 0;
} }
void SplitCommandLine(const UString &s, UStringVector &parts) void SplitCommandLine(const UString &s, UStringVector &parts)
@@ -36,10 +36,7 @@ void SplitCommandLine(const UString &s, UStringVector &parts)
for (;;) for (;;)
{ {
UString s1, s2; UString s1, s2;
SplitCommandLine(sTemp, s1, s2); if (SplitCommandLine(sTemp, s1, s2))
// s1.Trim();
// s2.Trim();
if (!s1.IsEmpty())
parts.Add(s1); parts.Add(s1);
if (s2.IsEmpty()) if (s2.IsEmpty())
break; break;

View File

@@ -1,13 +1,13 @@
// Common/CommandLineParser.h // Common/CommandLineParser.h
#ifndef __COMMON_COMMANDLINEPARSER_H #ifndef __COMMON_COMMAND_LINE_PARSER_H
#define __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMAND_LINE_PARSER_H
#include "MyString.h" #include "MyString.h"
namespace NCommandLineParser { namespace NCommandLineParser {
void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
void SplitCommandLine(const UString &s, UStringVector &parts); void SplitCommandLine(const UString &s, UStringVector &parts);
namespace NSwitchType { namespace NSwitchType {

View File

@@ -1,7 +1,7 @@
// Common/DynamicBuffer.h // Common/DynamicBuffer.h
#ifndef __COMMON_DYNAMICBUFFER_H #ifndef __COMMON_DYNAMIC_BUFFER_H
#define __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMIC_BUFFER_H
#include "Buffer.h" #include "Buffer.h"
@@ -17,7 +17,10 @@ template <class T> class CDynamicBuffer: public CBuffer<T>
else else
delta = 4; delta = 4;
delta = MyMax(delta, size); delta = MyMax(delta, size);
SetCapacity(this->_capacity + delta); size_t newCap = this->_capacity + delta;
if (newCap < delta)
newCap = this->_capacity + size;
SetCapacity(newCap);
} }
public: public:
CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(): CBuffer<T>() {};

View File

@@ -64,3 +64,14 @@ void ConvertInt64ToString(Int64 value, wchar_t *s)
} }
ConvertUInt64ToString(value, s); ConvertUInt64ToString(value, s);
} }
void ConvertUInt32ToHexWithZeros(UInt32 value, char *s)
{
for (int i = 0; i < 8; i++)
{
int t = value & 0xF;
value >>= 4;
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[8] = '\0';
}

View File

@@ -14,4 +14,6 @@ void ConvertInt64ToString(Int64 value, wchar_t *s);
void ConvertUInt32ToString(UInt32 value, char *s); void ConvertUInt32ToString(UInt32 value, char *s);
void ConvertUInt32ToString(UInt32 value, wchar_t *s); void ConvertUInt32ToString(UInt32 value, wchar_t *s);
void ConvertUInt32ToHexWithZeros(UInt32 value, char *s);
#endif #endif

View File

@@ -7,10 +7,6 @@
#include "MyVector.h" #include "MyVector.h"
#ifdef _WIN32
#include "MyWindows.h"
#endif
template <class T> template <class T>
inline int MyStringLen(const T *s) inline int MyStringLen(const T *s)
{ {

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