diff options
322 files changed, 9881 insertions, 7651 deletions
@@ -1,15 +1,24 @@ -/* 7zCrc.c -- CRC32 calculation -2009-11-23 : Igor Pavlov : Public domain */ +/* 7zCrc.c -- CRC32 init +2010-12-01 : Igor Pavlov : Public domain */ #include "7zCrc.h" #include "CpuArch.h" #define kCrcPoly 0xEDB88320 -#ifdef MY_CPU_LE -#define CRC_NUM_TABLES 8 +#ifdef MY_CPU_X86_OR_AMD64 + #define CRC_NUM_TABLES 8 + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#elif defined(MY_CPU_LE) + #define CRC_NUM_TABLES 4 #else -#define CRC_NUM_TABLES 1 + #define CRC_NUM_TABLES 5 + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); #endif typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); @@ -17,25 +26,6 @@ typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, static CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; -#if CRC_NUM_TABLES == 1 - -#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) -{ - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = CRC_UPDATE_BYTE_2(v, *p); - return v; -} - -#else - -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); - -#endif - UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { return g_CrcUpdate(v, data, size, g_CrcTable); @@ -57,18 +47,37 @@ void MY_FAST_CALL CrcGenerateTable() r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } - #if CRC_NUM_TABLES == 1 - g_CrcUpdate = CrcUpdateT1; - #else for (; i < 256 * CRC_NUM_TABLES; i++) { UInt32 r = g_CrcTable[i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } + + #ifdef MY_CPU_LE + g_CrcUpdate = CrcUpdateT4; - #ifdef MY_CPU_X86_OR_AMD64 + + #if CRC_NUM_TABLES == 8 if (!CPU_Is_InOrder()) g_CrcUpdate = CrcUpdateT8; #endif + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_CrcUpdate = CrcUpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdate = CrcUpdateT1_BeT4; + } + } #endif } diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c index 6c766a20..a8d42a80 100755 --- a/C/7zCrcOpt.c +++ b/C/7zCrcOpt.c @@ -1,12 +1,12 @@ -/* 7zCrcOpt.c -- CRC32 calculation : optimized version -2009-11-23 : Igor Pavlov : Public domain */ +/* 7zCrcOpt.c -- CRC32 calculation +2010-12-01 : Igor Pavlov : Public domain */ #include "CpuArch.h" -#ifdef MY_CPU_LE - #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; @@ -32,3 +32,33 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U } #endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT32_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x000 + (v & 0xFF)] ^ + table[0x100 + ((v >> 8) & 0xFF)] ^ + table[0x200 + ((v >> 16) & 0xFF)] ^ + table[0x300 + ((v >> 24))]; + } + table -= 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/C/7zVersion.h b/C/7zVersion.h index 9d99c5df..9691d29f 100755 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 20 -#define MY_VER_BUILD 0 -#define MY_VERSION "9.20" -#define MY_DATE "2010-11-18" +#define MY_VER_MINOR 21 +#define MY_VER_BUILD 00 +#define MY_VERSION "9.21 beta" +#define MY_DATE "2011-04-11" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/C/CpuArch.h b/C/CpuArch.h index 01930c7e..e3d7af2e 100755 --- a/C/CpuArch.h +++ b/C/CpuArch.h @@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ +2010-12-01: Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H @@ -52,7 +52,7 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla #define MY_CPU_LE #endif -#if defined(__BIG_ENDIAN__) +#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__) #define MY_CPU_BE #endif diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c index 7ea1cc95..f3a6b821 100755 --- a/C/Lzma2Dec.c +++ b/C/Lzma2Dec.c @@ -1,5 +1,5 @@ /* Lzma2Dec.c -- LZMA2 Decoder -2009-05-03 : Igor Pavlov : Public domain */ +2010-12-15 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ @@ -330,27 +330,21 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte * SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { - CLzma2Dec decoder; + CLzma2Dec p; SRes res; SizeT outSize = *destLen, inSize = *srcLen; - Byte props[LZMA_PROPS_SIZE]; - - Lzma2Dec_Construct(&decoder); - *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; - decoder.decoder.dic = dest; - decoder.decoder.dicBufSize = outSize; - - RINOK(Lzma2Dec_GetOldProps(prop, props)); - RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); - + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); *srcLen = inSize; - res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); - *destLen = decoder.decoder.dicPos; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; - - LzmaDec_FreeProbs(&decoder.decoder, alloc); + Lzma2Dec_FreeProbs(&p, alloc); return res; } diff --git a/C/LzmaDec.c b/C/LzmaDec.c index 2036761b..8c1a1486 100755 --- a/C/LzmaDec.c +++ b/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2009-09-20 : Igor Pavlov : Public domain */ +2010-12-15 : Igor Pavlov : Public domain */ #include "LzmaDec.h" @@ -442,8 +442,9 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) p->processedPos += len; p->remainLen -= len; - while (len-- != 0) + while (len != 0) { + len--; dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } @@ -972,28 +973,21 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, { CLzmaDec p; SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); p.dic = dest; p.dicBufSize = outSize; - LzmaDec_Init(&p); - *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - + *destLen = p.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index cf131388..ef26e0cf 100755 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2010-04-16 : Igor Pavlov : Public domain */ +2011-01-27 : Igor Pavlov : Public domain */ #include <string.h> @@ -46,6 +46,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; + p->reduceSize = (UInt32)(Int32)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } @@ -56,6 +57,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + for (i = 15; i <= 30; i++) + { + if (p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if (p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; @@ -329,7 +339,6 @@ typedef struct SRes result; UInt32 dictSize; - UInt32 matchFinderCycles; int needInit; @@ -398,7 +407,6 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; - p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h index 200d60eb..b8d9ce77 100755 --- a/C/LzmaEnc.h +++ b/C/LzmaEnc.h @@ -1,14 +1,12 @@ /* LzmaEnc.h -- LZMA Encoder -2009-02-07 : Igor Pavlov : Public domain */ +2011-01-27 : Igor Pavlov : Public domain */ #ifndef __LZMA_ENC_H #define __LZMA_ENC_H #include "Types.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN #define LZMA_PROPS_SIZE 5 @@ -18,6 +16,8 @@ typedef struct _CLzmaEncProps UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ + UInt32 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. + Encoder uses this value to reduce dictionary size */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ @@ -73,8 +73,6 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif @@ -1,5 +1,5 @@ /* Ppmd.h -- PPMD codec common code -2010-03-12 : Igor Pavlov : Public domain +2011-01-27 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #ifndef __PPMD_H @@ -29,6 +29,9 @@ EXTERN_C_BEGIN #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) +#pragma pack(push, 1) +/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ + /* SEE-contexts for PPM-contexts with masked symbols */ typedef struct { @@ -48,6 +51,8 @@ typedef struct UInt16 SuccessorHigh; } CPpmd_State; +#pragma pack(pop) + typedef #ifdef PPMD_32BIT CPpmd_State * @@ -1,5 +1,5 @@ /* Ppmd8.h -- PPMdI codec -2010-03-24 : Igor Pavlov : Public domain +2011-01-27 : Igor Pavlov : Public domain This code is based on: PPMd var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ @@ -24,6 +24,8 @@ typedef #endif CPpmd8_Context_Ref; +#pragma pack(push, 1) + typedef struct CPpmd8_Context_ { Byte NumStats; @@ -33,6 +35,8 @@ typedef struct CPpmd8_Context_ CPpmd8_Context_Ref Suffix; } CPpmd8_Context; +#pragma pack(pop) + #define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) /* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c index a15d7729..a8e3f587 100755 --- a/C/Util/SfxSetup/SfxSetup.c +++ b/C/Util/SfxSetup/SfxSetup.c @@ -1,5 +1,5 @@ /* SfxSetup.c - 7z SFX Setup -2010-11-11 : Igor Pavlov : Public domain */ +2010-12-13 : Igor Pavlov : Public domain */ #ifndef UNICODE #define UNICODE @@ -128,26 +128,21 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos) *resPos = 0; for (;;) { - size_t numTests, pos; + size_t processed, 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++) + processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + processed += numPrevBytes; + if (processed < k7zStartHeaderSize || + (processed == k7zStartHeaderSize && numPrevBytes != 0)) + return False; + processed -= k7zStartHeaderSize; + for (pos = 0; pos <= processed; pos++) { - for (; buf[pos] != '7' && pos < numTests; pos++); - if (pos == numTests) + for (; buf[pos] != '7' && pos <= processed; pos++); + if (pos > processed) break; if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) @@ -156,9 +151,9 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos) return True; } } - *resPos += numTests; - numPrevBytes -= numTests; - memmove(buf, buf + numTests, numPrevBytes); + *resPos += processed; + numPrevBytes = k7zStartHeaderSize; + memmove(buf, buf + processed, k7zStartHeaderSize); } } diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile index f3f78c81..ce1fbc9d 100755 --- a/C/Util/SfxSetup/makefile +++ b/C/Util/SfxSetup/makefile @@ -1,6 +1,6 @@ PROG = 7zS2.sfx LIBS = $(LIBS) -CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS C_OBJS = \ $O\7zAlloc.obj \ @@ -1,5 +1,5 @@ /* Xz.h - Xz interface -2010-09-17 : Igor Pavlov : Public domain */ +2011-01-09 : Igor Pavlov : Public domain */ #ifndef __XZ_H #define __XZ_H @@ -220,7 +220,8 @@ typedef struct Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; } CXzUnpacker; -SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Init(CXzUnpacker *p); void XzUnpacker_Free(CXzUnpacker *p); /* @@ -232,8 +233,9 @@ finishMode: Returns: SZ_OK status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams, + call XzUnpacker_IsStreamWasFinished to check that current stream was finished SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties @@ -1,5 +1,5 @@ /* XzDec.c -- Xz Decode -2010-04-16 : Igor Pavlov : Public domain */ +2011-02-07 : Igor Pavlov : Public domain */ /* #define XZ_DUMP */ @@ -18,7 +18,8 @@ #include "Lzma2Dec.h" #ifdef USE_SUBBLOCK -#include "SbDec.h" +#include "Bcj3Dec.c" +#include "SbDec.c" #endif #include "Xz.h" @@ -72,7 +73,6 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a { CBraState *p = ((CBraState *)pp); alloc = alloc; - p->encodeMode = 0; p->ip = 0; if (p->methodId == XZ_ID_Delta) { @@ -195,7 +195,7 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, return SZ_OK; } -SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc) { CBraState *decoder; if (id != XZ_ID_Delta && @@ -211,6 +211,7 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) if (decoder == 0) return SZ_ERROR_MEM; decoder->methodId = (UInt32)id; + decoder->encodeMode = encodeMode; p->p = decoder; p->Free = BraState_Free; p->SetProps = BraState_SetProps; @@ -225,8 +226,8 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc) static void SbState_Free(void *pp, ISzAlloc *alloc) { - CSubblockDec *p = (CSubblockDec *)pp; - SubblockDec_Free(p, alloc); + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); alloc->Free(alloc, pp); } @@ -240,24 +241,32 @@ static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAl static void SbState_Init(void *pp) { - SubblockDec_Init((CSubblockDec *)pp); + SbDec_Init((CSbDec *)pp); } static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) { - ECoderStatus status; - SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status); + CSbDec *p = (CSbDec *)pp; + SRes res; srcWasFinished = srcWasFinished; - *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ return res; } SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) { - CSubblockDec *decoder; + CSbDec *decoder; p->p = 0; - decoder = alloc->Alloc(alloc, sizeof(CSubblockDec)); + decoder = alloc->Alloc(alloc, sizeof(CSbDec)); if (decoder == 0) return SZ_ERROR_MEM; p->p = decoder; @@ -265,7 +274,8 @@ SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) p->SetProps = SbState_SetProps; p->Init = SbState_Init; p->Code = SbState_Code; - SubblockDec_Construct(decoder); + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); return SZ_OK; } #endif @@ -369,7 +379,7 @@ SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) } if (coderIndex == 0) return SZ_ERROR_UNSUPPORTED; - return BraState_SetFromMethod(sc, methodId, p->alloc); + return BraState_SetFromMethod(sc, methodId, 0, p->alloc); } SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, @@ -587,13 +597,17 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) return SZ_OK; } -SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc) +void XzUnpacker_Init(CXzUnpacker *p) { - MixCoder_Construct(&p->decoder, alloc); p->state = XZ_STATE_STREAM_HEADER; p->pos = 0; p->numStreams = 0; - return SZ_OK; +} + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + XzUnpacker_Init(p); } void XzUnpacker_Free(CXzUnpacker *p) @@ -1,5 +1,5 @@ /* XzEnc.c -- Xz Encode -2009-06-04 : Igor Pavlov : Public domain */ +2011-02-07 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <string.h> @@ -9,7 +9,9 @@ #include "Bra.h" #include "CpuArch.h" #ifdef USE_SUBBLOCK -#include "SbEnc.h" +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" #endif #include "XzEnc.h" @@ -198,158 +200,147 @@ static size_t MyWrite(void *pp, const void *data, size_t size) /* ---------- CSeqInFilter ---------- */ -/* -typedef struct _IFilter -{ - void *p; - void (*Free)(void *p, ISzAlloc *alloc); - SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); - void (*Init)(void *p); - size_t (*Filter)(void *p, Byte *data, SizeT destLen); -} IFilter; - -#define FILT_BUF_SIZE (1 << 19) +#define FILTER_BUF_SIZE (1 << 20) typedef struct { ISeqInStream p; ISeqInStream *realStream; - UInt32 x86State; - UInt32 ip; - UInt64 processed; - CXzCheck check; - Byte buf[FILT_BUF_SIZE]; - UInt32 bufferPos; - UInt32 convertedPosBegin; - UInt32 convertedPosEnd; - IFilter *filter; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; } CSeqInFilter; static SRes SeqInFilter_Read(void *pp, void *data, size_t *size) { CSeqInFilter *p = (CSeqInFilter *)pp; - size_t remSize = *size; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return S_OK; *size = 0; - - while (remSize > 0) + for (;;) { - int i; - if (p->convertedPosBegin != p->convertedPosEnd) - { - UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin; - if (remSize < sizeTemp) - sizeTemp = (UInt32)remSize; - memmove(data, p->buf + p->convertedPosBegin, sizeTemp); - p->convertedPosBegin += sizeTemp; - data = (void *)((Byte *)data + sizeTemp); - remSize -= sizeTemp; - *size += sizeTemp; - break; - } - for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++) - p->buf[i] = p->buf[i + p->convertedPosEnd]; - p->bufferPos = i; - p->convertedPosBegin = p->convertedPosEnd = 0; - { - size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos; - RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp)); - p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp; - } - p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); - if (p->convertedPosEnd == 0) + if (!p->srcWasFinished && p->curPos == p->endPos) { - if (p->bufferPos == 0) - break; - else - { - p->convertedPosEnd = p->bufferPos; - continue; - } + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos)); + if (p->endPos == 0) + p->srcWasFinished = 1; } - if (p->convertedPosEnd > p->bufferPos) { - for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++) - p->buf[p->bufferPos] = 0; - p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos); + SizeT srcLen = p->endPos - p->curPos; + int wasFinished; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, &wasFinished); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != 0) + return res; } } - return SZ_OK; } -*/ -/* -typedef struct +static void SeqInFilter_Construct(CSeqInFilter *p) { - ISeqInStream p; - ISeqInStream *realStream; - CMixCoder mixCoder; - Byte buf[FILT_BUF_SIZE]; - UInt32 bufPos; - UInt32 bufSize; -} CMixCoderSeqInStream; + p->buf = NULL; + p->p.Read = SeqInFilter_Read; +} -static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size) +static void SeqInFilter_Free(CSeqInFilter *p) { - CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp; - SRes res = SZ_OK; - size_t remSize = *size; - *size = 0; - while (remSize > 0) + if (p->buf) { - if (p->bufPos == p->bufSize) - { - size_t curSize; - p->bufPos = p->bufSize = 0; - if (*size != 0) - break; - curSize = FILT_BUF_SIZE; - RINOK(p->realStream->Read(p->realStream, p->buf, &curSize)); - p->bufSize = (UInt32)curSize; - } - { - SizeT destLen = remSize; - SizeT srcLen = p->bufSize - p->bufPos; - res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0); - data = (void *)((Byte *)data + destLen); - remSize -= destLen; - *size += destLen; - p->bufPos += srcLen; - } + g_Alloc.Free(&g_Alloc, p->buf); + p->buf = NULL; } - return res; } -*/ + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc); + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props) +{ + if (!p->buf) + { + p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc)); + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc)); + p->StateCoder.Init(p->StateCoder.p); + return S_OK; +} + +/* ---------- CSbEncInStream ---------- */ #ifdef USE_SUBBLOCK + typedef struct { ISeqInStream p; - CSubblockEnc sb; - UInt64 processed; + ISeqInStream *inStream; + CSbEnc enc; } CSbEncInStream; -void SbEncInStream_Init(CSbEncInStream *p) +static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) { - p->processed = 0; - SubblockEnc_Init(&p->sb); + CSbEncInStream *p = (CSbEncInStream *)pp; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return S_OK; + for (;;) + { + if (p->enc.needRead && !p->enc.readWasFinished) + { + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)); + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; + } + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)); + if (*size != 0 || !p->enc.needRead) + return S_OK; + } } -static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) +void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc) { - CSbEncInStream *p = (CSbEncInStream *)pp; - SRes res = SubblockEnc_Read(&p->sb, data, size); - p->processed += *size; - return res; + SbEnc_Construct(&p->enc, alloc); + p->p.Read = SbEncInStream_Read; } + +SRes SbEncInStream_Init(CSbEncInStream *p) +{ + return SbEnc_Init(&p->enc); +} + +void SbEncInStream_Free(CSbEncInStream *p) +{ + SbEnc_Free(&p->enc); +} + #endif + typedef struct { - /* CMixCoderSeqInStream inStream; */ CLzma2EncHandle lzma2; #ifdef USE_SUBBLOCK CSbEncInStream sb; #endif + CSeqInFilter filter; ISzAlloc *alloc; ISzAlloc *bigAlloc; } CLzma2WithFilters; @@ -361,9 +352,9 @@ static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, IS p->bigAlloc = bigAlloc; p->lzma2 = NULL; #ifdef USE_SUBBLOCK - p->sb.p.Read = SbEncInStream_Read; - SubblockEnc_Construct(&p->sb.sb, p->alloc); + SbEncInStream_Construct(&p->sb, alloc); #endif + SeqInFilter_Construct(&p->filter); } static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) @@ -376,8 +367,9 @@ static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) static void Lzma2WithFilters_Free(CLzma2WithFilters *p) { + SeqInFilter_Free(&p->filter); #ifdef USE_SUBBLOCK - SubblockEnc_Free(&p->sb.sb); + SbEncInStream_Free(&p->sb); #endif if (p->lzma2) { @@ -386,17 +378,28 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p) } } -static SRes Xz_Compress(CXzStream *xz, - CLzma2WithFilters *lzmaf, - ISeqOutStream *outStream, - ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, - Bool useSubblock, - ICompressProgress *progress) +void XzProps_Init(CXzProps *p) { - xz->flags = XZ_CHECK_CRC32; + p->lzma2Props = 0; + p->filterProps = 0; + p->checkId = XZ_CHECK_CRC32; +} - RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props)); +void XzFilterProps_Init(CXzFilterProps *p) +{ + p->id = 0; + p->delta = 0; + p->ip= 0; + p->ipDefined = False; +} + +static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, + ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + xz->flags = (Byte)props->checkId; + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props)); RINOK(Xz_WriteHeader(xz->flags, outStream)); { @@ -404,15 +407,27 @@ static SRes Xz_Compress(CXzStream *xz, CSeqSizeOutStream seqSizeOutStream; CXzBlock block; int filterIndex = 0; + CXzFilter *filter = NULL; + const CXzFilterProps *fp = props->filterProps; XzBlock_ClearFlags(&block); - XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0)); + XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); - if (useSubblock) + if (fp) { - CXzFilter *f = &block.filters[filterIndex++]; - f->id = XZ_ID_Subblock; - f->propsSize = 0; + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + SetUi32(filter->props, fp->ip); + filter->propsSize = 4; + } } { @@ -432,20 +447,30 @@ static SRes Xz_Compress(CXzStream *xz, checkInStream.realStream = inStream; SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags)); - #ifdef USE_SUBBLOCK - if (useSubblock) + if (fp) { - lzmaf->sb.sb.inStream = &checkInStream.p; - SubblockEnc_Init(&lzmaf->sb.sb); + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.p; + RINOK(SbEncInStream_Init(&lzmaf->sb)); + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.p; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter)); + } } - #endif - + { UInt64 packPos = seqSizeOutStream.processed; SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, + fp ? #ifdef USE_SUBBLOCK - useSubblock ? &lzmaf->sb.p: + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: #endif + &lzmaf->filter.p: &checkInStream.p, progress); RINOK(res); @@ -467,8 +492,7 @@ static SRes Xz_Compress(CXzStream *xz, } SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, Bool useSubblock, - ICompressProgress *progress) + const CXzProps *props, ICompressProgress *progress) { SRes res; CXzStream xz; @@ -477,8 +501,7 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc); res = Lzma2WithFilters_Create(&lzmaf); if (res == SZ_OK) - res = Xz_Compress(&xz, &lzmaf, outStream, inStream, - lzma2Props, useSubblock, progress); + res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress); Lzma2WithFilters_Free(&lzmaf); Xz_Free(&xz, &g_Alloc); return res; @@ -1,5 +1,5 @@ /* XzEnc.h -- Xz Encode -2009-04-15 : Igor Pavlov : Public domain */ +2011-02-07 : Igor Pavlov : Public domain */ #ifndef __XZ_ENC_H #define __XZ_ENC_H @@ -8,18 +8,32 @@ #include "Xz.h" -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + +typedef struct +{ + const CLzma2EncProps *lzma2Props; + const CXzFilterProps *filterProps; + unsigned checkId; +} CXzProps; + +void XzProps_Init(CXzProps *p); SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, - const CLzma2EncProps *lzma2Props, Bool useSubblock, - ICompressProgress *progress); + const CXzProps *props, ICompressProgress *progress); SRes Xz_EncodeEmpty(ISeqOutStream *outStream); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif @@ -1,5 +1,5 @@ /* XzIn.c - Xz input -2009-06-19 : Igor Pavlov : Public domain */ +2011-02-01 : Igor Pavlov : Public domain */ #include <string.h> @@ -152,39 +152,38 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) { - Int64 i = 0; + UInt32 total = 0; *startOffset += XZ_STREAM_FOOTER_SIZE; for (;;) { - int j; - size_t processedSize; + size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte tempBuf[TEMP_BUF_SIZE]; - if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16)) + if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; - processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; - i += processedSize; - *startOffset = -(Int64)processedSize; + i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; + total += (UInt32)i; + *startOffset = -(Int64)i; RINOK(SeekFromCur(stream, startOffset)); - RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE)); - for (j = (int)processedSize; j >= 0; j--) - if (tempBuf[j -1] != 0) + RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE)); + for (; i != 0; i--) + if (tempBuf[i - 1] != 0) break; - if (j != 0) + if (i != 0) { - if ((j & 3) != 0) - return SZ_ERROR_NO_ARCHIVE; - *startOffset += j; - if (*startOffset < XZ_STREAM_FOOTER_SIZE) - return SZ_ERROR_NO_ARCHIVE; - *startOffset -= XZ_STREAM_FOOTER_SIZE; - RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); - RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); - if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; + *startOffset += i; break; } } + if (*startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset -= XZ_STREAM_FOOTER_SIZE; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; } p->flags = (CXzStreamFlags)GetBe16(buf + 8); diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index 55bbc68e..5cde97c3 100755 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -3,19 +3,18 @@ #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H -#include "../../../Common/MyString.h" - -#include "../../../Windows/PropVariant.h" - +#include "../../Common/MethodId.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { -struct CMethodFull: public CMethod +struct CMethodFull: public CProps { + CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 87996bc0..614f9913 100755 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -49,6 +49,15 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn folder.PackStreams.Add(bindInfo.InStreams[i]); } +static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) +{ + CMyComPtr<ICompressSetCoderProperties> setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + if (setCoderProperties) + return props.SetCoderProps(setCoderProperties, dataSizeReduce); + return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; +} + HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) @@ -86,8 +95,7 @@ HRESULT CEncoder::CreateMixerCoder( } #endif - - RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); + RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 4ab7afa8..93d4f51e 100755 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -24,25 +24,20 @@ using namespace NWindows; -extern UString ConvertMethodIdToString(UInt64 id); - namespace NArchive { namespace N7z { CHandler::CHandler() { - _crcSize = 4; - #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY + _crcSize = 4; #ifdef __7Z_SET_PROPERTIES _numThreads = NSystem::GetNumberOfProcessors(); #endif - #else - Init(); #endif } @@ -70,7 +65,7 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, #else -STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, @@ -80,6 +75,25 @@ STATPROPSTG kArcProps[] = { NULL, kpidOffset, VT_UI8} }; +static inline wchar_t GetHex(Byte value) +{ + return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static UString ConvertMethodIdToString(UInt64 id) +{ + wchar_t s[32]; + int len = 32; + s[--len] = 0; + do + { + s[--len] = GetHex((Byte)id & 0xF); id >>= 4; + s[--len] = GetHex((Byte)id & 0xF); id >>= 4; + } + while (id != 0); + return s + len; +} + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -172,22 +186,18 @@ static UString GetStringForSizeValue(UInt32 value) return result; } -static const UInt64 k_Copy = 0x0; -static const UInt64 k_Delta = 3; -static const UInt64 k_LZMA2 = 0x21; -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_PPMD = 0x030401; - -static wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); -} static inline void AddHexToString(UString &res, Byte value) { res += GetHex((Byte)(value >> 4)); res += GetHex((Byte)(value & 0xF)); } +static void AddProp32(UString &s, const wchar_t *name, UInt32 v) +{ + s += name; + s += ConvertUInt32ToString(v); +} + #endif bool CHandler::IsEncrypted(UInt32 index2) const @@ -283,6 +293,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va { UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1); propsString = GetStringForSizeValue(dicSize); + UInt32 d = coder.Props[0]; + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) AddProp32(propsString, L":lc", lc); + if (lp != 0) AddProp32(propsString, L":lp", lp); + if (pb != 2) AddProp32(propsString, L":pb", pb); } else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1) { diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 56062d46..247b55f7 100755 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -18,6 +18,16 @@ namespace NArchive { namespace N7z { +const UInt32 k_Copy = 0x0; +const UInt32 k_Delta = 3; +const UInt32 k_LZMA2 = 0x21; +const UInt32 k_LZMA = 0x030101; +const UInt32 k_PPMD = 0x030401; +const UInt32 k_BCJ = 0x03030103; +const UInt32 k_BCJ2 = 0x0303011B; +const UInt32 k_Deflate = 0x040108; +const UInt32 k_BZip2 = 0x040202; + #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY @@ -31,9 +41,52 @@ namespace N7z { #endif +#ifndef EXTRACT_ONLY + +class COutHandler: public CMultiMethodProps +{ + HRESULT SetSolidFromString(const UString &s); + HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value); +public: + bool _removeSfxBlock; + + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + + bool WriteCTime; + bool WriteATime; + bool WriteMTime; + + bool _volumeMode; + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void InitProps(); + + COutHandler() { InitProps(); } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + +#endif + class CHandler: #ifndef EXTRACT_ONLY - public NArchive::COutHandler, + public COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES @@ -90,16 +143,16 @@ private: CRecordVector<CBind> _binds; - HRESULT SetCompressionMethod(CCompressionMethodMode &method, + HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); + HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); + void AddDefaultMethod(); + HRESULT SetMainMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ); - HRESULT SetCompressionMethod( - CCompressionMethodMode &method, - CCompressionMethodMode &headerMethod); #endif diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index a8ccab6d..dd73ee84 100755 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -2,13 +2,9 @@ #include "StdAfx.h" -#include "../../../Windows/PropVariant.h" - #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" -#include "../../ICoder.h" - #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" @@ -21,24 +17,19 @@ using namespace NWindows; namespace NArchive { namespace N7z { -static const wchar_t *kLZMAMethodName = L"LZMA"; -static const wchar_t *kCopyMethod = L"Copy"; -static const wchar_t *kDefaultMethodName = kLZMAMethodName; +static const wchar_t *k_LZMA_Name = L"LZMA"; +static const wchar_t *kDefaultMethodName = k_LZMA_Name; +static const wchar_t *k_Copy_Name = L"Copy"; -static const UInt32 kLzmaAlgorithmX5 = 1; -static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; -static const UInt32 kDictionaryForHeaders = +static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; +static const UInt32 k_NumFastBytes_ForHeaders = 273; +static const UInt32 k_Level_ForHeaders = 5; +static const UInt32 k_Dictionary_ForHeaders = #ifdef UNDER_CE - 1 << 18 + 1 << 18; #else - 1 << 20 + 1 << 20; #endif -; -static const UInt32 kNumFastBytesForHeaders = 273; -static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; - -static inline bool IsCopyMethod(const UString &methodName) - { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { @@ -46,123 +37,105 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT CHandler::SetCompressionMethod( - CCompressionMethodMode &methodMode, - CCompressionMethodMode &headerMethod) +HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) { - HRESULT res = SetCompressionMethod(methodMode, _methods - #ifndef _7ZIP_ST - , _numThreads - #endif - ); - RINOK(res); - methodMode.Binds = _binds; + if (!FindMethod( + EXTERNAL_CODECS_VARS + m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams)) + return E_INVALIDARG; + (CProps &)dest = (CProps &)m; + return S_OK; +} - if (_compressHeaders) - { - // headerMethod.Methods.Add(methodMode.Methods.Back()); +HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) +{ + if (!_compressHeaders) + return S_OK; + COneMethodInfo m; + m.MethodName = k_LZMA_Name; + m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); + m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders); + m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); + m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); + m.AddNumThreadsProp(1); + + CMethodFull methodFull; + RINOK(PropsMethod_To_FullMethod(methodFull, m)); + headerMethod.Methods.Add(methodFull); + return S_OK; +} - CObjectVector<COneMethodInfo> headerMethodInfoVector; - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = kLZMAMethodName; - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kLzmaMatchFinderForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = (UInt32)kNumFastBytesForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = (UInt32)kDictionaryForHeaders; - oneMethodInfo.Props.Add(prop); - } - headerMethodInfoVector.Add(oneMethodInfo); - HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector - #ifndef _7ZIP_ST - , 1 - #endif - ); - RINOK(res); +void CHandler::AddDefaultMethod() +{ + for (int i = 0; i < _methods.Size(); i++) + { + UString &methodName = _methods[0].MethodName; + if (methodName.IsEmpty()) + methodName = kDefaultMethodName; + } + if (_methods.IsEmpty()) + { + COneMethodInfo m; + m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); + _methods.Add(m); } - return S_OK; } -HRESULT CHandler::SetCompressionMethod( +HRESULT CHandler::SetMainMethod( CCompressionMethodMode &methodMode, - CObjectVector<COneMethodInfo> &methodsInfo + CObjectVector<COneMethodInfo> &methods #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { - UInt32 level = _level; - - if (methodsInfo.IsEmpty()) - { - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); - methodsInfo.Add(oneMethodInfo); - } + AddDefaultMethod(); + + const UInt64 kSolidBytes_Min = (1 << 24); + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; bool needSolid = false; - for(int i = 0; i < methodsInfo.Size(); i++) + for (int i = 0; i < methods.Size(); i++) { - COneMethodInfo &oneMethodInfo = methodsInfo[i]; - SetCompressionMethod2(oneMethodInfo + COneMethodInfo &oneMethodInfo = methods[i]; + SetGlobalLevelAndThreads(oneMethodInfo #ifndef _7ZIP_ST , numThreads #endif ); - if (!IsCopyMethod(oneMethodInfo.MethodName)) - needSolid = true; - CMethodFull methodFull; - - if (!FindMethod( - EXTERNAL_CODECS_VARS - oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) - return E_INVALIDARG; - methodFull.Props = oneMethodInfo.Props; + RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); methodMode.Methods.Add(methodFull); - if (!_numSolidBytesDefined) + if (methodFull.Id != k_Copy) + needSolid = true; + + if (_numSolidBytesDefined) + continue; + + UInt32 dicSize; + switch (methodFull.Id) { - for (int j = 0; j < methodFull.Props.Size(); j++) - { - const CProp &prop = methodFull.Props[j]; - if ((prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) - { - _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; - const UInt64 kMinSize = (1 << 24); - if (_numSolidBytes < kMinSize) - _numSolidBytes = kMinSize; - _numSolidBytesDefined = true; - break; - } - } + case k_LZMA: + case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; + case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; + case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; + default: continue; } - } - - if (!needSolid && !_numSolidBytesDefined) - { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; + if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; _numSolidBytesDefined = true; - _numSolidBytes = 0; } + + if (!_numSolidBytesDefined) + if (needSolid) + _numSolidBytes = kSolidBytes_Max; + else + _numSolidBytes = 0; + _numSolidBytesDefined = true; return S_OK; } @@ -326,7 +299,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } CCompressionMethodMode methodMode, headerMethod; - RINOK(SetCompressionMethod(methodMode, headerMethod)); + + HRESULT res = SetMainMethod(methodMode, _methods + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + RINOK(res); + methodMode.Binds = _binds; + + RINOK(SetHeaderMethod(headerMethod)); #ifndef _7ZIP_ST methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; @@ -373,8 +355,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; - options.UseFilters = _level != 0 && _autoFilter; - options.MaxFilter = _level >= 8; + int level = GetLevel(); + options.UseFilters = level != 0 && _autoFilter; + options.MaxFilter = level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; @@ -393,7 +376,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr<ICryptoGetTextPassword> getPassword; updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); - HRESULT res = Update( + res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, @@ -437,25 +420,138 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream return S_OK; } -static HRESULT GetBindInfo(UString &srcString, CBind &bind) +void COutHandler::InitProps() { - RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); - if (srcString[0] != ':') - return E_INVALIDARG; - srcString.Delete(0); - RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); - if (!srcString.IsEmpty()) - return E_INVALIDARG; + CMultiMethodProps::Init(); + + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + + WriteCTime = false; + WriteATime = false; + WriteMTime = true; + + _volumeMode = false; + InitSolid(); +} + +HRESULT COutHandler::SetSolidFromString(const UString &s) +{ + UString s2 = s; + s2.MakeUpper(); + for (int i = 0; i < s2.Length();) + { + const wchar_t *start = ((const wchar_t *)s2) + i; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (start == end) + { + if (s2[i++] != 'E') + return E_INVALIDARG; + _solidExtension = true; + continue; + } + i += (int)(end - start); + if (i == s2.Length()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + if (c == 'F') + { + if (v < 1) + v = 1; + _numSolidFiles = v; + } + else + { + unsigned numBits; + switch (c) + { + case 'B': numBits = 0; break; + case 'K': numBits = 10; break; + case 'M': numBits = 20; break; + case 'G': numBits = 30; break; + default: return E_INVALIDARG; + } + _numSolidBytes = (v << numBits); + _numSolidBytesDefined = true; + } + } + return S_OK; +} + +HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) +{ + bool isSolid; + switch (value.vt) + { + case VT_EMPTY: isSolid = true; break; + case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; + case VT_BSTR: + if (StringToBool(value.bstrVal, isSolid)) + break; + return SetSolidFromString(value.bstrVal); + default: return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; return S_OK; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == L'S') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidFromPROPVARIANT(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidFromString(name); + } + + UInt32 number; + int index = ParseStringToUInt32(name, number); + UString realName = name.Mid(index); + if (index == 0) + { + if (name.CompareNoCase(L"RSFX") == 0) return PROPVARIANT_to_bool(value, _removeSfxBlock); + if (name.CompareNoCase(L"HC") == 0) return PROPVARIANT_to_bool(value, _compressHeaders); + if (name.CompareNoCase(L"HCF") == 0) + { + bool compressHeadersFull = true; + RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)); + return compressHeadersFull ? S_OK: E_INVALIDARG; + } + if (name.CompareNoCase(L"HE") == 0) + { + RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)); + _encryptHeadersSpecified = true; + return S_OK; + } + if (name.CompareNoCase(L"TC") == 0) return PROPVARIANT_to_bool(value, WriteCTime); + if (name.CompareNoCase(L"TA") == 0) return PROPVARIANT_to_bool(value, WriteATime); + if (name.CompareNoCase(L"TM") == 0) return PROPVARIANT_to_bool(value, WriteMTime); + if (name.CompareNoCase(L"V") == 0) return PROPVARIANT_to_bool(value, _volumeMode); + } + return CMultiMethodProps::SetProperty(name, value); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) { COM_TRY_BEGIN _binds.Clear(); - BeforeSetProperty(); + InitProps(); - for (int i = 0; i < numProperties; i++) + for (int i = 0; i < numProps; i++) { UString name = names[i]; name.MakeUpper(); @@ -466,9 +562,17 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v if (name[0] == 'B') { + if (value.vt != VT_EMPTY) + return E_INVALIDARG; name.Delete(0); CBind bind; - RINOK(GetBindInfo(name, bind)); + RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream)); + if (name[0] != ':') + return E_INVALIDARG; + name.Delete(0); + RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream)); + if (!name.IsEmpty()) + return E_INVALIDARG; _binds.Add(bind); continue; } @@ -476,6 +580,47 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v RINOK(SetProperty(name, value)); } + int numEmptyMethods = GetNumEmptyMethods(); + if (numEmptyMethods > 0) + { + int k; + for (k = 0; k < _binds.Size(); k++) + { + const CBind &bind = _binds[k]; + if (bind.InCoder < (UInt32)numEmptyMethods || + bind.OutCoder < (UInt32)numEmptyMethods) + return E_INVALIDARG; + } + for (k = 0; k < _binds.Size(); k++) + { + CBind &bind = _binds[k]; + bind.InCoder -= (UInt32)numEmptyMethods; + bind.OutCoder -= (UInt32)numEmptyMethods; + } + _methods.Delete(0, numEmptyMethods); + } + + AddDefaultMethod(); + + if (!_filterMethod.MethodName.IsEmpty()) + { + for (int k = 0; k < _binds.Size(); k++) + { + CBind &bind = _binds[k]; + bind.InCoder++; + bind.OutCoder++; + } + _methods.Insert(0, _filterMethod); + } + + for (int k = 0; k < _binds.Size(); k++) + { + const CBind &bind = _binds[k]; + if (bind.InCoder >= (UInt32)_methods.Size() || + bind.OutCoder >= (UInt32)_methods.Size()) + return E_INVALIDARG; + } + return S_OK; COM_TRY_END } diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index 0feb81d2..fd751a74 100755 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -317,7 +317,6 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; - UInt32 numPrevBytes = kHeaderSize; memcpy(buffer, _header, kHeaderSize); UInt64 curTestPos = _arhiveBeginStreamPosition; for (;;) @@ -325,21 +324,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; - do - { - UInt32 numReadBytes = kBufferSize - numPrevBytes; - UInt32 processedSize; - RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); - numPrevBytes += processedSize; - if (processedSize == 0) - return S_FALSE; - } - while (numPrevBytes <= kHeaderSize); - UInt32 numTests = numPrevBytes - kHeaderSize; - for (UInt32 pos = 0; pos < numTests; pos++) + UInt32 processedSize; + RINOK(stream->Read(buffer + kHeaderSize, kBufferSize - kHeaderSize, &processedSize)); + if (processedSize == 0) + return S_FALSE; + for (UInt32 pos = 1; pos <= processedSize; pos++) { - for (; buffer[pos] != '7' && pos < numTests; pos++); - if (pos == numTests) + for (; buffer[pos] != '7' && pos <= processedSize; pos++); + if (pos > processedSize) break; if (TestSignature(buffer + pos)) { @@ -349,9 +341,8 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } - curTestPos += numTests; - numPrevBytes -= numTests; - memmove(buffer, buffer + numTests, numPrevBytes); + curTestPos += processedSize; + memmove(buffer, buffer + processedSize, kHeaderSize); } return S_FALSE; } @@ -362,6 +353,8 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) + RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) + RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; @@ -1194,12 +1187,14 @@ HRESULT CInArchive::ReadDatabase2( if (nextHeaderSize == 0) return S_OK; - if (nextHeaderSize > (UInt64)0xFFFFFFFF) + if (nextHeaderSize > (UInt64)(UInt32)0xFFFFFFFF) return S_FALSE; if ((Int64)nextHeaderOffset < 0) return S_FALSE; + if (db.ArchiveInfo.StartPositionAfterHeader + nextHeaderOffset > _fileEndPosition) + return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 971f27b2..4305a8c5 100755 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -133,6 +133,7 @@ class CInArchive CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; + UInt64 _fileEndPosition; Byte _header[kHeaderSize]; diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index ee7f55c0..e63b09d2 100755 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -24,15 +24,6 @@ namespace NArchive { namespace N7z { -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - -static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; -static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; -static const UInt32 kAlgorithmForBCJ2_LZMA = 1; -static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; - #ifdef MY_CPU_X86_OR_AMD64 #define USE_86_FILTER #endif @@ -339,90 +330,74 @@ static bool IsExeExt(const UString &ext) return false; } -#ifdef USE_86_FILTER -static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) +static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m) { - methodResult.Id = methodID; - methodResult.NumInStreams = numInStreams; - methodResult.NumOutStreams = 1; + m.Id = methodID; + m.NumInStreams = numInStreams; + m.NumOutStreams = 1; +} + +static void AddBcj2Methods(CCompressionMethodMode &mode) +{ + CMethodFull m; + GetMethodFull(k_LZMA, 1, m); + + m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20); + m.AddProp32(NCoderPropID::kNumFastBytes, 128); + m.AddProp32(NCoderPropID::kNumThreads, 1); + m.AddProp32(NCoderPropID::kLitPosBits, 2); + m.AddProp32(NCoderPropID::kLitContextBits, 0); + // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2"); + + mode.Methods.Add(m); + mode.Methods.Add(m); + + CBind bind; + bind.OutCoder = 0; + bind.InStream = 0; + bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind); + bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind); + bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind); } -static void MakeExeMethod(const CCompressionMethodMode &method, - bool bcj2Filter, CCompressionMethodMode &exeMethod) +static void MakeExeMethod(CCompressionMethodMode &mode, + bool useFilters, bool addFilter, bool bcj2Filter) { - exeMethod = method; + if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2) + return; + if (mode.Methods.Size() == 2) + { + if (mode.Methods[0].Id == k_BCJ2) + AddBcj2Methods(mode); + return; + } + if (!addFilter) + return; + bcj2Filter = bcj2Filter; + #ifdef USE_86_FILTER if (bcj2Filter) { - CMethodFull methodFull; - GetMethodFull(k_BCJ2, 4, methodFull); - exeMethod.Methods.Insert(0, methodFull); - GetMethodFull(k_LZMA, 1, methodFull); - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kMatchFinderForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = kDictionaryForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = kNumFastBytesForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumThreads; - prop.Value = (UInt32)1; - methodFull.Props.Add(prop); - } - - exeMethod.Methods.Add(methodFull); - exeMethod.Methods.Add(methodFull); - CBind bind; - - bind.OutCoder = 0; - bind.InStream = 0; - - bind.InCoder = 1; - bind.OutStream = 0; - exeMethod.Binds.Add(bind); - - bind.InCoder = 2; - bind.OutStream = 1; - exeMethod.Binds.Add(bind); - - bind.InCoder = 3; - bind.OutStream = 2; - exeMethod.Binds.Add(bind); + CMethodFull m; + GetMethodFull(k_BCJ2, 4, m); + mode.Methods.Insert(0, m); + AddBcj2Methods(mode); } else { - CMethodFull methodFull; - GetMethodFull(k_BCJ, 1, methodFull); - exeMethod.Methods.Insert(0, methodFull); + CMethodFull m; + GetMethodFull(k_BCJ, 1, m); + mode.Methods.Insert(0, m); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; - exeMethod.Binds.Add(bind); + mode.Binds.Add(bind); } + #endif } -#endif static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) @@ -601,6 +576,7 @@ public: Fos = FosSpec; Result = E_FAIL; } + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } virtual void Execute(); }; @@ -669,9 +645,7 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) static const int kNumGroupsMax = 4; -#ifdef USE_86_FILTER static bool Is86Group(int group) { return (group & 1) != 0; } -#endif static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } static int GetGroupIndex(bool encrypted, int bcjFiltered) { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } @@ -789,16 +763,15 @@ HRESULT Update( if (inSizeForReduce2 > inSizeForReduce) inSizeForReduce = inSizeForReduce2; - const UInt32 kMinReduceSize = (1 << 16); - if (inSizeForReduce < kMinReduceSize) - inSizeForReduce = kMinReduceSize; - RINOK(updateCallback->SetTotal(complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CThreadDecoder threadDecoder; if (!folderRefs.IsEmpty()) { @@ -870,13 +843,8 @@ HRESULT Update( { const CSolidGroup &group = groups[groupIndex]; - CCompressionMethodMode method; - #ifdef USE_86_FILTER - if (Is86Group(groupIndex)) - MakeExeMethod(*options.Method, options.MaxFilter, method); - else - #endif - method = *options.Method; + CCompressionMethodMode method = *options.Method; + MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter); if (IsEncryptedGroup(groupIndex)) { @@ -923,11 +891,6 @@ HRESULT Update( } else { - CStreamBinder sb; - RINOK(sb.CreateEvents()); - CMyComPtr<ISequentialOutStream> sbOutStream; - CMyComPtr<ISequentialInStream> sbInStream; - sb.CreateStreams(&sbInStream, &sbOutStream); CBoolVector extractStatuses; CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; @@ -946,24 +909,31 @@ HRESULT Update( extractStatuses.Add(needExtract); } - RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); - sbOutStream.Release(); - - threadDecoder.InStream = inStream; - threadDecoder.Folder = &db->Folders[folderIndex]; - threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); - threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; - - threadDecoder.Start(); - int startPackIndex = newDatabase.PackSizes.Size(); CFolder newFolder; - RINOK(encoder.Encode( - EXTERNAL_CODECS_LOC_VARS - sbInStream, NULL, &inSizeForReduce, newFolder, - archive.SeqStream, newDatabase.PackSizes, progress)); - - threadDecoder.WaitFinish(); + { + CMyComPtr<ISequentialInStream> sbInStream; + { + CMyComPtr<ISequentialOutStream> sbOutStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + sb.ReInit(); + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + } + + threadDecoder.InStream = inStream; + threadDecoder.Folder = &db->Folders[folderIndex]; + threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; + + threadDecoder.Start(); + + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + sbInStream, NULL, &inSizeForReduce, newFolder, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitExecuteFinish(); + } RINOK(threadDecoder.Result); @@ -1134,6 +1104,8 @@ HRESULT Update( if (folderRefIndex != folderRefs.Size()) return E_FAIL; + RINOK(lps->SetCur()); + /* folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); @@ -1169,7 +1141,7 @@ HRESULT Update( newDatabase.AddFile(file, file2); } } - + newDatabase.ReserveDown(); return S_OK; } diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp index 98cbcc18..49ae8c79 100755 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -4,13 +4,6 @@ #include "Common/ComTry.h" -#include "Windows/PropVariant.h" - -#ifndef _7ZIP_ST -#include "../../Windows/System.h" -#endif - -#include "../Common/CreateCoder.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" @@ -20,21 +13,13 @@ #include "../Compress/CopyCoder.h" #include "Common/DummyOutStream.h" -#include "Common/ParseProperties.h" +#include "Common/HandlerOut.h" using namespace NWindows; namespace NArchive { namespace NBz2 { -static const UInt32 kNumPassesX1 = 1; -static const UInt32 kNumPassesX7 = 2; -static const UInt32 kNumPassesX9 = 7; - -static const UInt32 kDicSizeX1 = 100000; -static const UInt32 kDicSizeX3 = 500000; -static const UInt32 kDicSizeX5 = 900000; - class CHandler: public IInArchive, public IArchiveOpenSeq, @@ -48,22 +33,7 @@ class CHandler: UInt64 _startPosition; bool _packSizeDefined; - UInt32 _level; - UInt32 _dicSize; - UInt32 _numPasses; - #ifndef _7ZIP_ST - UInt32 _numThreads; - #endif - - void InitMethodProperties() - { - _level = 5; - _dicSize = - _numPasses = 0xFFFFFFFF; - #ifndef _7ZIP_ST - _numThreads = NWindows::NSystem::GetNumberOfProcessors();; - #endif - } + CSingleMethodProps _props; public: MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) @@ -73,10 +43,10 @@ public: STDMETHOD(OpenSeq)(ISequentialInStream *stream); STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); - CHandler() { InitMethodProperties(); } + CHandler() { } }; -STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPackSize, VT_UI8} }; @@ -87,7 +57,7 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; } @@ -104,7 +74,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; } @@ -188,7 +158,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, decoderSpec->SetInStream(_seqStream); #ifndef _7ZIP_ST - RINOK(decoderSpec->SetNumberOfThreads(_numThreads)); + RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads)); #endif CDummyOutStream *outStreamSpec = new CDummyOutStream; @@ -246,50 +216,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, static HRESULT UpdateArchive( UInt64 unpackSize, ISequentialOutStream *outStream, - int indexInClient, - UInt32 dictionary, - UInt32 numPasses, - #ifndef _7ZIP_ST - UInt32 numThreads, - #endif + const CProps &props, IArchiveUpdateCallback *updateCallback) { RINOK(updateCallback->SetTotal(unpackSize)); - UInt64 complexity = 0; - RINOK(updateCallback->SetCompleted(&complexity)); - CMyComPtr<ISequentialInStream> fileInStream; - - RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); - + RINOK(updateCallback->GetStream(0, &fileInStream)); CLocalProgress *localProgressSpec = new CLocalProgress; CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; localProgressSpec->Init(updateCallback, true); - NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; - { - NWindows::NCOM::CPropVariant properties[] = - { - dictionary, - numPasses - #ifndef _7ZIP_ST - , numThreads - #endif - }; - PROPID propIDs[] = - { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumPasses - #ifndef _7ZIP_ST - , NCoderPropID::kNumThreads - #endif - }; - RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); - } - + RINOK(props.SetCoderProps(encoderSpec, NULL)); RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } @@ -336,25 +275,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; size = prop.uhVal.QuadPart; } - - UInt32 dicSize = _dicSize; - if (dicSize == 0xFFFFFFFF) - dicSize = (_level >= 5 ? kDicSizeX5 : - (_level >= 3 ? kDicSizeX3 : - kDicSizeX1)); - - UInt32 numPasses = _numPasses; - if (numPasses == 0xFFFFFFFF) - numPasses = (_level >= 9 ? kNumPassesX9 : - (_level >= 7 ? kNumPassesX7 : - kNumPassesX1)); - - return UpdateArchive( - size, outStream, 0, dicSize, numPasses, - #ifndef _7ZIP_ST - _numThreads, - #endif - updateCallback); + return UpdateArchive(size, outStream, _props, updateCallback); } if (indexInArchive != 0) return E_INVALIDARG; @@ -365,47 +286,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) { - InitMethodProperties(); - #ifndef _7ZIP_ST - const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); - _numThreads = numProcessors; - #endif - - for (int i = 0; i < numProps; i++) - { - UString name = names[i]; - name.MakeUpper(); - if (name.IsEmpty()) - return E_INVALIDARG; - const PROPVARIANT &prop = values[i]; - if (name[0] == L'X') - { - UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - _level = level; - } - else if (name[0] == L'D') - { - UInt32 dicSize = kDicSizeX5; - RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); - _dicSize = dicSize; - } - else if (name.Left(4) == L"PASS") - { - UInt32 num = kNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - _numPasses = num; - } - else if (name.Left(2) == L"MT") - { - #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); - #endif - } - else - return E_INVALIDARG; - } - return S_OK; + return _props.SetProperties(names, values, numProps); } static IInArchive *CreateArc() { return new CHandler; } diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 20f670d3..fd707fe5 100755 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -4,9 +4,7 @@ #include "../../../../C/Alloc.h" -#include "Common/Buffer.h" #include "Common/ComTry.h" -#include "Common/Defs.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Common/UTFConvert.h" @@ -654,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, bool allFilesMode = (numItems == (UInt32)-1); if (allFilesMode) numItems = m_Database.Items.Size(); - if(numItems == 0) + if (numItems == 0) return S_OK; bool testMode = (testModeSpec != 0); UInt64 totalUnPacked = 0; @@ -780,12 +778,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, curUnpack, extractCallback, testMode); cabBlockInStreamSpec->MsZip = false; + HRESULT res = S_OK; switch(folder.GetCompressionMethod()) { case NHeader::NCompressionMethodMajor::kNone: break; case NHeader::NCompressionMethodMajor::kMSZip: - if(deflateDecoderSpec == NULL) + if (!deflateDecoder) { deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; deflateDecoder = deflateDecoderSpec; @@ -793,33 +792,35 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, cabBlockInStreamSpec->MsZip = true; break; case NHeader::NCompressionMethodMajor::kLZX: - if(lzxDecoderSpec == NULL) + if (!lzxDecoder) { lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoder = lzxDecoderSpec; } - RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor)); + res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor); break; case NHeader::NCompressionMethodMajor::kQuantum: - if(quantumDecoderSpec == NULL) + if (!quantumDecoder) { quantumDecoderSpec = new NCompress::NQuantum::CDecoder; quantumDecoder = quantumDecoderSpec; } - quantumDecoderSpec->SetParams(folder.CompressionTypeMinor); + res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor); break; default: - { - RINOK(cabFolderOutStream->Unsupported()); - totalUnPacked += curUnpack; - continue; - } + res = E_INVALIDARG; + break; } - cabBlockInStreamSpec->InitForNewFolder(); - - HRESULT res = S_OK; + if (res == E_INVALIDARG) + { + RINOK(cabFolderOutStream->Unsupported()); + totalUnPacked += curUnpack; + continue; + } + RINOK(res); + cabBlockInStreamSpec->InitForNewFolder(); { int volIndex = mvItem.VolumeIndex; int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index 4719a484..4b1ac7a6 100755 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -39,7 +39,7 @@ struct CItem { if (Name.Length() == 0) return false; - return (Name[Name.Length() - 1] == '/'); + return (Name.Back() == '/'); } }; diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp index d76450bd..87686e85 100755 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -214,7 +214,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) - _coders[i].WaitFinish(); + _coders[i].WaitExecuteFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h index d1c7f4d0..81bb3f0b 100755 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -19,6 +19,7 @@ struct CCoder2: public CCoderInfo2, public CVirtThread CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); + ~CCoder2() { CVirtThread::WaitThreadFinish(); } void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp index a59ce5fc..a21ca0c0 100755 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -4,7 +4,7 @@ #include "CoderMixer2ST.h" -namespace NCoderMixer2 { +namespace NCoderMixer { CCoderMixer2ST::CCoderMixer2ST() {} @@ -42,7 +42,7 @@ HRESULT CCoderMixer2ST::GetInStream( { CMyComPtr<ISequentialInStream> seqInStream; int i; - for(i = 0; i < _bindInfo.InStreams.Size(); i++) + for (i = 0; i < _bindInfo.InStreams.Size(); i++) if (_bindInfo.InStreams[i] == streamIndex) { seqInStream = inStreams[i]; @@ -57,7 +57,7 @@ HRESULT CCoderMixer2ST::GetInStream( _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex, coderIndex, coderStreamIndex); - CCoderInfo &coder = _coders[coderIndex]; + CCoderInfo2 &coder = _coders[coderIndex]; if (!coder.Coder) return E_NOTIMPL; coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream); @@ -91,7 +91,7 @@ HRESULT CCoderMixer2ST::GetOutStream( { CMyComPtr<ISequentialOutStream> seqOutStream; int i; - for(i = 0; i < _bindInfo.OutStreams.Size(); i++) + for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == streamIndex) { seqOutStream = outStreams[i]; @@ -106,7 +106,7 @@ HRESULT CCoderMixer2ST::GetOutStream( _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex, coderIndex, coderStreamIndex); - CCoderInfo &coder = _coders[coderIndex]; + CCoderInfo2 &coder = _coders[coderIndex]; if (!coder.Coder) return E_NOTIMPL; coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream); @@ -169,7 +169,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, // _mainCoderIndex = 0; // _mainCoderIndex = _coders.Size() - 1; - CCoderInfo &mainCoder = _coders[_mainCoderIndex]; + CCoderInfo2 &mainCoder = _coders[_mainCoderIndex]; CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; @@ -198,7 +198,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, { if (i == _mainCoderIndex) continue; - CCoderInfo &coder = _coders[i]; + CCoderInfo2 &coder = _coders[i]; CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); if (setOutStreamSize) diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h index a4ea7e80..d35655ba 100755 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.h +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h @@ -7,7 +7,7 @@ #include "../../../Common/MyCom.h" #include "../../ICoder.h" -namespace NCoderMixer2 { +namespace NCoderMixer { // SetBindInfo() // for each coder @@ -26,11 +26,11 @@ namespace NCoderMixer2 { // Code // } -struct CSTCoderInfo: public CCoderInfo +struct CSTCoderInfo: public CCoderInfo2 { bool IsMain; CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain): - CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {} + CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {} }; class CCoderMixer2ST: @@ -84,5 +84,5 @@ public: }; } -#endif +#endif diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp index f43d1612..96ea76a3 100755 --- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp +++ b/CPP/7zip/Archive/Common/CoderMixerMT.cpp @@ -73,7 +73,7 @@ STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream, for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) - _coders[i].WaitFinish(); + _coders[i].WaitExecuteFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h index c70e1829..9491a965 100755 --- a/CPP/7zip/Archive/Common/CoderMixerMT.h +++ b/CPP/7zip/Archive/Common/CoderMixerMT.h @@ -18,6 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread virtual void Execute(); void Code(ICompressProgressInfo *progress); + ~CCoder() { CVirtThread::WaitThreadFinish(); } }; /* diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 70ad47aa..7e6f4602 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -2,16 +2,10 @@ #include "StdAfx.h" -#include "../../../Common/StringToInt.h" - -#include "../../../Windows/PropVariant.h" - #ifndef _7ZIP_ST #include "../../../Windows/System.h" #endif -#include "../../ICoder.h" - #include "../Common/ParseProperties.h" #include "HandlerOut.h" @@ -20,487 +14,40 @@ using namespace NWindows; namespace NArchive { -static const wchar_t *kCopyMethod = L"Copy"; -static const wchar_t *kLZMAMethodName = L"LZMA"; -static const wchar_t *kLZMA2MethodName = L"LZMA2"; -static const wchar_t *kBZip2MethodName = L"BZip2"; -static const wchar_t *kPpmdMethodName = L"PPMd"; -static const wchar_t *kDeflateMethodName = L"Deflate"; -static const wchar_t *kDeflate64MethodName = L"Deflate64"; - -static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; -static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; - -static const UInt32 kLzmaAlgoX1 = 0; -static const UInt32 kLzmaAlgoX5 = 1; - -static const UInt32 kLzmaDicSizeX1 = 1 << 16; -static const UInt32 kLzmaDicSizeX3 = 1 << 20; -static const UInt32 kLzmaDicSizeX5 = 1 << 24; -static const UInt32 kLzmaDicSizeX7 = 1 << 25; -static const UInt32 kLzmaDicSizeX9 = 1 << 26; - -static const UInt32 kLzmaFastBytesX1 = 32; -static const UInt32 kLzmaFastBytesX7 = 64; - -static const UInt32 kPpmdMemSizeX1 = (1 << 22); -static const UInt32 kPpmdMemSizeX5 = (1 << 24); -static const UInt32 kPpmdMemSizeX7 = (1 << 26); -static const UInt32 kPpmdMemSizeX9 = (192 << 20); - -static const UInt32 kPpmdOrderX1 = 4; -static const UInt32 kPpmdOrderX5 = 6; -static const UInt32 kPpmdOrderX7 = 16; -static const UInt32 kPpmdOrderX9 = 32; - -static const UInt32 kDeflateAlgoX1 = 0; -static const UInt32 kDeflateAlgoX5 = 1; - -static const UInt32 kDeflateFastBytesX1 = 32; -static const UInt32 kDeflateFastBytesX7 = 64; -static const UInt32 kDeflateFastBytesX9 = 128; - -static const UInt32 kDeflatePassesX1 = 1; -static const UInt32 kDeflatePassesX7 = 3; -static const UInt32 kDeflatePassesX9 = 10; - -static const UInt32 kBZip2NumPassesX1 = 1; -static const UInt32 kBZip2NumPassesX7 = 2; -static const UInt32 kBZip2NumPassesX9 = 7; - -static const UInt32 kBZip2DicSizeX1 = 100000; -static const UInt32 kBZip2DicSizeX3 = 500000; -static const UInt32 kBZip2DicSizeX5 = 900000; - -static const wchar_t *kDefaultMethodName = kLZMAMethodName; - -static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; -static const UInt32 kDictionaryForHeaders = 1 << 20; -static const UInt32 kNumFastBytesForHeaders = 273; -static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; - -static bool AreEqual(const UString &methodName, const wchar_t *s) - { return (methodName.CompareNoCase(s) == 0); } - -bool COneMethodInfo::IsLzma() const -{ - return - AreEqual(MethodName, kLZMAMethodName) || - AreEqual(MethodName, kLZMA2MethodName); -} - -static inline bool IsBZip2Method(const UString &methodName) - { return AreEqual(methodName, kBZip2MethodName); } - -static inline bool IsPpmdMethod(const UString &methodName) - { return AreEqual(methodName, kPpmdMethodName); } - -static inline bool IsDeflateMethod(const UString &methodName) -{ - return - AreEqual(methodName, kDeflateMethodName) || - AreEqual(methodName, kDeflate64MethodName); -} - -struct CNameToPropID -{ - PROPID PropID; - VARTYPE VarType; - const wchar_t *Name; -}; - -static CNameToPropID g_NameToPropID[] = -{ - { NCoderPropID::kBlockSize, VT_UI4, L"C" }, - { NCoderPropID::kDictionarySize, VT_UI4, L"D" }, - { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" }, - - { NCoderPropID::kOrder, VT_UI4, L"O" }, - { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, - { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, - { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, - { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, - - { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, - { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, - { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, - { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, - { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, - { NCoderPropID::kNumThreads, VT_UI4, L"mt" }, - { NCoderPropID::kDefaultProp, VT_UI4, L"" } -}; - -static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) -{ - if (varType == srcProp.vt) - { - destProp = srcProp; - return true; - } - if (varType == VT_UI1) - { - if (srcProp.vt == VT_UI4) - { - UInt32 value = srcProp.ulVal; - if (value > 0xFF) - return false; - destProp = (Byte)value; - return true; - } - } - else if (varType == VT_BOOL) - { - bool res; - if (SetBoolProperty(res, srcProp) != S_OK) - return false; - destProp = res; - return true; - } - return false; -} - -static int FindPropIdExact(const UString &name) -{ - for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) - if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) - return i; - return -1; -} - -static int FindPropIdStart(const UString &name) +static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value) { - for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) - { - UString t = g_NameToPropID[i].Name; - if (t.CompareNoCase(name.Left(t.Length())) == 0) - return i; - } - return -1; + if (m.FindProp(propID) < 0) + m.AddProp32(propID, value); } -static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value) -{ - for (int j = 0; j < m.Props.Size(); j++) - if (m.Props[j].Id == propID) - return; - CProp prop; - prop.Id = propID; - prop.Value = value; - m.Props.Add(prop); -} - -void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo +void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { UInt32 level = _level; - if (oneMethodInfo.MethodName.IsEmpty()) - oneMethodInfo.MethodName = kDefaultMethodName; - - if (oneMethodInfo.IsLzma()) - { - UInt32 dicSize = - (level >= 9 ? kLzmaDicSizeX9 : - (level >= 7 ? kLzmaDicSizeX7 : - (level >= 5 ? kLzmaDicSizeX5 : - (level >= 3 ? kLzmaDicSizeX3 : - kLzmaDicSizeX1)))); - - UInt32 algo = - (level >= 5 ? kLzmaAlgoX5 : - kLzmaAlgoX1); - - UInt32 fastBytes = - (level >= 7 ? kLzmaFastBytesX7 : - kLzmaFastBytesX1); - - const wchar_t *matchFinder = - (level >= 5 ? kLzmaMatchFinderX5 : - kLzmaMatchFinderX1); - - SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); - #ifndef _7ZIP_ST - SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); - #endif - } - else if (IsDeflateMethod(oneMethodInfo.MethodName)) - { - UInt32 fastBytes = - (level >= 9 ? kDeflateFastBytesX9 : - (level >= 7 ? kDeflateFastBytesX7 : - kDeflateFastBytesX1)); - - UInt32 numPasses = - (level >= 9 ? kDeflatePassesX9 : - (level >= 7 ? kDeflatePassesX7 : - kDeflatePassesX1)); - - UInt32 algo = - (level >= 5 ? kDeflateAlgoX5 : - kDeflateAlgoX1); - - SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); - SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - } - else if (IsBZip2Method(oneMethodInfo.MethodName)) - { - UInt32 numPasses = - (level >= 9 ? kBZip2NumPassesX9 : - (level >= 7 ? kBZip2NumPassesX7 : - kBZip2NumPassesX1)); - - UInt32 dicSize = - (level >= 5 ? kBZip2DicSizeX5 : - (level >= 3 ? kBZip2DicSizeX3 : - kBZip2DicSizeX1)); - - SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); - SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); - #ifndef _7ZIP_ST - SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); - #endif - } - else if (IsPpmdMethod(oneMethodInfo.MethodName)) - { - UInt32 useMemSize = - (level >= 9 ? kPpmdMemSizeX9 : - (level >= 7 ? kPpmdMemSizeX7 : - (level >= 5 ? kPpmdMemSizeX5 : - kPpmdMemSizeX1))); - - UInt32 order = - (level >= 9 ? kPpmdOrderX9 : - (level >= 7 ? kPpmdOrderX7 : - (level >= 5 ? kPpmdOrderX5 : - kPpmdOrderX1))); - - SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); - SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); - } -} - -static void SplitParams(const UString &srcString, UStringVector &subStrings) -{ - subStrings.Clear(); - UString name; - int len = srcString.Length(); - if (len == 0) - return; - for (int i = 0; i < len; i++) - { - wchar_t c = srcString[i]; - if (c == L':') - { - subStrings.Add(name); - name.Empty(); - } - else - name += c; - } - subStrings.Add(name); -} - -static void SplitParam(const UString ¶m, UString &name, UString &value) -{ - int eqPos = param.Find(L'='); - if (eqPos >= 0) - { - name = param.Left(eqPos); - value = param.Mid(eqPos + 1); - return; - } - for(int i = 0; i < param.Length(); i++) - { - wchar_t c = param[i]; - if (c >= L'0' && c <= L'9') - { - name = param.Left(i); - value = param.Mid(i); - return; - } - } - name = param; -} - -HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) -{ - CProp prop; - int index = FindPropIdExact(name); - if (index < 0) - return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - - if (prop.Id == NCoderPropID::kBlockSize || - prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) - { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(value, dicSize)); - prop.Value = dicSize; - } - else - { - NCOM::CPropVariant propValue; - - if (nameToPropID.VarType == VT_BSTR) - propValue = value; - else if (nameToPropID.VarType == VT_BOOL) - { - bool res; - if (!StringToBool(value, res)) - return E_INVALIDARG; - propValue = res; - } - else - { - UInt32 number; - if (ParseStringToUInt32(value, number) == value.Length()) - propValue = number; - else - propValue = value; - } - - if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) - return E_INVALIDARG; - } - oneMethodInfo.Props.Add(prop); - return S_OK; -} - -HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) -{ - UStringVector params; - SplitParams(srcString, params); - if (params.Size() > 0) - oneMethodInfo.MethodName = params[0]; - for (int i = 1; i < params.Size(); i++) - { - const UString ¶m = params[i]; - UString name, value; - SplitParam(param, name, value); - RINOK(SetParam(oneMethodInfo, name, value)); - } - return S_OK; -} - -HRESULT COutHandler::SetSolidSettings(const UString &s) -{ - UString s2 = s; - s2.MakeUpper(); - for (int i = 0; i < s2.Length();) - { - const wchar_t *start = ((const wchar_t *)s2) + i; - const wchar_t *end; - UInt64 v = ConvertStringToUInt64(start, &end); - if (start == end) - { - if (s2[i++] != 'E') - return E_INVALIDARG; - _solidExtension = true; - continue; - } - i += (int)(end - start); - if (i == s2.Length()) - return E_INVALIDARG; - wchar_t c = s2[i++]; - switch(c) - { - case 'F': - if (v < 1) - v = 1; - _numSolidFiles = v; - break; - case 'B': - _numSolidBytes = v; - _numSolidBytesDefined = true; - break; - case 'K': - _numSolidBytes = (v << 10); - _numSolidBytesDefined = true; - break; - case 'M': - _numSolidBytes = (v << 20); - _numSolidBytesDefined = true; - break; - case 'G': - _numSolidBytes = (v << 30); - _numSolidBytesDefined = true; - break; - default: - return E_INVALIDARG; - } - } - return S_OK; -} - -HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) -{ - bool isSolid; - switch(value.vt) - { - case VT_EMPTY: - isSolid = true; - break; - case VT_BOOL: - isSolid = (value.boolVal != VARIANT_FALSE); - break; - case VT_BSTR: - if (StringToBool(value.bstrVal, isSolid)) - break; - return SetSolidSettings(value.bstrVal); - default: - return E_INVALIDARG; - } - if (isSolid) - InitSolid(); - else - _numSolidFiles = 1; - return S_OK; -} - -void COutHandler::Init() -{ - _removeSfxBlock = false; - _compressHeaders = true; - _encryptHeadersSpecified = false; - _encryptHeaders = false; - - WriteCTime = false; - WriteATime = false; - WriteMTime = true; - + if (level != (UInt32)(UInt32)-1) + SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); #ifndef _7ZIP_ST - _numThreads = NSystem::GetNumberOfProcessors(); + SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif - - _level = 5; - _autoFilter = true; - _volumeMode = false; - _crcSize = 4; - InitSolid(); } -void COutHandler::BeforeSetProperty() +void CMultiMethodProps::Init() { - Init(); #ifndef _7ZIP_ST - numProcessors = NSystem::GetNumberOfProcessors(); + _numProcessors = _numThreads = NSystem::GetNumberOfProcessors(); #endif - - mainDicSize = 0xFFFFFFFF; - mainDicMethodIndex = 0xFFFFFFFF; - minNumber = 0; + + _level = (UInt32)(UInt32)-1; + _autoFilter = true; _crcSize = 4; + _filterMethod.Clear(); + _methods.Clear(); } -HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); @@ -511,24 +58,14 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val { name.Delete(0); _level = 9; - return ParsePropValue(name, value, _level); - } - - if (name[0] == L'S') - { - name.Delete(0); - if (name.IsEmpty()) - return SetSolidSettings(value); - if (value.vt != VT_EMPTY) - return E_INVALIDARG; - return SetSolidSettings(name); + return ParsePropToUInt32(name, value, _level); } if (name == L"CRC") { - _crcSize = 4; name.Delete(0, 3); - return ParsePropValue(name, value, _crcSize); + _crcSize = 4; + return ParsePropToUInt32(name, value, _crcSize); } UInt32 number; @@ -536,86 +73,67 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val UString realName = name.Mid(index); if (index == 0) { - if(name.Left(2).CompareNoCase(L"MT") == 0) + if (name.Left(2).CompareNoCase(L"MT") == 0) { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads)); #endif return S_OK; } - if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); - if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); - if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); - if (name.CompareNoCase(L"HCF") == 0) + if (name.CompareNoCase(L"F") == 0) { - bool compressHeadersFull = true; - RINOK(SetBoolProperty(compressHeadersFull, value)); - if (!compressHeadersFull) + HRESULT res = PROPVARIANT_to_bool(value, _autoFilter); + if (res == S_OK) + return res; + if (value.vt != VT_BSTR) return E_INVALIDARG; - return S_OK; + return _filterMethod.ParseMethodFromPROPVARIANT(L"", value); } - if (name.CompareNoCase(L"HE") == 0) - { - RINOK(SetBoolProperty(_encryptHeaders, value)); - _encryptHeadersSpecified = true; - return S_OK; - } - if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); - if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); - if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); - if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } - if (number > 10000) + if (number > 64) return E_FAIL; - if (number < minNumber) - return E_INVALIDARG; - number -= minNumber; - for(int j = _methods.Size(); j <= (int)number; j++) - { - COneMethodInfo oneMethodInfo; - _methods.Add(oneMethodInfo); - } - - COneMethodInfo &oneMethodInfo = _methods[number]; - - if (realName.Length() == 0) - { - if (value.vt != VT_BSTR) - return E_INVALIDARG; - - RINOK(SetParams(oneMethodInfo, value.bstrVal)); - } - else + for (int j = _methods.Size(); j <= (int)number; j++) + _methods.Add(COneMethodInfo()); + return _methods[number].ParseMethodFromPROPVARIANT(realName, value); +} + +void CSingleMethodProps::Init() +{ + Clear(); + #ifndef _7ZIP_ST + _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + AddNumThreadsProp(_numThreads); + #endif + _level = (UInt32)(UInt32)-1; +} + +HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + Init(); + for (int i = 0; i < numProps; i++) { - int index = FindPropIdStart(realName); - if (index < 0) + UString name = names[i]; + name.MakeUpper(); + if (name.IsEmpty()) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - CProp prop; - prop.Id = nameToPropID.PropID; - - if (prop.Id == NCoderPropID::kBlockSize || - prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) + const PROPVARIANT &value = values[i]; + if (name[0] == L'X') { - UInt32 dicSize; - RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize)); - prop.Value = dicSize; - if (number <= mainDicMethodIndex) - mainDicSize = dicSize; + UInt32 a = 9; + RINOK(ParsePropToUInt32(name.Mid(1), value, a)); + _level = a; + AddLevelProp(a); } - else + else if (name.Left(2).CompareNoCase(L"MT") == 0) { - int index = FindPropIdExact(realName); - if (index < 0) - return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; - prop.Id = nameToPropID.PropID; - if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) - return E_INVALIDARG; + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads)); + AddNumThreadsProp(_numThreads); + #endif } - oneMethodInfo.Props.Add(prop); + else + return ParseParamsFromPROPVARIANT(name, value); } return S_OK; } diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 72ea4032..d3c9a237 100755 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -3,83 +3,61 @@ #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H -#include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { -struct COneMethodInfo -{ - CObjectVector<CProp> Props; - UString MethodName; - - bool IsLzma() const; -}; - -class COutHandler +class CMultiMethodProps { + UInt32 _level; public: - HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); - - HRESULT SetSolidSettings(const UString &s); - HRESULT SetSolidSettings(const PROPVARIANT &value); - #ifndef _7ZIP_ST UInt32 _numThreads; + UInt32 _numProcessors; #endif UInt32 _crcSize; - CObjectVector<COneMethodInfo> _methods; - bool _removeSfxBlock; - - UInt64 _numSolidFiles; - UInt64 _numSolidBytes; - bool _numSolidBytesDefined; - bool _solidExtension; - - bool _compressHeaders; - bool _encryptHeadersSpecified; - bool _encryptHeaders; - - bool WriteCTime; - bool WriteATime; - bool WriteMTime; - + COneMethodInfo _filterMethod; bool _autoFilter; - UInt32 _level; - bool _volumeMode; - - HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); - HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); - - void SetCompressionMethod2(COneMethodInfo &oneMethodInfo + void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ); - void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } - void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } - void InitSolid() + int GetNumEmptyMethods() const { - InitSolidFiles(); - InitSolidSize(); - _solidExtension = false; - _numSolidBytesDefined = false; + int i; + for (i = 0; i < _methods.Size(); i++) + if (!_methods[i].IsEmpty()) + break; + return i; } + int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; } + void Init(); - COutHandler() { Init(); } + CMultiMethodProps() { Init(); } + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; - void BeforeSetProperty(); +class CSingleMethodProps: public CMethodProps +{ + UInt32 _level; + + void Init(); +public: + #ifndef _7ZIP_ST + UInt32 _numThreads; + UInt32 _numProcessors; + #endif - UInt32 minNumber; - UInt32 numProcessors; - UInt32 mainDicSize; - UInt32 mainDicMethodIndex; + CSingleMethodProps() { Init(); } + int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; } + HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); }; } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index a5e0dc0b..cc476fad 100755 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -31,8 +31,8 @@ UString GetOSName2(const UString &name) if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); - if (newName[newName.Length() - 1] == kOSDirDelimiter) - newName.Delete(newName.Length() - 1); + if (newName.Back() == kOSDirDelimiter) + newName.DeleteBack(); return newName; } diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp index 5cd849e2..63e4f3ef 100755 --- a/CPP/7zip/Archive/Common/ParseProperties.cpp +++ b/CPP/7zip/Archive/Common/ParseProperties.cpp @@ -1,177 +1,3 @@ // ParseProperties.cpp #include "StdAfx.h" - -#include "ParseProperties.h" - -#include "Common/StringToInt.h" -#include "Common/MyCom.h" - -HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) -{ - if (prop.vt == VT_UI4) - { - if (!name.IsEmpty()) - return E_INVALIDARG; - resValue = prop.ulVal; - } - else if (prop.vt == VT_EMPTY) - { - if(!name.IsEmpty()) - { - const wchar_t *start = name; - const wchar_t *end; - UInt64 v = ConvertStringToUInt64(start, &end); - if (end - start != name.Length()) - return E_INVALIDARG; - resValue = (UInt32)v; - } - } - else - return E_INVALIDARG; - return S_OK; -} - -static const int kLogarithmicSizeLimit = 32; -static const wchar_t kByteSymbol = L'B'; -static const wchar_t kKiloByteSymbol = L'K'; -static const wchar_t kMegaByteSymbol = L'M'; - -HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) -{ - UString srcString = srcStringSpec; - srcString.MakeUpper(); - - const wchar_t *start = srcString; - const wchar_t *end; - UInt64 number = ConvertStringToUInt64(start, &end); - int numDigits = (int)(end - start); - if (numDigits == 0 || srcString.Length() > numDigits + 1) - return E_INVALIDARG; - if (srcString.Length() == numDigits) - { - if (number >= kLogarithmicSizeLimit) - return E_INVALIDARG; - dicSize = (UInt32)1 << (int)number; - return S_OK; - } - switch (srcString[numDigits]) - { - case kByteSymbol: - if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) - return E_INVALIDARG; - dicSize = (UInt32)number; - break; - case kKiloByteSymbol: - if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) - return E_INVALIDARG; - dicSize = (UInt32)(number << 10); - break; - case kMegaByteSymbol: - if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) - return E_INVALIDARG; - dicSize = (UInt32)(number << 20); - break; - default: - return E_INVALIDARG; - } - return S_OK; -} - -HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) -{ - if (name.IsEmpty()) - { - if (prop.vt == VT_UI4) - { - UInt32 logDicSize = prop.ulVal; - if (logDicSize >= 32) - return E_INVALIDARG; - resValue = (UInt32)1 << logDicSize; - return S_OK; - } - if (prop.vt == VT_BSTR) - return ParsePropDictionaryValue(prop.bstrVal, resValue); - return E_INVALIDARG; - } - return ParsePropDictionaryValue(name, resValue); -} - -bool StringToBool(const UString &s, bool &res) -{ - if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) - { - res = true; - return true; - } - if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) - { - res = false; - return true; - } - return false; -} - -HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) -{ - switch(value.vt) - { - case VT_EMPTY: - dest = true; - return S_OK; - case VT_BOOL: - dest = (value.boolVal != VARIANT_FALSE); - return S_OK; - /* - case VT_UI4: - dest = (value.ulVal != 0); - break; - */ - case VT_BSTR: - return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; - } - return E_INVALIDARG; -} - -int ParseStringToUInt32(const UString &srcString, UInt32 &number) -{ - const wchar_t *start = srcString; - const wchar_t *end; - UInt64 number64 = ConvertStringToUInt64(start, &end); - if (number64 > 0xFFFFFFFF) - { - number = 0; - return 0; - } - number = (UInt32)number64; - return (int)(end - start); -} - -HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) -{ - if (name.IsEmpty()) - { - switch(prop.vt) - { - case VT_UI4: - numThreads = prop.ulVal; - break; - default: - { - bool val; - RINOK(SetBoolProperty(val, prop)); - numThreads = (val ? defaultNumThreads : 1); - break; - } - } - } - else - { - UInt32 number; - int index = ParseStringToUInt32(name, number); - if (index != name.Length()) - return E_INVALIDARG; - numThreads = number; - } - return S_OK; -} diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h index 6f80f634..1038a8c0 100755 --- a/CPP/7zip/Archive/Common/ParseProperties.h +++ b/CPP/7zip/Archive/Common/ParseProperties.h @@ -1,18 +1,6 @@ // ParseProperties.h -#ifndef __PARSEPROPERTIES_H -#define __PARSEPROPERTIES_H - -#include "Common/MyString.h" -#include "Common/Types.h" - -HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); -HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); -HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); - -bool StringToBool(const UString &s, bool &res); -HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); -int ParseStringToUInt32(const UString &srcString, UInt32 &number); -HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); +#ifndef __PARSE_PROPERTIES_H +#define __PARSE_PROPERTIES_H #endif diff --git a/CPP/7zip/Archive/DeflateProps.cpp b/CPP/7zip/Archive/DeflateProps.cpp index 8498e056..ca3dc6f5 100755 --- a/CPP/7zip/Archive/DeflateProps.cpp +++ b/CPP/7zip/Archive/DeflateProps.cpp @@ -1,118 +1,3 @@ // DeflateProps.cpp #include "StdAfx.h" - -#include "Windows/PropVariant.h" - -#include "Common/ParseProperties.h" - -#include "DeflateProps.h" - -namespace NArchive { - -static const UInt32 kAlgo1 = 0; -static const UInt32 kAlgo5 = 1; - -static const UInt32 kPasses1 = 1; -static const UInt32 kPasses7 = 3; -static const UInt32 kPasses9 = 10; - -static const UInt32 kFb1 = 32; -static const UInt32 kFb7 = 64; -static const UInt32 kFb9 = 128; - -void CDeflateProps::Normalize() -{ - UInt32 level = Level; - if (level == 0xFFFFFFFF) - level = 5; - - if (Algo == 0xFFFFFFFF) - Algo = (level >= 5 ? - kAlgo5 : - kAlgo1); - - if (NumPasses == 0xFFFFFFFF) - NumPasses = - (level >= 9 ? kPasses9 : - (level >= 7 ? kPasses7 : - kPasses1)); - if (Fb == 0xFFFFFFFF) - Fb = - (level >= 9 ? kFb9 : - (level >= 7 ? kFb7 : - kFb1)); -} - -HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties) -{ - Normalize(); - - NWindows::NCOM::CPropVariant props[] = - { - Algo, - NumPasses, - Fb, - Mc - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kNumPasses, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!McDefined) - numProps--; - return setCoderProperties->SetCoderProperties(propIDs, props, numProps); -} - -HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) -{ - Init(); - for (int i = 0; i < numProps; i++) - { - UString name = names[i]; - name.MakeUpper(); - if (name.IsEmpty()) - return E_INVALIDARG; - const PROPVARIANT &prop = values[i]; - if (name[0] == L'X') - { - UInt32 a = 9; - RINOK(ParsePropValue(name.Mid(1), prop, a)); - Level = a; - } - else if (name.Left(1) == L"A") - { - UInt32 a = kAlgo5; - RINOK(ParsePropValue(name.Mid(1), prop, a)); - Algo = a; - } - else if (name.Left(4) == L"PASS") - { - UInt32 a = kPasses9; - RINOK(ParsePropValue(name.Mid(4), prop, a)); - NumPasses = a; - } - else if (name.Left(2) == L"FB") - { - UInt32 a = kFb9; - RINOK(ParsePropValue(name.Mid(2), prop, a)); - Fb = a; - } - else if (name.Left(2) == L"MC") - { - UInt32 a = 0xFFFFFFFF; - RINOK(ParsePropValue(name.Mid(2), prop, a)); - Mc = a; - McDefined = true; - } - else - return E_INVALIDARG; - } - return S_OK; -} - -} diff --git a/CPP/7zip/Archive/DeflateProps.h b/CPP/7zip/Archive/DeflateProps.h index e05a9d4a..9fd2c2e9 100755 --- a/CPP/7zip/Archive/DeflateProps.h +++ b/CPP/7zip/Archive/DeflateProps.h @@ -3,33 +3,4 @@ #ifndef __DEFLATE_PROPS_H #define __DEFLATE_PROPS_H -#include "../ICoder.h" - -namespace NArchive { - -class CDeflateProps -{ - UInt32 Level; - UInt32 NumPasses; - UInt32 Fb; - UInt32 Algo; - UInt32 Mc; - bool McDefined; - - void Init() - { - Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF; - McDefined = false; - } - void Normalize(); -public: - CDeflateProps() { Init(); } - bool IsMaximum() const { return Algo > 0; } - - HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties); - HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); -}; - -} - #endif diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index 7b73bddc..ede6b01b 100755 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -18,11 +18,10 @@ #include "../Compress/DeflateDecoder.h" #include "../Compress/DeflateEncoder.h" +#include "Common/HandlerOut.h" #include "Common/InStreamWithCRC.h" #include "Common/OutStreamWithCRC.h" -#include "DeflateProps.h" - #define Get32(p) GetUi32(p) using namespace NWindows; @@ -305,7 +304,7 @@ class CHandler: CMyComPtr<ICompressCoder> _decoder; NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec; - CDeflateProps _method; + CSingleMethodProps _props; public: MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) @@ -321,7 +320,7 @@ public: } }; -STATPROPSTG kProps[] = +static STATPROPSTG const kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, @@ -545,7 +544,7 @@ static HRESULT UpdateArchive( ISequentialOutStream *outStream, UInt64 unpackSize, const CItem &newItem, - CDeflateProps &deflateProps, + const CSingleMethodProps &props, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = 0; @@ -567,7 +566,7 @@ static HRESULT UpdateArchive( CItem item = newItem; item.Method = NHeader::NCompressionMethod::kDeflate; - item.ExtraFlags = deflateProps.IsMaximum() ? + item.ExtraFlags = props.GetLevel() >= 7 ? NHeader::NExtraFlags::kMaximum : NHeader::NExtraFlags::kFastest; @@ -577,7 +576,7 @@ static HRESULT UpdateArchive( NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder; CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec; - RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec)); + RINOK(props.SetCoderProps(deflateEncoderSpec, NULL)); RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); item.Crc = inStreamSpec->GetCRC(); @@ -616,8 +615,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (prop.vt != VT_FILETIME) return E_INVALIDARG; utcTime = prop.filetime; - if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time)) - return E_INVALIDARG; + NTime::FileTimeToUnixTime(utcTime, newItem.Time); } { NCOM::CPropVariant prop; @@ -658,8 +656,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; size = prop.uhVal.QuadPart; } - - return UpdateArchive(outStream, size, newItem, _method, updateCallback); + return UpdateArchive(outStream, size, newItem, _props, updateCallback); } if (indexInArchive != 0) @@ -680,7 +677,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) { - return _method.SetProperties(names, values, numProps); + return _props.SetProperties(names, values, numProps); } static IInArchive *CreateArc() { return new CHandler; } diff --git a/CPP/7zip/Archive/Icons/bz2.ico b/CPP/7zip/Archive/Icons/bz2.ico Binary files differindex 614e3540..f22abebc 100755 --- a/CPP/7zip/Archive/Icons/bz2.ico +++ b/CPP/7zip/Archive/Icons/bz2.ico diff --git a/CPP/7zip/Archive/Icons/cab.ico b/CPP/7zip/Archive/Icons/cab.ico Binary files differindex cc2007fc..c96c0f01 100755 --- a/CPP/7zip/Archive/Icons/cab.ico +++ b/CPP/7zip/Archive/Icons/cab.ico diff --git a/CPP/7zip/Archive/Icons/fat.ico b/CPP/7zip/Archive/Icons/fat.ico Binary files differindex 882753ac..7503d933 100755 --- a/CPP/7zip/Archive/Icons/fat.ico +++ b/CPP/7zip/Archive/Icons/fat.ico diff --git a/CPP/7zip/Archive/Icons/gz.ico b/CPP/7zip/Archive/Icons/gz.ico Binary files differindex f50d8c08..d402a698 100755 --- a/CPP/7zip/Archive/Icons/gz.ico +++ b/CPP/7zip/Archive/Icons/gz.ico diff --git a/CPP/7zip/Archive/Icons/hfs.ico b/CPP/7zip/Archive/Icons/hfs.ico Binary files differindex 92a46b81..bf2c1986 100755 --- a/CPP/7zip/Archive/Icons/hfs.ico +++ b/CPP/7zip/Archive/Icons/hfs.ico diff --git a/CPP/7zip/Archive/Icons/iso.ico b/CPP/7zip/Archive/Icons/iso.ico Binary files differindex 2538e408..b3e3ac2f 100755 --- a/CPP/7zip/Archive/Icons/iso.ico +++ b/CPP/7zip/Archive/Icons/iso.ico diff --git a/CPP/7zip/Archive/Icons/split.ico b/CPP/7zip/Archive/Icons/split.ico Binary files differindex 79cb089b..65723ff3 100755 --- a/CPP/7zip/Archive/Icons/split.ico +++ b/CPP/7zip/Archive/Icons/split.ico diff --git a/CPP/7zip/Archive/Icons/squashfs.ico b/CPP/7zip/Archive/Icons/squashfs.ico Binary files differindex 551a7439..b802d942 100755 --- a/CPP/7zip/Archive/Icons/squashfs.ico +++ b/CPP/7zip/Archive/Icons/squashfs.ico diff --git a/CPP/7zip/Archive/Icons/xz.ico b/CPP/7zip/Archive/Icons/xz.ico Binary files differindex 02707351..bc07a7eb 100755 --- a/CPP/7zip/Archive/Icons/xz.ico +++ b/CPP/7zip/Archive/Icons/xz.ico diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 4bfb7dc6..f040b033 100755 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -172,11 +172,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val int pos = s.ReverseFind(L';'); if (pos >= 0 && pos == s.Length() - 2) - if (s[s.Length() - 1] == L'1') + if (s.Back() == L'1') s = s.Left(pos); if (!s.IsEmpty()) - if (s[s.Length() - 1] == L'.') - s = s.Left(s.Length() - 1); + if (s.Back() == L'.') + s.DeleteBack(); prop = (const wchar_t *)NItemName::GetOSName2(s); } break; @@ -211,19 +211,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return S_OK; UInt64 totalSize = 0; UInt32 i; - for(i = 0; i < numItems; i++) + for (i = 0; i < numItems; i++) { UInt32 index = (allFilesMode ? i : indices[i]); if (index < (UInt32)_archive.Refs.Size()) { const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; - totalSize += item.DataLength; + if (!item.IsDir()) + totalSize += item.DataLength; } else - { totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size()); - } } extractCallback->SetTotal(totalSize); diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index 95efc501..194de47e 100755 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -177,47 +177,6 @@ struct CItem } }; -struct CItemEx: public CItem -{ - UInt64 DataPosition; -}; - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); - HRESULT CheckReadBytes(void *data, UInt32 size); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skip(UInt64 numBytes); -}; - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size) -{ - UInt32 processedSize; - RINOK(ReadBytes(data, size, processedSize)); - return (processedSize == size) ? S_OK: S_FALSE; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - static const Byte *ReadUInt16(const Byte *p, UInt16 &v) { v = Get16(p); @@ -245,13 +204,13 @@ static Byte CalcSum(const Byte *data, size_t size) return sum; } -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &item) { filled = false; - UInt32 processedSize; + size_t processedSize = 2; Byte startHeader[2]; - RINOK(ReadBytes(startHeader, 2, processedSize)) + RINOK(ReadStream(stream, startHeader, &processedSize)) if (processedSize == 0) return S_OK; if (processedSize == 1) @@ -261,7 +220,8 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) Byte header[256]; const UInt32 kBasicPartSize = 22; - RINOK(ReadBytes(header, kBasicPartSize, processedSize)); + processedSize = kBasicPartSize; + RINOK(ReadStream(stream, header, &processedSize)); if (processedSize != kBasicPartSize) return (startHeader[0] == 0) ? S_OK: S_FALSE; @@ -284,8 +244,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) headerSize = startHeader[0]; if (headerSize < kBasicPartSize) return S_FALSE; - UInt32 remain = headerSize - kBasicPartSize; - RINOK(CheckReadBytes(header + kBasicPartSize, remain)); + RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, headerSize - kBasicPartSize)); if (startHeader[1] != CalcSum(header, headerSize)) return S_FALSE; size_t nameLength = *p++; @@ -294,13 +253,13 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) p = ReadString(p, nameLength, item.Name); } else - headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); + headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); p = ReadUInt16(p, item.CRC); if (item.Level != 0) { if (item.Level == 2) { - RINOK(CheckReadBytes(header + kBasicPartSize, 2)); + RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, 2)); } if ((size_t)(p - header) + 3 > headerSize) return S_FALSE; @@ -317,39 +276,30 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) return S_FALSE; item.PackSize -= nextSize; } + if (item.Extensions.Size() >= (1 << 8)) + return S_FALSE; CExtension ext; - RINOK(CheckReadBytes(&ext.Type, 1)) + RINOK(ReadStream_FALSE(stream, &ext.Type, 1)) nextSize -= 3; ext.Data.SetCapacity(nextSize); - RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) + RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); Byte hdr2[2]; - RINOK(CheckReadBytes(hdr2, 2)); + RINOK(ReadStream_FALSE(stream, hdr2, 2)); ReadUInt16(hdr2, nextSize); } } - item.DataPosition = m_Position; filled = true; return S_OK; } -HRESULT CInArchive::Skip(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - struct COsPair { Byte Id; const char *Name; }; -static COsPair g_OsPairs[] = +static const COsPair g_OsPairs[] = { { 0, "MS-DOS" }, { 'M', "MS-DOS" }, @@ -380,7 +330,7 @@ static const char *GetOS(Byte osId) return kUnknownOS; } -static STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -393,6 +343,11 @@ static STATPROPSTG kProps[] = { NULL, kpidHostOS, VT_BSTR} }; +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI8} +}; + class CCRC { UInt16 _value; @@ -479,12 +434,19 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pro return result; } +struct CItemEx: public CItem +{ + UInt64 DataPosition; +}; + class CHandler: public IInArchive, public CMyUnknownImp { CObjectVector<CItemEx> _items; CMyComPtr<IInStream> _stream; + UInt64 _phySize; + AString _errorMessage; public: MY_UNKNOWN_IMP1(IInArchive) INTERFACE_IInArchive(;) @@ -492,7 +454,7 @@ public: }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps CHandler::CHandler() {} @@ -502,6 +464,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _phySize; break; + case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break; + } + prop.Detach(value); + return S_OK; +} + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -514,8 +488,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); if (!s.IsEmpty()) { - if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) - s.Delete(s.Length() - 1); + if (s.Back() == WCHAR_PATH_SEPARATOR) + s.DeleteBack(); prop = s; } break; @@ -567,32 +541,43 @@ STDMETHODIMP CHandler::Open(IInStream *stream, try { _items.Clear(); - CInArchive archive; UInt64 endPos = 0; bool needSetTotal = true; - if (callback != NULL) - { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - } + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(archive.Open(stream)); + _phySize = 0; for (;;) { CItemEx item; bool filled; - HRESULT result = archive.GetNextItem(filled, item); + HRESULT result = GetNextItem(stream, filled, item); + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition)); if (result == S_FALSE) - return S_FALSE; + { + _errorMessage = "Incorrect header"; + break; + } + if (result != S_OK) return S_FALSE; + _phySize = item.DataPosition; if (!filled) break; _items.Add(item); - archive.Skip(item.PackSize); - if (callback != NULL) + + UInt64 newPostion; + RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion)); + if (newPostion > endPos) + { + _phySize = endPos; + _errorMessage = "Unexpected end of archive"; + break; + } + _phySize = newPostion; + if (callback) { if (needSetTotal) { @@ -622,6 +607,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, STDMETHODIMP CHandler::Close() { + _errorMessage.Empty(); _items.Clear(); _stream.Release(); return S_OK; diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index a83e6a1a..778c2fd8 100755 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -296,7 +296,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); _packSize = endPos - _startPosition; _packSizeDefined = true; - + if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0) + return S_FALSE; _stream = inStream; _seqStream = inStream; return S_OK; diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index da4df24c..5ebda099 100755 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -15,7 +15,7 @@ #include "../Compress/CopyCoder.h" -#define Get32(p) GetBe32(p) +static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); } namespace NArchive { namespace NMub { @@ -116,8 +116,16 @@ HRESULT CHandler::Open2(IInStream *stream) RINOK(ReadStream(stream, buf, &processed)); if (processed < kHeaderSize) return S_FALSE; - UInt32 num = Get32(buf + 4); - if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize) + + bool be; + switch (GetBe32(buf)) + { + case 0xCAFEBABE: be = true; break; + case 0xB9FAF10E: be = false; break; + default: return S_FALSE; + } + UInt32 num = Get32(buf + 4, be); + if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize) return S_FALSE; UInt64 endPosMax = kHeaderSize; for (UInt32 i = 0; i < num; i++) @@ -125,11 +133,11 @@ HRESULT CHandler::Open2(IInStream *stream) const Byte *p = buf + kHeaderSize + i * kRecordSize; CItem &sb = _items[i]; sb.IsTail = false; - sb.Type = Get32(p); - sb.SubType = Get32(p + 4); - sb.Offset = Get32(p + 8); - sb.Size = Get32(p + 12); - sb.Align = Get32(p + 16); + sb.Type = Get32(p, be); + sb.SubType = Get32(p + 4, be); + sb.Offset = Get32(p + 8, be); + sb.Size = Get32(p + 12, be); + sb.Align = Get32(p + 16, be); if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 || (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 || diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 87ae3f1c..7ca719e4 100755 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -87,7 +87,7 @@ struct CItem else s = MultiByteToUnicodeString(PrefixA); if (s.Length() > 0) - if (s[s.Length() - 1] != L'\\') + if (s.Back() != L'\\') s += L'\\'; if (unicode) s += NameU; diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index c64067aa..e5946969 100755 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -631,7 +631,7 @@ enum // kpidBaseOfData32, }; -STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidCpu, VT_BSTR}, { NULL, kpidBit64, VT_BOOL}, @@ -662,7 +662,7 @@ STATPROPSTG kArcProps[] = // { L"Base Of Data", kpidBaseOfData32, VT_UI8}, }; -STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, @@ -1749,4 +1749,335 @@ static CArcInfo g_ArcInfo = REGISTER_ARC(Pe) -}} +} + + + + +namespace NTe { + +// Terse Executable (TE) image + +/* +struct CDataDir +{ + UInt32 Va; + UInt32 Size; +}; +*/ + +static const UInt32 kHeaderSize = 40; + +static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) +{ + for (unsigned i = 0; i < num; i++) + if (pairs[i].Value == value) + return true; + return false; +} + +#define MY_FIND_VALUE(pairs, value) FindValue(pairs, sizeof(pairs) / sizeof(pairs[0]), value) + +struct CHeader +{ + UInt16 Machine; + Byte NumSections; + Byte SubSystem; + UInt16 StrippedSize; + /* + UInt32 AddressOfEntryPoint; + UInt32 BaseOfCode; + UInt64 ImageBase; + CDataDir DataDir[2]; // base relocation and debug directory + */ + + UInt32 ConvertPa(UInt32 pa) const { return pa - StrippedSize + kHeaderSize; } + + bool Parse(const Byte *p) + { + if (p[0] != 'V' || p[1] != 'Z') + return false; + Machine = Get16(p + 2); + NumSections = p[4]; + SubSystem = p[5]; + StrippedSize = Get16(p + 6); + /* + AddressOfEntryPoint = Get32(p + 8); + BaseOfCode = Get32(p + 12); + ImageBase = Get64(p + 16); + for (int i = 0; i < 2; i++) + { + const Byte *p2 = p + 24 + i * 8; + DataDir[i].Va = Get32(p2); + DataDir[i].Size = Get32(p2 + 4); + } + */ + return NumSections <= 64 && + MY_FIND_VALUE(NPe::g_MachinePairs, Machine) && + MY_FIND_VALUE(NPe::g_SubSystems, SubSystem); + } +}; + +struct CSection +{ + Byte Name[8]; + + // UInt32 VSize; + UInt32 Va; + UInt32 PSize; + UInt32 Pa; + UInt32 Flags; + // UInt16 NumRelocs; + + void Parse(const Byte *p) + { + memcpy(Name, p, 8); + // VSize = Get32(p + 8); + Va = Get32(p + 12); + PSize = Get32(p + 16); + Pa = Get32(p + 20); + // NumRelocs = Get16(p + 32); + Flags = Get32(p + 36); + } + + bool Check() const { return (PSize + Pa > Pa); } + + void UpdateTotalSize(UInt32 &totalSize) + { + UInt32 t = Pa + PSize; + if (t > totalSize) + totalSize = t; + } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UInt32 _totalSize; + CMyComPtr<IInStream> _stream; + CObjectVector<CSection> _items; + CHeader _h; + UInt64 _fileSize; + + HRESULT Open2(IInStream *stream); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI4}, + { NULL, kpidPackSize, VT_UI4}, + { NULL, kpidCharacts, VT_BSTR}, + { NULL, kpidOffset, VT_UI4}, + { NULL, kpidVa, VT_UI8} +}; + +enum +{ + kpidSubSystem + // , kpidImageBase +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI4}, + // { NULL, kpidHeadersSize, VT_UI4}, + { NULL, kpidCpu, VT_BSTR}, + { L"Subsystem", kpidSubSystem, VT_BSTR}, + // { L"Image Base", kpidImageBase, VT_UI8} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_WITH_NAME + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _totalSize; break; + case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break; + case kpidSubSystem: PAIR_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break; + /* + case kpidImageBase: prop = _h.ImageBase; break; + case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break; + case kpidBaseOfCode: prop = _h.BaseOfCode; break; + */ + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + { + const CSection &item = _items[index]; + switch(propID) + { + case kpidPath: StringToProp(NPe::GetName(item.Name), prop); break; + case kpidSize: + case kpidPackSize: prop = (UInt64)item.PSize; break; + case kpidOffset: prop = item.Pa; break; + case kpidVa: prop = item.Va; break; + case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Open2(IInStream *stream) +{ + Byte h[kHeaderSize]; + RINOK(ReadStream_FALSE(stream, h, kHeaderSize)); + if (!_h.Parse(h)) + return S_FALSE; + + CByteBuffer buf; + UInt32 headerSize = NPe::kSectionSize * _h.NumSections; + buf.SetCapacity(headerSize); + RINOK(ReadStream_FALSE(stream, buf, headerSize)); + + _totalSize = kHeaderSize + headerSize; + + for (UInt32 i = 0; i < headerSize; i += NPe::kSectionSize) + { + CSection sect; + sect.Parse(buf + i); + sect.Pa = _h.ConvertPa(sect.Pa); + _items.Add(sect); + sect.UpdateTotalSize(_totalSize); + if (!sect.Check()) + return S_FALSE; + } + + return stream->Seek(0, STREAM_SEEK_END, &_fileSize); +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + Close(); + try + { + if (Open2(inStream) != S_OK) + return S_FALSE; + _stream = inStream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _items.Clear(); + _totalSize = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +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; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].PSize; + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + streamSpec->SetStream(_stream); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CSection &item = _items[index]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + currentTotalSize += item.PSize; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + int res = NExtract::NOperationResult::kDataError; + if (item.Pa <= _fileSize) + { + if (testMode) + { + if (item.Pa + item.PSize <= _fileSize) + res = NExtract::NOperationResult::kOK; + } + else + { + RINOK(_stream->Seek(item.Pa, STREAM_SEEK_SET, NULL)); + streamSpec->Init(item.PSize); + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.PSize) + res = NExtract::NOperationResult::kOK; + } + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CSection &item = _items[index]; + return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream); + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"TE", L"te", 0, 0xCF, { 'V', 'Z' }, 2, false, CreateArc, 0 }; + +REGISTER_ARC(TE) + +} +} diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp index e4c23752..a7d018ff 100755 --- a/CPP/7zip/Archive/Rar/RarIn.cpp +++ b/CPP/7zip/Archive/Rar/RarIn.cpp @@ -112,7 +112,7 @@ HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF)) return S_FALSE; - size_t commentSize = blockSize - headerSize; + size_t commentSize = blockSize - headerSize; _comment.SetCapacity(commentSize); RINOK(ReadStream_FALSE(stream, _comment, commentSize)); AddToSeekValue(commentSize); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 2cc1219a..efaffed1 100755 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -5,6 +5,7 @@ #include "../../../C/7zCrc.h" #include "../../../C/Alloc.h" #include "../../../C/CpuArch.h" +#include "../../../C/Xz.h" #include "Common/ComTry.h" #include "Common/IntToString.h" @@ -13,6 +14,7 @@ #include "Windows/PropVariantUtils.h" #include "Windows/Time.h" +#include "../Common/CWrappers.h" #include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" @@ -26,6 +28,10 @@ namespace NArchive { namespace NSquashfs { +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + static const UInt32 kNumFilesMax = (1 << 28); static const unsigned kNumDirLevelsMax = (1 << 10); @@ -62,13 +68,15 @@ static const UInt32 kSignature32_LZ = 0x71736873; #define kMethod_ZLIB 1 #define kMethod_LZMA 2 #define kMethod_LZO 3 +#define kMethod_XZ 4 static const char *k_Methods[] = { "Unknown", "ZLIB", "LZMA", - "LZO" + "LZO", + "XZ" }; static const UInt32 kMetadataBlockSizeLog = 13; @@ -860,6 +868,8 @@ class CHandler: NCompress::NZlib::CDecoder *_zlibDecoderSpec; CMyComPtr<ICompressCoder> _zlibDecoder; + CXzUnpacker _xz; + CByteBuffer _inputBuffer; CDynBufSeqOutStream *_dynOutStreamSpec; @@ -886,6 +896,11 @@ class CHandler: public: CHandler(); + ~CHandler() + { + XzUnpacker_Free(&_xz); + } + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); @@ -895,6 +910,8 @@ public: CHandler::CHandler() { + XzUnpacker_Construct(&_xz, &g_Alloc); + _limitedInStreamSpec = new CLimitedSequentialInStream; _limitedInStream = _limitedInStreamSpec; @@ -1104,33 +1121,16 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL)); } - if (method == kMethod_LZO) + if (method == kMethod_ZLIB) { - if (_inputBuffer.GetCapacity() < inSize) - { - _inputBuffer.Free(); - _inputBuffer.SetCapacity(inSize); - } - RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize)); - - Byte *dest = outBuf; - if (!outBuf) + if (!_zlibDecoder) { - dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax); - if (!dest) - return E_OUTOFMEMORY; + _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); + _zlibDecoder = _zlibDecoderSpec; } - SizeT destLen = outSizeMax, srcLen = inSize; - RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen)); - if (inSize != srcLen) + RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL)); + if (inSize != _zlibDecoderSpec->GetInputProcessedSize()) return S_FALSE; - if (outBuf) - { - *outBufWasWritten = true; - *outBufWasWrittenSize = (UInt32)destLen; - } - else - _dynOutStreamSpec->UpdateSize(destLen); } else if (method == kMethod_LZMA) { @@ -1153,14 +1153,44 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool } else { - if (!_zlibDecoder) + if (_inputBuffer.GetCapacity() < inSize) { - _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); - _zlibDecoder = _zlibDecoderSpec; + _inputBuffer.Free(); + _inputBuffer.SetCapacity(inSize); } - RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL)); - if (inSize != _zlibDecoderSpec->GetInputProcessedSize()) + RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize)); + + Byte *dest = outBuf; + if (!outBuf) + { + dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax); + if (!dest) + return E_OUTOFMEMORY; + } + SizeT destLen = outSizeMax, srcLen = inSize; + if (method == kMethod_LZO) + { + RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen)); + } + else + { + ECoderStatus status; + XzUnpacker_Init(&_xz); + SRes res = XzUnpacker_Code(&_xz, dest, &destLen, _inputBuffer, &srcLen, LZMA_FINISH_END, &status); + if (res != 0) + return SResToHRESULT(res); + if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz)) + return S_FALSE; + } + if (inSize != srcLen) return S_FALSE; + if (outBuf) + { + *outBufWasWritten = true; + *outBufWasWrittenSize = (UInt32)destLen; + } + else + _dynOutStreamSpec->UpdateSize(destLen); } return S_OK; } @@ -1418,6 +1448,7 @@ HRESULT CHandler::Open2(IInStream *inStream) case kMethod_ZLIB: case kMethod_LZMA: case kMethod_LZO: + case kMethod_XZ: break; default: return E_NOTIMPL; @@ -2072,15 +2103,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (inStream) { HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); - if (hres != S_OK && hres != S_FALSE) + if (hres == S_OK) { - RINOK(hres); + if (copyCoderSpec->TotalSize == unpackSize) + res = NExtract::NOperationResult::kOK; + } + else if (hres == E_NOTIMPL) + { + res = NExtract::NOperationResult::kUnSupportedMethod; } - if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK) - res = NExtract::NOperationResult::kOK; - else + else if(hres != S_FALSE) { - res = res; + RINOK(hres); } } } diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index dfc0326d..d7d9537e 100755 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -21,8 +21,7 @@ #include "../Compress/ZlibEncoder.h" #include "Common/DummyOutStream.h" - -#include "DeflateProps.h" +#include "Common/HandlerOut.h" using namespace NWindows; @@ -69,7 +68,7 @@ class CHandler: CMyComPtr<ISequentialInStream> _seqStream; CMyComPtr<IInStream> _stream; - CDeflateProps _method; + CSingleMethodProps _props; public: MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) @@ -206,7 +205,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } static HRESULT UpdateArchive(ISequentialOutStream *outStream, - UInt64 size, CDeflateProps &deflateProps, + UInt64 size, const CSingleMethodProps &props, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = 0; @@ -234,7 +233,7 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream, NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; encoderSpec->Create(); - RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec)); + RINOK(props.SetCoderProps(encoderSpec->DeflateEncoderSpec, NULL)); RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)); if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size) return E_INVALIDARG; @@ -284,7 +283,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; size = prop.uhVal.QuadPart; } - return UpdateArchive(outStream, size, _method, updateCallback); + return UpdateArchive(outStream, size, _props, updateCallback); } if (indexInArchive != 0) @@ -304,7 +303,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) { - return _method.SetProperties(names, values, numProps); + return _props.SetProperties(names, values, numProps); } static IInArchive *CreateArc() { return new CHandler; } diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 4db0cae8..251afdb7 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -64,6 +64,8 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx & { item.HeaderPos = _phySize; RINOK(ReadItem(stream, filled, item, _errorMessage)); + if (filled && item.IsSparse()) + _isSparse = true; _phySize += item.HeaderSize; _headersSize += item.HeaderSize; return S_OK; @@ -87,7 +89,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) break; _items.Add(item); - RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize)); + RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); if (_phySize > endPos) { _errorMessage = kUnexpectedEnd; @@ -162,6 +164,7 @@ STDMETHODIMP CHandler::Close() _headersSize = 0; _curIndex = 0; _latestIsRead = false; + _isSparse = false; _items.Clear(); _seqStream.Release(); _stream.Release(); @@ -186,7 +189,7 @@ HRESULT CHandler::SkipTo(UInt32 index) { if (_latestIsRead) { - UInt64 packSize = _latestItem.GetPackSize(); + UInt64 packSize = _latestItem.GetPackSizeAligned(); RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL)); _phySize += copyCoderSpec->TotalSize; if (copyCoderSpec->TotalSize != packSize) @@ -241,13 +244,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break; case kpidIsDir: prop = item->IsDir(); break; case kpidSize: prop = item->GetUnpackSize(); break; - case kpidPackSize: prop = item->GetPackSize(); break; + case kpidPackSize: prop = item->GetPackSizeAligned(); break; case kpidMTime: if (item->MTime != 0) { FILETIME ft; - NTime::UnixTimeToFileTime(item->MTime, ft); - prop = ft; + if (NTime::UnixTime64ToFileTime(item->MTime, ft)) + prop = ft; } break; case kpidPosixAttrib: prop = item->Mode; break; @@ -319,7 +322,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); UInt64 unpackSize = item->GetUnpackSize(); totalSize += unpackSize; - totalPackSize += item->GetPackSize(); + totalPackSize += item->GetPackSizeAligned(); if (item->IsDir()) { RINOK(extractCallback->PrepareOperation(askMode)); @@ -340,18 +343,26 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, realOutStream.Release(); outStreamSpec->Init(skipMode ? 0 : unpackSize, true); - if (item->IsLink()) - { - RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length())); - } + Int32 opRes = NExtract::NOperationResult::kOK; + if (item->IsSparse()) + opRes = NExtract::NOperationResult::kUnSupportedMethod; else { - if (!seqMode) + if (item->IsLink()) + { + RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length())); + } + else { - RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + if (!seqMode) + { + RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + } + streamSpec->Init(item->GetPackSizeAligned()); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); } - streamSpec->Init(item->GetPackSize()); - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + if (outStreamSpec->GetRem() != 0) + opRes = NExtract::NOperationResult::kDataError; } if (seqMode) { @@ -359,9 +370,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, _curIndex++; } outStreamSpec->ReleaseStream(); - RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kDataError)); + RINOK(extractCallback->SetOperationResult(opRes)); } return S_OK; COM_TRY_END @@ -371,6 +380,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN const CItemEx &item = _items[index]; + if (item.IsSparse()) + return E_NOTIMPL; if (item.IsLink()) { CBufInStream *streamSpec = new CBufInStream; @@ -379,7 +390,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = streamTemp.Detach(); return S_OK; } - return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); + return CreateLimitedInStream(_stream, item.GetDataPosition(), item.PackSize, stream); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index b1967061..9251edf6 100755 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -32,6 +32,7 @@ class CHandler: UInt64 _headersSize; bool _phySizeDefined; AString _errorMessage; + bool _isSparse; NCompress::CCopyCoder *copyCoderSpec; CMyComPtr<ICompressCoder> copyCoder; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index ffdf2b13..b0ec63d1 100755 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt IArchiveUpdateCallback *callback) { COM_TRY_BEGIN - if ((_stream && !_errorMessage.IsEmpty()) || _seqStream) + if ((_stream && (!_errorMessage.IsEmpty() || _isSparse)) || _seqStream) return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) @@ -81,11 +81,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidMTime, &prop)); if (prop.vt == VT_EMPTY) - ui.Time = 0; + ui.MTime = 0; else if (prop.vt != VT_FILETIME) return E_INVALIDARG; - else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time)) - ui.Time = 0; + else + ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); } { NCOM::CPropVariant prop; diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h index 0b78bdc2..a212ae03 100755 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -84,6 +84,7 @@ namespace NFileHeader Each file name is terminated by a null + an additional null after the last file name. */ + const char kSparse = 'S'; } // Further link types may be defined later. diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 5ceaa509..b6e5e0f5 100755 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -63,6 +63,31 @@ static void ReadString(const char *s, int size, AString &result) result = temp; } +static bool ParseInt64(const char *p, Int64 &val) +{ + UInt32 h = GetBe32(p); + val = GetBe64(p + 4); + if (h == (UInt32)1 << 31) + return ((val >> 63) & 1) == 0; + if (h == (UInt32)(Int32)-1) + return ((val >> 63) & 1) != 0; + UInt64 uv; + bool res = OctalToNumber(p, 12, uv); + val = uv; + return res; +} + +static bool ParseSize(const char *p, UInt64 &val) +{ + if (GetBe32(p) == (UInt32)1 << 31) + { + // GNU extension + val = GetBe64(p + 4); + return ((val >> 63) & 1) == 0; + } + return OctalToNumber(p, 12, val); +} + static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error) { char buf[NFileHeader::kRecordSize]; @@ -105,17 +130,10 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; - if (GetBe32(p) == (UInt32)1 << 31) - { - // GNU extension - item.Size = GetBe64(p + 4); - } - else - { - RIF(OctalToNumber(p, 12, item.Size)); - } + RIF(ParseSize(p, item.PackSize)); + item.Size = item.PackSize; p += 12; - RIF(OctalToNumber32(p, 12, item.MTime)); p += 12; + RIF(ParseInt64(p, item.MTime)); p += 12; UInt32 checkSum; RIF(OctalToNumber32(p, 8, checkSum)); @@ -141,7 +159,36 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE item.Name = prefix + AString('/') + item.Name; if (item.LinkFlag == NFileHeader::NLinkFlag::kLink) + { + item.PackSize = 0; item.Size = 0; + } + else if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) + { + if (buf[482] != 0) + return S_FALSE; + RIF(ParseSize(buf + 483, item.Size)); + p = buf + 386; + UInt64 min = 0; + for (int i = 0; i < 4; i++, p += 24) + { + if (GetBe32(p) == 0) + break; + CSparseBlock sb; + RIF(ParseSize(p, sb.Offset)); + RIF(ParseSize(p + 12, sb.Size)); + item.SparseBlocks.Add(sb); + if (sb.Offset < min || sb.Offset > item.Size) + return S_FALSE; + if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) + return S_FALSE; + min = sb.Offset + sb.Size; + if (min < sb.Offset) + return S_FALSE; + } + if (min > item.Size) + return S_FALSE; + } UInt32 checkSumReal = 0; for (int i = 0; i < NFileHeader::kRecordSize; i++) @@ -178,26 +225,39 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AStri if (item.Name.Compare(NFileHeader::kLongLink) != 0 && item.Name.Compare(NFileHeader::kLongLink2) != 0) return S_FALSE; - if (item.Size > (1 << 14)) + if (item.PackSize > (1 << 14)) return S_FALSE; - int packSize = (int)item.GetPackSize(); + int packSize = (int)item.GetPackSizeAligned(); char *buf = name->GetBuffer(packSize); RINOK(ReadStream_FALSE(stream, buf, packSize)); item.HeaderSize += packSize; - buf[(size_t)item.Size] = '\0'; + buf[(size_t)item.PackSize] = '\0'; name->ReleaseBuffer(); continue; } - if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X') + switch (item.LinkFlag) { - // pax Extended Header + case 'g': + case 'x': + case 'X': + { + // pax Extended Header + break; + } + case NFileHeader::NLinkFlag::kDumpDir: + { + break; + // GNU Extensions to the Archive Format + } + case NFileHeader::NLinkFlag::kSparse: + { + break; + // GNU Extensions to the Archive Format + } + default: + if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) + return S_FALSE; } - 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; if (flagL) item.Name = nameL; if (flagK) item.LinkName = nameK; return S_OK; diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 859e66dd..3584a7ce 100755 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -10,15 +10,22 @@ namespace NArchive { namespace NTar { +struct CSparseBlock +{ + UInt64 Offset; + UInt64 Size; +}; + struct CItem { AString Name; + UInt64 PackSize; UInt64 Size; + Int64 MTime; UInt32 Mode; UInt32 UID; UInt32 GID; - UInt32 MTime; UInt32 DeviceMajor; UInt32 DeviceMinor; @@ -31,7 +38,10 @@ struct CItem bool DeviceMajorDefined; bool DeviceMinorDefined; + CRecordVector<CSparseBlock> SparseBlocks; + bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); } + bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; } UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; } bool IsDir() const @@ -56,15 +66,16 @@ struct CItem return true; } - UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); } + UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } }; struct CItemEx: public CItem { UInt64 HeaderPos; unsigned HeaderSize; + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } - UInt64 GetFullSize() const { return HeaderSize + Size; } + UInt64 GetFullSize() const { return HeaderSize + PackSize; } }; }} diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index e542a3b2..6e699e28 100755 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -47,7 +47,7 @@ static bool MakeOctalString8(char *s, UInt32 value) if (tempString.Length() >= kMaxSize) return false; int numSpaces = kMaxSize - (tempString.Length() + 1); - for(int i = 0; i < numSpaces; i++) + for (int i = 0; i < numSpaces; i++) s[i] = ' '; MyStringCopy(s + numSpaces, (const char *)tempString); return true; @@ -55,7 +55,7 @@ static bool MakeOctalString8(char *s, UInt32 value) static void MakeOctalString12(char *s, UInt64 value) { - AString tempString = MakeOctalString(value); + AString tempString = MakeOctalString(value); const int kMaxSize = 12; if (tempString.Length() > kMaxSize) { @@ -67,11 +67,23 @@ static void MakeOctalString12(char *s, UInt64 value) return; } int numSpaces = kMaxSize - tempString.Length(); - for(int i = 0; i < numSpaces; i++) + for (int i = 0; i < numSpaces; i++) s[i] = ' '; memmove(s + numSpaces, (const char *)tempString, tempString.Length()); } +static void MakeOctalString12_From_Int64(char *s, Int64 value) +{ + if (value >= 0) + { + MakeOctalString12(s, value); + return; + } + s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF; + for (int i = 0; i < 8; i++, value <<= 8) + s[4 + i] = (char)(value >> 56); +} + static bool CopyString(char *dest, const AString &src, int maxSize) { if (src.Length() >= maxSize) @@ -100,8 +112,8 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8; RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8; - MakeOctalString12(cur, item.Size); cur += 12; - MakeOctalString12(cur, item.MTime); cur += 12; + MakeOctalString12(cur, item.PackSize); cur += 12; + MakeOctalString12_From_Int64(cur, item.MTime); cur += 12; memmove(cur, NFileHeader::kCheckSumBlanks, 8); cur += 8; @@ -130,7 +142,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item) UInt32 checkSumReal = 0; - for(i = 0; i < NFileHeader::kRecordSize; i++) + for (i = 0; i < NFileHeader::kRecordSize; i++) checkSumReal += Byte(record[i]); RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal)); @@ -146,7 +158,7 @@ HRESULT COutArchive::WriteHeader(const CItem &item) CItem modifiedItem = item; int nameStreamSize = nameSize + 1; - modifiedItem.Size = nameStreamSize; + modifiedItem.PackSize = nameStreamSize; modifiedItem.LinkFlag = 'L'; modifiedItem.Name = NFileHeader::kLongLink; modifiedItem.LinkName.Empty(); diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index c1633218..fb123169 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -48,7 +48,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, complexity = 0; - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) { lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); @@ -64,14 +64,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; - item.Size = 0; + item.PackSize = 0; } else { item.LinkFlag = NFileHeader::NLinkFlag::kNormal; - item.Size = ui.Size; + item.PackSize = ui.Size; } - item.MTime = ui.Time; + item.MTime = ui.MTime; item.DeviceMajorDefined = false; item.DeviceMinorDefined = false; item.UID = 0; @@ -83,12 +83,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (ui.NewData) { - item.Size = ui.Size; - if (item.Size == (UInt64)(Int64)-1) + item.PackSize = ui.Size; + if (ui.Size == (UInt64)(Int64)-1) return E_INVALIDARG; } else - item.Size = inputItems[ui.IndexInArchive].Size; + item.PackSize = inputItems[ui.IndexInArchive].PackSize; if (ui.NewData) { @@ -101,9 +101,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (!ui.IsDir) { RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); - if (copyCoderSpec->TotalSize != item.Size) + if (copyCoderSpec->TotalSize != item.PackSize) return E_FAIL; - RINOK(outArchive.FillDataResidual(item.Size)); + RINOK(outArchive.FillDataResidual(item.PackSize)); } } complexity += ui.Size; @@ -117,7 +117,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, { RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); - size = existItem.Size; + size = existItem.PackSize; } else { @@ -129,10 +129,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; - RINOK(outArchive.FillDataResidual(existItem.Size)); + RINOK(outArchive.FillDataResidual(existItem.PackSize)); complexity += size; } } + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); return outArchive.WriteFinishHeader(); } diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index fb217d19..3f889739 100755 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -13,15 +13,15 @@ struct CUpdateItem { int IndexInArchive; int IndexInClient; - UInt32 Time; - UInt32 Mode; + Int64 MTime; UInt64 Size; - AString Name; - AString User; - AString Group; + UInt32 Mode; bool NewData; bool NewProps; bool IsDir; + AString Name; + AString User; + AString Group; }; HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 60d5fc2a..d2a2884f 100755 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -574,34 +574,33 @@ HRESULT CInArchive::Open2() { Clear(); + // Some UDFs contain additional pad zeros (2 KB). + // Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB. + // And when we read last block, result read size can be smaller than required size. + UInt64 fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - - // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11. - const int kSecLogSizeMax = 12; - Byte buf[1 << kSecLogSizeMax]; - Byte kSizesLog[] = { 11, 8, 12 }; - - for (int i = 0;; i++) + const size_t kBufSize = 1 << 14; + Byte buf[kBufSize]; + size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize; + RINOK(_stream->Seek(fileSize - readSize, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(_stream, buf, &readSize)); + size_t i = readSize; + for (;;) { - if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0])) - return S_FALSE; - SecLogSize = kSizesLog[i]; - Int32 bufSize = 1 << SecLogSize; - if (bufSize > fileSize) + const size_t kSecSizeMin = 1 << 8; + if (i < kSecSizeMin) return S_FALSE; - RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL)); - RINOK(ReadStream_FALSE(_stream, buf, bufSize)); + i -= kSecSizeMin; + SecLogSize = (readSize - i < ((size_t)1 << 11)) ? 8 : 11; CTag tag; - if (tag.Parse(buf, bufSize) == S_OK) + if (tag.Parse(buf + i, (1 << SecLogSize)) == S_OK) if (tag.Id == DESC_TYPE_AnchorVolPtr) break; } - if (SecLogSize == 12) - SecLogSize = 11; CExtent extentVDS; - extentVDS.Parse(buf + 16); + extentVDS.Parse(buf + i + 16); for (UInt32 location = extentVDS.Pos; ; location++) { diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp new file mode 100755 index 00000000..88739d8f --- /dev/null +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -0,0 +1,1935 @@ +// UefiHandler.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +// #include <stdio.h> + +#ifdef SHOW_DEBUG_INFO +#include <stdio.h> +#endif + +#include "../../../C/7zCrc.h" +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" +#include "../../../C/LzmaDec.h" + +#include "Common/Buffer.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/PropVariantUtils.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" + +#include "./Common/FindSignature.h" + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) +#define Get24(p) (Get32(p) & 0xFFFFFF) + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +namespace NArchive { +namespace NUefi { + +static const UInt32 kBufTotalSizeMax = (1 << 29); +static const UInt32 kNumFilesMax = (1 << 18); +static const int kLevelMax = 64; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +static const UInt32 kFvHeaderSize = 0x38; +static const UInt32 kGuidSize = 16; +static const UInt32 kCapsuleSigSize = kGuidSize; +#define CAPSULE_SIGNATURE \ + { 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 } +static const Byte kCapsuleSig[kCapsuleSigSize] = CAPSULE_SIGNATURE; + +static const UInt32 kFfsGuidOffset = 16; +#define FFS_SIGNATURE \ + { 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF } +static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE; + +static const Byte k_MacFS_Guid[kGuidSize] = + { 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A }; + +static const UInt32 kFvSignature = 0x4856465F; + +static const Byte kGuids[][kGuidSize] = +{ + { 0xB0,0xCD,0x1B,0xFC,0x31,0x7D,0xAA,0x49,0x93,0x6A,0xA4,0x60,0x0D,0x9D,0xD0,0x83 }, + { 0x2E,0x06,0xA0,0x1B,0x79,0xC7,0x82,0x45,0x85,0x66,0x33,0x6A,0xE8,0xF7,0x8F,0x09 }, + { 0x25,0x4E,0x37,0x7E,0x01,0x8E,0xEE,0x4F,0x87,0xf2,0x39,0x0C,0x23,0xC6,0x06,0xCD }, + { 0x97,0xE5,0x1B,0x16,0xC5,0xE9,0xDB,0x49,0xAE,0x50,0xC4,0x62,0xAB,0x54,0xEE,0xDA }, + { 0xDB,0x7F,0xAD,0x77,0x2A,0xDF,0x02,0x43,0x88,0x98,0xC7,0x2E,0x4C,0xDB,0xD0,0xF4 }, + { 0xAB,0x71,0xCF,0xF5,0x4B,0xB0,0x7E,0x4B,0x98,0x8A,0xD8,0xA0,0xD4,0x98,0xE6,0x92 }, + { 0x91,0x45,0x53,0x7A,0xCE,0x37,0x81,0x48,0xB3,0xC9,0x71,0x38,0x14,0xF4,0x5D,0x6B }, + { 0x84,0xE6,0x7A,0x36,0x5D,0x33,0x71,0x46,0xA1,0x6D,0x89,0x9D,0xBF,0xEA,0x6B,0x88 }, + { 0x98,0x07,0x40,0x24,0x07,0x38,0x42,0x4A,0xB4,0x13,0xA1,0xEC,0xEE,0x20,0x5D,0xD8 }, + { 0xEE,0xA2,0x3F,0x28,0x2C,0x53,0x4D,0x48,0x93,0x83,0x9F,0x93,0xB3,0x6F,0x0B,0x7E }, + { 0x9B,0xD5,0xB8,0x98,0xBA,0xE8,0xEE,0x48,0x98,0xDD,0xC2,0x95,0x39,0x2F,0x1E,0xDB }, + { 0x09,0x6D,0xE3,0xC3,0x94,0x82,0x97,0x4B,0xA8,0x57,0xD5,0x28,0x8F,0xE3,0x3E,0x28 }, + { 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 } +}; + + +static const char *kGuidNames[] = +{ + "CRC", + "VolumeTopFile", + "ACPI", + "ACPI2", + "Main", + "Intel32", + "Intel64", + "Intel32c", + "Intel64c", + "MacVolume", + "MacUpdate.txt", + "MacName", + "Insyde" +}; + +enum +{ + kGuidIndex_CRC = 0 +}; + +struct CSigExtPair +{ + const char *ext; + unsigned sigSize; + Byte sig[16]; +}; + +static const CSigExtPair g_Sigs[] = +{ + { "bmp", 2, { 'B','M' } }, + { "riff", 4, { 'R','I','F','F' } }, + { "pe", 2, { 'M','Z'} }, + { "gif", 6, { 'G','I','F','8','9', 'a' } }, + { "png", 8, { 0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A } }, + { "jpg", 10, { 0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46 } }, + { "rom", 2, { 0x55,0xAA } } +}; + +enum +{ + kSig_BMP, + kSig_RIFF, + kSig_PE +}; + +static const char *FindExt(const Byte *p, size_t size) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE(g_Sigs); i++) + { + const CSigExtPair &pair = g_Sigs[i]; + if (size >= pair.sigSize) + if (memcmp(p, pair.sig, pair.sigSize) == 0) + break; + } + if (i == ARRAY_SIZE(g_Sigs)) + return NULL; + switch (i) + { + case kSig_BMP: + if (GetUi32(p + 2) > size || GetUi32(p + 0xA) > size) + return NULL; + break; + case kSig_RIFF: + if (GetUi32(p + 8) == 0x45564157 || GetUi32(p + 0xC) == 0x20746D66 ) + return "wav"; + break; + case kSig_PE: + { + if (size < 512) + return NULL; + UInt32 peOffset = GetUi32(p + 0x3C); + if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0) + return NULL; + if (GetUi32(p + peOffset) != 0x00004550) + return NULL; + break; + } + } + return g_Sigs[i].ext; +} + +static bool AreGuidsEq(const Byte *p1, const Byte *p2) +{ + return memcmp(p1, p2, kGuidSize) == 0; +} + +static int FindGuid(const Byte *p) +{ + for (int i = 0; i < ARRAY_SIZE(kGuids); i++) + if (AreGuidsEq(p, kGuids[i])) + return i; + return -1; +} + +static bool IsFfs(const Byte *p) +{ + return (Get32(p + 0x28) == kFvSignature && AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid)); +} + +#define FVB_ERASE_POLARITY (1 << 11) + +/* +static const CUInt32PCharPair g_FV_Attribs[] = +{ + { 0, "ReadDisabledCap" }, + { 1, "ReadEnabledCap" }, + { 2, "ReadEnabled" }, + { 3, "WriteDisabledCap" }, + { 4, "WriteEnabledCap" }, + { 5, "WriteEnabled" }, + { 6, "LockCap" }, + { 7, "Locked" }, + + { 9, "StickyWrite" }, + { 10, "MemoryMapped" }, + { 11, "ErasePolarity" }, + + { 12, "ReadLockCap" }, + { 13, "WriteLockCap" }, + { 14, "WriteLockCap" } +}; +*/ + +enum +{ + FV_FILETYPE_ALL, + FV_FILETYPE_RAW, + FV_FILETYPE_FREEFORM, + FV_FILETYPE_SECURITY_CORE, + FV_FILETYPE_PEI_CORE, + FV_FILETYPE_DXE_CORE, + FV_FILETYPE_PEIM, + FV_FILETYPE_DRIVER, + FV_FILETYPE_COMBINED_PEIM_DRIVER, + FV_FILETYPE_APPLICATION, + // The value 0x0A is reserved and should not be used + FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B, + // types 0xF0 - 0xFF are FFS file types + FV_FILETYPE_FFS_PAD = 0xF0 +}; + +static const char *g_FileTypes[] = +{ + "ALL", + "RAW", + "FREEFORM", + "SECURITY_CORE", + "PEI_CORE", + "DXE_CORE", + "PEIM", + "DRIVER", + "COMBINED_PEIM_DRIVER", + "APPLICATION", + "0xA", + "VOLUME" +}; + +// typedef Byte FFS_FILE_ATTRIBUTES; +// FFS File Attributes +#define FFS_ATTRIB_TAIL_PRESENT 0x01 +// #define FFS_ATTRIB_RECOVERY 0x02 +// #define FFS_ATTRIB_HEADER_EXTENSION 0x04 +// #define FFS_ATTRIB_DATA_ALIGNMENT 0x38 +#define FFS_ATTRIB_CHECKSUM 0x40 + +static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] = +{ + { 0, "" /* "TAIL" */ }, + { 1, "RECOVERY" }, + // { 2, "HEADER_EXTENSION" }, // reserved for future + { 6, "" /* "CHECKSUM" */ } +}; + +// static const Byte g_Allignment[8] = { 3, 4, 7, 9, 10, 12, 15, 16 }; + +// typedef Byte FFS_FILE_STATE; + +// Look also FVB_ERASE_POLARITY. +// Lower-order State bits are superceded by higher-order State bits. + +// #define FILE_HEADER_CONSTRUCTION 0x01 +// #define FILE_HEADER_VALID 0x02 +#define FILE_DATA_VALID 0x04 +// #define FILE_MARKED_FOR_UPDATE 0x08 +// #define FILE_DELETED 0x10 +// #define FILE_HEADER_INVALID 0x20 + +// SECTION_TYPE + +#define SECTION_ALL 0x00 + +#define SECTION_COMPRESSION 0x01 +#define SECTION_GUID_DEFINED 0x02 + +// Leaf section Type values +#define SECTION_PE32 0x10 +#define SECTION_PIC 0x11 +#define SECTION_TE 0x12 +#define SECTION_DXE_DEPEX 0x13 +#define SECTION_VERSION 0x14 +#define SECTION_USER_INTERFACE 0x15 +#define SECTION_COMPATIBILITY16 0x16 +#define SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define SECTION_RAW 0x19 +#define SECTION_PEI_DEPEX 0x1B + + +// #define GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +// #define GUIDED_SECTION_AUTH_STATUS_VALID 0x02 + +static const CUInt32PCharPair g_GUIDED_SECTION_ATTRIBUTES[] = +{ + { 0, "PROCESSING_REQUIRED" }, + { 1, "AUTH" } +}; + +static const CUInt32PCharPair g_SECTION_TYPE[] = +{ + { 0x01, "COMPRESSION" }, + { 0x02, "GUID" }, + { 0x10, "efi" }, + { 0x11, "PIC" }, + { 0x12, "te" }, + { 0x13, "DXE_DEPEX" }, + { 0x14, "VERSION" }, + { 0x15, "USER_INTERFACE" }, + { 0x16, "COMPATIBILITY16" }, + { 0x17, "VOLUME" }, + { 0x18, "FREEFORM_SUBTYPE_GUID" }, + { 0x19, "raw" }, + { 0x1B, "PEI_DEPEX" } +}; + +#define COMPRESSION_TYPE_NONE 0 +#define COMPRESSION_TYPE_LZH 1 +#define COMPRESSION_TYPE_LZMA 2 + +static const char *g_Methods[] = +{ + "COPY", + "LZH", + "LZMA" +}; + +static AString UInt32ToString(UInt32 val) +{ + char sz[16]; + ConvertUInt32ToString(val, sz); + return sz; +} + +static void ConvertByteToHex(unsigned value, char *s) +{ + for (int i = 0; i < 2; i++) + { + unsigned t = value & 0xF; + value >>= 4; + s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } +} + +static AString GuidToString(const Byte *p, bool full) +{ + char s[16 * 2 + 8]; + int i; + for (i = 0; i < 4; i++) + ConvertByteToHex(p[3 - i], s + i * 2); + s[8] = 0; + + if (full) + { + s[8] = '-'; + for (i = 4; i < kGuidSize; i++) + ConvertByteToHex(p[i], s + 1 + i * 2); + s[32 + 1] = 0; + } + return s; +} + +static const char *kExpressionCommands[] = +{ + "BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR" +}; + +static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res) +{ + res.Empty(); + for (UInt32 i = 0; i < size;) + { + unsigned command = p[i++]; + if (command > ARRAY_SIZE(kExpressionCommands)) + return false; + res += kExpressionCommands[command]; + if (command < 3) + { + if (i + kGuidSize > size) + return false; + res += " "; + res += GuidToString(p + i, false); + i += kGuidSize; + } + res += "; "; + } + return true; +} + +static bool ParseUtf16zString(const Byte *p, UInt32 size, UString &res) +{ + if ((size & 1) != 0) + return false; + res.Empty(); + UInt32 i; + for (i = 0; i < size; i += 2) + { + wchar_t c = Get16(p + i); + if (c == 0) + break; + res += c; + } + return (i == size - 2); +} + +static bool ParseUtf16zString2(const Byte *p, UInt32 size, AString &res) +{ + UString s; + if (!ParseUtf16zString(p, size, s)) + return false; + res = UnicodeStringToMultiByte(s); + return true; +} + +#define FLAGS_TO_STRING(pairs, value) FlagsToString(pairs, ARRAY_SIZE(pairs), value) +#define TYPE_TO_STRING(table, value) TypeToString(table, ARRAY_SIZE(table), value) +#define TYPE_PAIR_TO_STRING(table, value) TypePairToString(table, ARRAY_SIZE(table), value) + +static const UInt32 kFileHeaderSize = 24; + +static void AddSpaceAndString(AString &res, const AString &newString) +{ + if (!res.IsEmpty() && !newString.IsEmpty()) + res += ' '; + res += newString; +} + +class CFfsFileHeader +{ + Byte CheckHeader; + Byte CheckFile; + Byte Attrib; + Byte State; + + UInt16 GetTailReference() const { return CheckHeader | ((UInt16)CheckFile << 8); } + UInt32 GetTailSize() const { return IsThereTail() ? 2 : 0; } + bool IsThereFileChecksum() const { return (Attrib & FFS_ATTRIB_CHECKSUM) != 0; } + bool IsThereTail() const { return (Attrib & FFS_ATTRIB_TAIL_PRESENT) != 0; } +public: + Byte GuidName[kGuidSize]; + Byte Type; + UInt32 Size; + + bool Parse(const Byte *p) + { + int i; + for (i = 0; i < kFileHeaderSize; i++) + if (p[i] != 0xFF) + break; + if (i == kFileHeaderSize) + return false; + memcpy(GuidName, p, kGuidSize); + CheckHeader = p[0x10]; + CheckFile = p[0x11]; + Type = p[0x12]; + Attrib = p[0x13]; + Size = Get24(p + 0x14); + State = p[0x17]; + return true; + } + + UInt32 GetDataSize() const { return Size - kFileHeaderSize - GetTailSize(); } + + bool Check(const Byte *p, UInt32 size) + { + if (Size > size) + return false; + UInt32 tailSize = GetTailSize(); + if (Size < kFileHeaderSize + tailSize) + return false; + + { + unsigned checkSum = 0; + for (UInt32 i = 0; i < kFileHeaderSize; i++) + checkSum += p[i]; + checkSum -= p[0x17]; + checkSum -= p[0x11]; + if ((Byte)checkSum != 0) + return false; + } + + if (IsThereFileChecksum()) + { + unsigned checkSum = 0; + UInt32 checkSize = Size - tailSize; + for (UInt32 i = 0; i < checkSize; i++) + checkSum += p[i]; + checkSum -= p[0x17]; + if ((Byte)checkSum != 0) + return false; + } + + if (IsThereTail()) + if (GetTailReference() != (UInt16)~Get16(p + Size - 2)) + return false; + + int polarity = 0; + int i; + for (i = 5; i >= 0; i--) + if (((State >> i) & 1) == polarity) + { + // AddSpaceAndString(s, g_FFS_FILE_STATE_Flags[i]); + if ((1 << i) != FILE_DATA_VALID) + return false; + break; + } + if (i < 0) + return false; + + return true; + } + + AString GetCharacts() const + { + AString s; + if (Type == FV_FILETYPE_FFS_PAD) + s += "PAD"; + else + s += TYPE_TO_STRING(g_FileTypes, Type); + AddSpaceAndString(s, FLAGS_TO_STRING(g_FFS_FILE_ATTRIBUTES, Attrib & 0xC7)); + /* + int align = (Attrib >> 3) & 7; + if (align != 0) + { + s += " Align:"; + s += UInt32ToString((UInt32)1 << g_Allignment[align]); + } + */ + return s; + } +}; + +#define GET_32(offs, dest) dest = Get32(p + (offs)); +#define GET_64(offs, dest) dest = Get64(p + (offs)); + +struct CCapsuleHeader +{ + UInt32 HeaderSize; + UInt32 Flags; + UInt32 CapsuleImageSize; + UInt32 SequenceNumber; + // Guid InstanceId; + UInt32 OffsetToSplitInformation; + UInt32 OffsetToCapsuleBody; + UInt32 OffsetToOemDefinedHeader; + UInt32 OffsetToAuthorInformation; + UInt32 OffsetToRevisionInformation; + UInt32 OffsetToShortDescription; + UInt32 OffsetToLongDescription; + UInt32 OffsetToApplicableDevices; + + void Clear() { memset(this, 0, sizeof(this)); } + + void Parse(const Byte *p) + { + GET_32(0x10, HeaderSize); + GET_32(0x14, Flags); + GET_32(0x18, CapsuleImageSize); + GET_32(0x1C, SequenceNumber); + GET_32(0x30, OffsetToSplitInformation); + GET_32(0x34, OffsetToCapsuleBody); + GET_32(0x38, OffsetToOemDefinedHeader); + GET_32(0x3C, OffsetToAuthorInformation); + GET_32(0x40, OffsetToRevisionInformation); + GET_32(0x44, OffsetToShortDescription); + GET_32(0x48, OffsetToLongDescription); + GET_32(0x4C, OffsetToApplicableDevices); + } +}; + +struct CItem +{ + AString Name; + AString Characts; + int Parent; + int Method; + int NameIndex; + int NumChilds; + bool IsDir; + bool Skip; + bool ThereAreSubDirs; + bool ThereIsUniqueName; + bool KeepName; + + int BufIndex; + UInt32 Offset; + UInt32 Size; + + CItem(): Parent(-1), Method(-1), NameIndex(-1), NumChilds(0), + IsDir(false), Skip(false), ThereAreSubDirs(false), ThereIsUniqueName(false), KeepName(true) {} + void SetGuid(const Byte *guidName, bool full = false); + AString GetName(int numChildsInParent) const; +}; + +void CItem::SetGuid(const Byte *guidName, bool full) +{ + ThereIsUniqueName = true; + int index = FindGuid(guidName); + if (index >= 0) + Name = kGuidNames[index]; + else + Name = GuidToString(guidName, full); +} + +AString CItem::GetName(int numChildsInParent) const +{ + if (numChildsInParent <= 1 || NameIndex < 0) + return Name; + char sz[32]; + char sz2[32]; + ConvertUInt32ToString(NameIndex, sz); + ConvertUInt32ToString(numChildsInParent - 1, sz2); + int numZeros = (int)strlen(sz2) - (int)strlen(sz); + AString res; + for (int i = 0; i < numZeros; i++) + res += '0'; + return res + (AString)sz + '.' + Name; +} + +struct CItem2 +{ + AString Name; + AString Characts; + int MainIndex; + int Parent; + + CItem2(): Parent(-1) {} +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector<CItem> _items; + CObjectVector<CItem2> _items2; + CObjectVector<CByteBuffer> _bufs; + UString _comment; + UInt32 _methodsMask; + bool _capsuleMode; + + UInt32 _totalBufsSize; + CCapsuleHeader _h; + + void AddCommentString(const wchar_t *name, UInt32 pos); + int AddItem(const CItem &item); + int AddFileItemWithIndex(CItem &item); + int AddDirItem(CItem &item); + int AddBuf(UInt32 size); + + HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level); + HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level); + HRESULT OpenCapsule(IInStream *stream); + HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); + HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); +public: + CHandler(bool capsuleMode): _capsuleMode(capsuleMode) {} + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +static const STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidCharacts, VT_BSTR} +}; + +static const STATPROPSTG kArcProps[] = +{ + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidPhySize, VT_UI8}, + { NULL, kpidCharacts, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem2 &item2 = _items2[index]; + const CItem &item = _items[item2.MainIndex]; + switch(propID) + { + case kpidPath: + { + AString path = item2.Name; + int cur = item2.Parent; + while (cur >= 0) + { + const CItem2 &item2 = _items2[cur]; + path = item2.Name + CHAR_PATH_SEPARATOR + path; + cur = item2.Parent; + } + prop = path; + break; + } + case kpidIsDir: prop = item.IsDir; break; + case kpidMethod: if (item.Method >= 0) prop = g_Methods[item.Method]; break; + case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break; + case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +void CHandler::AddCommentString(const wchar_t *name, UInt32 pos) +{ + UString s; + const Byte *buf = _bufs[0]; + if (pos < _h.HeaderSize) + return; + for (UInt32 i = pos;; i += 2) + { + if (s.Length() > (1 << 16) || i >= _h.OffsetToCapsuleBody) + return; + wchar_t c = Get16(buf + i); + if (c == 0) + { + i += 2; + if (i >= _h.OffsetToCapsuleBody) + return; + c = Get16(buf + i); + if (c == 0) + break; + s += L'\n'; + } + s += c; + } + if (s.IsEmpty()) + return; + _comment += L'\n'; + _comment += name; + _comment += L": "; + _comment += s; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: + { + AString s; + for (int i = 0; i < 32; i++) + if ((_methodsMask & ((UInt32)1 << i)) != 0) + AddSpaceAndString(s, g_Methods[i]); + if (!s.IsEmpty()) + prop = s; + break; + } + case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break; + case kpidPhySize: prop = (UInt64)_h.CapsuleImageSize; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +#ifdef SHOW_DEBUG_INFO +static void PrintLevel(int level) +{ + PRF(printf("\n")); + for (int i = 0; i < level; i++) + PRF(printf(" ")); +} +static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name) +{ + PrintLevel(level); + PRF(printf("%s, pos = %6x, size = %6d", name, posBase, size)); +} +#else +#define PrintLevel(level) +#define MyPrint(posBase, size, level, name) +#endif + +static const unsigned kNumBigValueBits = 8 * 4; +static const unsigned kNumValueBytes = 3; +static const unsigned kNumValueBits = 8 * kNumValueBytes; +static const UInt32 kMask = (1 << kNumValueBits) - 1; + +class CBitmMemDecoder +{ + unsigned _bitPos; + UInt32 _value; + const Byte *_buf; + size_t _pos; + size_t _size; + size_t _extra; +public: + void Init(const Byte *buf, size_t size) + { + _buf = buf; + _size = size; + _pos = 0; + _extra = 0; + _bitPos = kNumBigValueBits; + Normalize(); + } + + bool IsFullFinished() const { return (_extra * 8) == (kNumBigValueBits - _bitPos); } + + void Normalize() + { + for (; _bitPos >= 8; _bitPos -= 8) + { + Byte b; + if (_pos < _size) + b = _buf[_pos++]; + else + { + b = 0; + _extra++; + } + _value = (_value << 8) | b; + } + } + + UInt32 GetValue(unsigned numBits) const + { + return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits); + } + + void MovePos(unsigned numBits) + { + _bitPos += numBits; + Normalize(); + } + + UInt32 ReadBitsFast(unsigned numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } + + UInt32 ReadBits(unsigned numBits); + UInt32 ReadAlignBits() { return ReadBits((32 - _bitPos) & 7); } +}; + +UInt32 CBitmMemDecoder::ReadBits(unsigned numBits) +{ + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; +} + +namespace NHuffman { + +static const int kNumTableBits = 9; +static const int kNumBitsMax = 16; + +class CDecoder +{ + UInt32 m_Limits[kNumBitsMax + 1]; + UInt32 m_Positions[kNumBitsMax + 1]; + Byte m_Lengths[1 << kNumTableBits]; + Int32 m_MainSymbol; + +public: + UInt32 *m_Symbols; + UInt32 m_NumSymbols; + + void SetSingleSymbolMode(UInt32 symbol) { m_MainSymbol = symbol; } + bool SetCodeLengths(const Byte *codeLengths); + UInt32 DecodeSymbol(CBitmMemDecoder *bitStream) + { + if (m_MainSymbol != -1) + return (UInt32)m_MainSymbol; + int numBits; + UInt32 value = bitStream->GetValue(kNumBitsMax); + if (value < m_Limits[kNumTableBits]) + numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; + else + for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++); + bitStream->MovePos(numBits); + return m_Symbols[m_Positions[numBits] + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits))]; + } +}; + +bool CDecoder::SetCodeLengths(const Byte *codeLengths) +{ + m_MainSymbol = -1; + int lenCounts[kNumBitsMax + 1]; + UInt32 tmpPositions[kNumBitsMax + 1]; + int i; + for (i = 1; i <= kNumBitsMax; i++) + lenCounts[i] = 0; + UInt32 symbol; + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len > kNumBitsMax) + return false; + lenCounts[len]++; + m_Symbols[symbol] = 0xFFFFFFFF; + } + lenCounts[0] = 0; + m_Positions[0] = m_Limits[0] = 0; + UInt32 startPos = 0; + UInt32 index = 0; + const UInt32 kMaxValue = (1 << kNumBitsMax); + for (i = 1; i <= kNumBitsMax; i++) + { + startPos += lenCounts[i] << (kNumBitsMax - i); + if (startPos > kMaxValue) + return false; + m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos; + m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1]; + tmpPositions[i] = m_Positions[i]; + if (i <= kNumTableBits) + { + UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits)); + for (; index < limit; index++) + m_Lengths[index] = (Byte)i; + } + } + if (startPos != kMaxValue) + return false; + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len != 0) + m_Symbols[tmpPositions[len]++] = symbol; + } + return true; +} + +} + +static const int kMaxHuffmanLen = 16; +static const int kExtraSize = kMaxHuffmanLen + 3; +static const int kMinMatchLen = 3; +static const int kMaxMatchLen = 256; +static const int kNumAlphaSymsMax = 256 + kMaxMatchLen - kMinMatchLen + 1; +static const int kNumDistSymsMax = 24 + 2; // it's limited by bit decoder. + +#define HUFF_START_CODE(huff, numSymsMax, numSymBits) \ + UInt32 numSyms = bitDec.ReadBits(numSymBits); \ + Byte lens[numSymsMax]; memset(lens, 0, sizeof(lens)); \ + if (numSyms > (numSymsMax)) return S_FALSE; \ + huff.m_NumSymbols = numSyms; \ + if (numSyms == 0) { \ + numSyms = bitDec.ReadBits(numSymBits); \ + if (numSyms >= (numSymsMax)) return S_FALSE; \ + huff.SetSingleSymbolMode(numSyms); } \ + +static HRESULT LzhDecode(Byte *dest, UInt32 destSize, const Byte *src, UInt32 srcSize) +{ + if (srcSize < 8) + return S_FALSE; + { + UInt32 packSize = Get32(src); + UInt32 unpackSize = Get32(src + 4); + src += 8; + srcSize -= 8; + if (destSize != unpackSize || srcSize != packSize) + return S_FALSE; + } + + CBitmMemDecoder bitDec; + bitDec.Init(src, srcSize); + + UInt32 pos = 0; + for (;;) + { + UInt32 blockSize = bitDec.ReadBits(16); + UInt32 symbols[kExtraSize + kNumAlphaSymsMax + kNumDistSymsMax]; + + NHuffman::CDecoder extraHuff; + extraHuff.m_Symbols = symbols; + { + HUFF_START_CODE(extraHuff, kExtraSize, 5) + else + { + for (UInt32 i = 0; i < numSyms; i++) + { + if (i == 3) + { + UInt32 numZeros = bitDec.ReadBits(2); + if (i + numZeros > numSyms) + return S_FALSE; + for (UInt32 j = 0; j < numZeros; j++, i++) + lens[i] = (Byte)0; + if (i == numSyms) + break; + } + + UInt32 len = bitDec.ReadBits(3); + if (len == 7) + { + for(;; len++) + { + if (len > kMaxHuffmanLen) + return S_FALSE; + if (bitDec.ReadBits(1) == 0) + break; + } + } + lens[i] = (Byte)len; + } + if (!extraHuff.SetCodeLengths(lens)) + return S_FALSE; + } + } + + NHuffman::CDecoder symHuff; + symHuff.m_Symbols = symbols + kExtraSize; + { + HUFF_START_CODE(symHuff, kNumAlphaSymsMax, 9) + else + { + for (UInt32 i = 0; i < numSyms;) + { + UInt32 c = extraHuff.DecodeSymbol(&bitDec); + if (c > 2) + lens[i++] = (Byte)c - 2; + else + { + UInt32 numZeros; + if (c == 0) + numZeros = 1; + else if (c == 1) + numZeros = bitDec.ReadBits(4) + 3; + else + numZeros = bitDec.ReadBits(9) + 20; + if (i + numZeros > numSyms) + return S_FALSE; + for (UInt32 j = 0; j < numZeros; j++, i++) + lens[i] = (Byte)0; + } + } + if (!symHuff.SetCodeLengths(lens)) + return S_FALSE; + } + } + + NHuffman::CDecoder distHuff; + distHuff.m_Symbols = symbols + kExtraSize + kNumAlphaSymsMax; + { + const UInt32 version = 1; + const UInt32 numDistBits = version + 4; + HUFF_START_CODE(distHuff, kNumDistSymsMax, numDistBits) + else + { + for (UInt32 i = 0; i < numSyms; i++) + { + UInt32 len = bitDec.ReadBits(3); + if (len == 7) + { + for(;; len++) + { + if (len > kMaxHuffmanLen) + return S_FALSE; + if (bitDec.ReadBits(1) == 0) + break; + } + } + lens[i] = (Byte)len; + } + if (!distHuff.SetCodeLengths(lens)) + return S_FALSE; + } + } + + while (blockSize) + { + blockSize--; + UInt32 c = symHuff.DecodeSymbol(&bitDec); + if (c < 256) + { + if (destSize == 0) + return S_FALSE; + *dest++ = (Byte)c; + destSize--; + pos++; + continue; + } + c = c - 256 + kMinMatchLen; + if (destSize < c) + return S_FALSE; + UInt32 dist = distHuff.DecodeSymbol(&bitDec); + if (dist > 1) + dist = ((UInt32)1 << (dist - 1)) + bitDec.ReadBits(dist - 1); + dist++; + if (dist > pos) + return S_FALSE; + pos += c; + destSize -= c; + do + { + *dest = dest[0 - (Int32)dist]; + dest++; + } + while (--c); + } + + // PRF(printf("\ndestSize = %6d", destSize)); + if (destSize == 0) + { + if (bitDec.ReadAlignBits() != 0) + return S_FALSE; + if (bitDec.ReadBits(8) != 0) + return S_FALSE; + if (!bitDec.IsFullFinished()) + return S_FALSE; + break; + } + } + return S_OK; +} + +int CHandler::AddItem(const CItem &item) +{ + if (_items.Size() >= kNumFilesMax) + throw 2; + return _items.Add(item); +} + +int CHandler::AddFileItemWithIndex(CItem &item) +{ + int nameIndex = _items.Size(); + if (item.Parent >= 0) + nameIndex = _items[item.Parent].NumChilds++; + item.NameIndex = nameIndex; + return AddItem(item); +} + +int CHandler::AddDirItem(CItem &item) +{ + if (item.Parent >= 0) + _items[item.Parent].ThereAreSubDirs = true; + item.IsDir = true; + item.Size = 0; + return AddItem(item); +} + +int CHandler::AddBuf(UInt32 size) +{ + if (size > kBufTotalSizeMax - _totalBufsSize) + throw 1; + _totalBufsSize += size; + int index = _bufs.Add(CByteBuffer()); + _bufs[index].SetCapacity(size); + return index; +} + +HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level) +{ + if (level > kLevelMax) + return S_FALSE; + MyPrint(posBase, size, level, "Sections"); + level++; + const Byte *bufData = _bufs[bufIndex]; + UInt32 pos = 0; + for (;;) + { + if (size == pos) + return S_OK; + PrintLevel(level); + PRF(printf("%s, pos = %6x", "Sect", pos)); + pos = (pos + 3) & ~(UInt32)3; + if (pos > size) + return S_FALSE; + UInt32 rem = size - pos; + if (rem == 0) + return S_OK; + if (rem < 4) + return S_FALSE; + const Byte *p = bufData + posBase + pos; + UInt32 sectSize = Get24(p); + if (sectSize > rem || sectSize < 4) + return S_FALSE; + + Byte type = p[3]; + PrintLevel(level); + PRF(printf("%s, type = %2x, pos = %6x, size = %6d", "Sect", type, pos, sectSize)); + CItem item; + item.Method = method; + item.BufIndex = bufIndex; + item.Parent = parent; + item.Offset = posBase + pos + 4; + UInt32 sectDataSize = sectSize - 4; + item.Size = sectDataSize; + item.Name = TYPE_PAIR_TO_STRING(g_SECTION_TYPE, type); + + if (type == SECTION_COMPRESSION) + { + if (sectSize < 4 + 5) + return S_FALSE; + UInt32 uncompressedSize = Get32(p + 4); + Byte compressionType = p[8]; + + UInt32 newSectSize = sectSize - 9; + UInt32 newOffset = posBase + pos + 9; + const Byte *pStart = p + 9; + + item.KeepName = false; + if (compressionType > 2) + { + // AddFileItemWithIndex(item); + return S_FALSE; + } + else + { + item.Name = g_Methods[compressionType]; + // int parent = AddDirItem(item); + if (compressionType == COMPRESSION_TYPE_NONE) + { + RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level)); + } + else if (compressionType == COMPRESSION_TYPE_LZH) + { + int newBufIndex = AddBuf(uncompressedSize); + CByteBuffer &buf = _bufs[newBufIndex]; + RINOK(LzhDecode(buf, uncompressedSize, pStart, newSectSize)); + RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level)); + } + else + { + if (newSectSize < 4 + 5 + 8) + return S_FALSE; + unsigned addSize = 4; + if (pStart[0] == 0x5d && pStart[1] == 0 && pStart[2] == 0 && pStart[3] == 0x80 && pStart[4] == 0) + { + addSize = 0; + // some archives have such header + } + else + { + // normal BIOS contains uncompressed size here + // UInt32 uncompressedSize2 = Get24(pStart); + // Byte firstSectType = p[9 + 3]; + // firstSectType can be 0 in some archives + } + pStart += addSize; + UInt64 lzmaUncompressedSize = Get64(pStart + 5); + if (lzmaUncompressedSize > (1 << 30)) + return S_FALSE; + if (lzmaUncompressedSize < uncompressedSize) + return S_FALSE; + SizeT destLen = (SizeT)lzmaUncompressedSize; + int newBufIndex = AddBuf((UInt32)lzmaUncompressedSize); + CByteBuffer &buf = _bufs[newBufIndex]; + ELzmaStatus status; + SizeT srcLen = newSectSize - (addSize + 5 + 8); + SizeT srcLen2 = srcLen; + SRes res = LzmaDecode(buf, &destLen, pStart + 13, &srcLen, + pStart, 5, LZMA_FINISH_END, &status, &g_Alloc); + if (res != 0) + return S_FALSE; + if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + return S_FALSE; + RINOK(ParseSections(newBufIndex, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level)); + } + _methodsMask |= (1 << compressionType); + } + } + else if (type == SECTION_GUID_DEFINED) + { + const UInt32 kHeaderSize = 4 + kGuidSize + 4; + if (sectSize < kHeaderSize) + return S_FALSE; + item.SetGuid(p + 4); + UInt32 dataOffset = Get16(p + 4 + kGuidSize); + UInt32 attrib = Get16(p + 4 + kGuidSize + 2); + if (dataOffset > sectSize || dataOffset < kHeaderSize) + return S_FALSE; + UInt32 newSectSize = sectSize - dataOffset; + item.Size = newSectSize; + UInt32 newOffset = posBase + pos + dataOffset; + item.Offset = newOffset; + UInt32 propsSize = dataOffset - kHeaderSize; + bool needDir = true; + AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib)); + if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4) + { + needDir = false; + item.KeepName = false; + if (CrcCalc(bufData + newOffset, newSectSize) != Get32(p + kHeaderSize)) + return S_FALSE; + } + else + { + if (propsSize != 0) + { + CItem item2 = item; + item2.Name += ".prop"; + item2.Size = propsSize; + item2.Offset = posBase + pos + kHeaderSize; + AddItem(item2); + } + } + int newParent = parent; + if (needDir) + newParent = AddDirItem(item); + RINOK(ParseSections(bufIndex, newOffset, newSectSize, newParent, method, level)); + } + else if (type == SECTION_FIRMWARE_VOLUME_IMAGE) + { + item.KeepName = false; + int newParent = AddDirItem(item); + RINOK(ParseVolume(bufIndex, posBase + pos + 4, sectSize - 4, newParent, method, level)); + } + else + { + bool needAdd = true; + switch(type) + { + case SECTION_RAW: + { + const UInt32 kInsydeOffset = 12; + if (sectDataSize >= kFvHeaderSize + kInsydeOffset) + { + if (IsFfs(p + 4 + kInsydeOffset) && + sectDataSize - kInsydeOffset == Get64(p + 4 + kInsydeOffset + 0x20)) + { + needAdd = false; + item.Name = "vol"; + int newParent = AddDirItem(item); + RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset, sectDataSize - kInsydeOffset, newParent, method, level)); + } + + if (needAdd) + { + const char *ext = FindExt(p + 4, sectDataSize); + if (ext) + item.Name = ext; + } + } + break; + } + case SECTION_DXE_DEPEX: + case SECTION_PEI_DEPEX: + { + AString s; + if (ParseDepedencyExpression(p + 4, sectDataSize, s)) + { + if (s.Length() < (1 << 9)) + { + s = '[' + s + ']'; + AddSpaceAndString(_items[item.Parent].Characts, s); + needAdd = false; + } + else + { + item.BufIndex = AddBuf(s.Length()); + CByteBuffer &buf0 = _bufs[item.BufIndex]; + memcpy(buf0, s, s.Length()); + item.Offset = 0; + item.Size = s.Length(); + } + } + break; + } + case SECTION_VERSION: + { + if (sectDataSize > 2) + { + AString s; + if (ParseUtf16zString2(p + 6, sectDataSize - 2, s)) + { + AddSpaceAndString(_items[item.Parent].Characts, (AString)"ver:" + UInt32ToString(Get16(p + 4)) + ' ' + s); + needAdd = false; + } + } + break; + } + case SECTION_USER_INTERFACE: + { + AString s; + if (ParseUtf16zString2(p + 4, sectDataSize, s)) + { + _items[parent].Name = s; + needAdd = false; + } + break; + } + case SECTION_FREEFORM_SUBTYPE_GUID: + { + if (sectDataSize >= kGuidSize) + { + item.SetGuid(p + 4); + item.Size = sectDataSize - kGuidSize; + item.Offset = posBase + pos + 4 + kGuidSize; + } + break; + } + } + + if (needAdd) + AddFileItemWithIndex(item); + } + pos += sectSize; + } +} + +static UInt32 Count_FF_Bytes(const Byte *p, UInt32 size) +{ + UInt32 i; + for (i = 0; i < size && p[i] == 0xFF; i++); + return i; +} + +static bool Is_FF_Stream(const Byte *p, UInt32 size) +{ + return (Count_FF_Bytes(p, size) == size); +} + +HRESULT CHandler::ParseVolume(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level) +{ + if (level > kLevelMax) + return S_FALSE; + MyPrint(posBase, size, level, "Volume"); + level++; + if (size < kFvHeaderSize) + return S_FALSE; + const Byte *p = _bufs[bufIndex] + posBase; + // first 16 bytes must be zeros, but they are not zeros sometimes. + if (!AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid) && + !AreGuidsEq(p + kFfsGuidOffset, k_MacFS_Guid)) + { + CItem item; + item.Method = method; + item.BufIndex = bufIndex; + item.Parent = parent; + item.Offset = posBase; + item.Size = size; + item.SetGuid(p + kFfsGuidOffset); + item.Name += " [VOLUME]"; + AddItem(item); + return S_OK; + } + + if (Get32(p + 0x28) != kFvSignature) + return S_FALSE; + UInt32 attribs = Get32(p + 0x2C); + if ((attribs & FVB_ERASE_POLARITY) == 0) + return S_FALSE; + // if (parent >= 0) AddSpaceAndString(_items[parent].Characts, FLAGS_TO_STRING(g_FV_Attribs, attribs)); + UInt64 fvLen = Get64(p + 0x20); + UInt32 headerLen = Get16(p + 0x30); + if (headerLen > size || headerLen < kFvHeaderSize || (headerLen & 0x7) != 0 || + fvLen > size || fvLen < headerLen) + return S_FALSE; + + { + UInt32 checkCalc = 0; + for (UInt32 i = 0; i < headerLen; i += 2) + checkCalc += Get16(p + i); + if ((checkCalc & 0xFFFF) != 0) + return S_FALSE; + } + + // 3 reserved bytes are not zeros sometimes. + // UInt16 ExtHeaderOffset; // in new SPECIFICATION? + // Byte revision = p[0x37]; + + UInt32 pos = kFvHeaderSize; + for (;;) + { + if (pos >= headerLen) + return S_FALSE; + UInt32 numBlocks = Get32(p + pos); + UInt32 length = Get32(p + pos + 4); + pos += 8; + if (numBlocks == 0 && length == 0) + break; + } + if (pos != headerLen) + return S_FALSE; + + CRecordVector<UInt32> guidsVector; + + for (;;) + { + UInt32 rem = (UInt32)fvLen - pos; + if (rem < kFileHeaderSize) + break; + pos = (pos + 7) & ~7; + rem = (UInt32)fvLen - pos; + if (rem < kFileHeaderSize) + break; + + CItem item; + item.Method = method; + item.BufIndex = bufIndex; + item.Parent = parent; + + const Byte *pFile = p + pos; + CFfsFileHeader fh; + if (!fh.Parse(pFile)) + { + UInt32 num_FF_bytes = Count_FF_Bytes(pFile, rem); + if (num_FF_bytes != rem) + { + item.Name = "[junk]"; + item.Offset = posBase + pos + num_FF_bytes; + item.Size = rem - num_FF_bytes; + AddItem(item); + } + break; + } + PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6d", "FILE", posBase + pos, fh.Size)); + if (!fh.Check(pFile, rem)) + return S_FALSE; + + UInt32 offset = posBase + pos + kFileHeaderSize; + UInt32 sectSize = fh.GetDataSize(); + item.Offset = offset; + item.Size = sectSize; + + pos += fh.Size; + + if (fh.Type == FV_FILETYPE_FFS_PAD) + if (Is_FF_Stream(pFile + kFileHeaderSize, sectSize)) + continue; + + UInt32 guid32 = Get32(fh.GuidName); + bool full = true; + if (guidsVector.FindInSorted(guid32) < 0) + { + guidsVector.AddToUniqueSorted(guid32); + full = false; + } + item.SetGuid(fh.GuidName, full); + + item.Characts = fh.GetCharacts(); + PrintLevel(level); + PRF(printf("%s", item.Characts)); + + if (fh.Type == FV_FILETYPE_FFS_PAD || + fh.Type == FV_FILETYPE_RAW) + { + bool isVolume = false; + if (fh.Type == FV_FILETYPE_RAW) + { + if (sectSize >= kFvHeaderSize) + if (IsFfs(pFile + kFileHeaderSize)) + isVolume = true; + } + if (isVolume) + { + int newParent = AddDirItem(item); + RINOK(ParseVolume(bufIndex, offset, sectSize, newParent, method, level)); + } + else + AddItem(item); + } + else + { + int newParent = AddDirItem(item); + RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level)); + } + } + return S_OK; +} + +HRESULT CHandler::OpenCapsule(IInStream *stream) +{ + const UInt32 kHeaderSize = 80; + Byte buf[kHeaderSize]; + RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); + _h.Parse(buf); + if (_h.HeaderSize != kHeaderSize || + _h.CapsuleImageSize < kHeaderSize || + _h.OffsetToCapsuleBody < kHeaderSize || + _h.OffsetToCapsuleBody > _h.CapsuleImageSize) + return S_FALSE; + + if (_h.SequenceNumber != 0 || + _h.OffsetToSplitInformation != 0 ) + return E_NOTIMPL; + + int bufIndex = AddBuf(_h.CapsuleImageSize); + CByteBuffer &buf0 = _bufs[bufIndex]; + memcpy(buf0, buf, kHeaderSize); + ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize); + + AddCommentString(L"Author", _h.OffsetToAuthorInformation); + AddCommentString(L"Revision", _h.OffsetToRevisionInformation); + AddCommentString(L"Short Description", _h.OffsetToShortDescription); + AddCommentString(L"Long Description", _h.OffsetToLongDescription); + + return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, _h.CapsuleImageSize - _h.OffsetToCapsuleBody, -1, -1, 0); +} + +HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) +{ + UInt64 fileSize; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); + if (fileSize > (1 << 27)) + return S_FALSE; + + UInt32 volIndex = 0; + UInt32 pos = 0, prevEnd = 0; + if (callback) + { + RINOK(callback->SetTotal(NULL, &fileSize)); + } + + for (;;) + { + UInt64 limit = 0; + UInt64 *limitPtr = NULL; + if (maxCheckStartPosition) + { + UInt32 directSize = pos - prevEnd; + if (directSize >= *maxCheckStartPosition) + break; + limit = *maxCheckStartPosition - directSize; + limitPtr = &limit; + } + + UInt64 resPos; + RINOK(stream->Seek(pos + kFfsGuidOffset, STREAM_SEEK_SET, NULL)); + if (FindSignatureInStream(stream, k_FFS_Guid, kGuidSize, limitPtr, resPos) == S_FALSE) + break; + + pos += (UInt32)resPos; + UInt64 fvSize; + { + UInt32 rem = (UInt32)fileSize - pos; + if (rem < kFvHeaderSize) + break; + RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); + Byte buf[kFvHeaderSize]; + RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize)); + fvSize = Get64(buf + 0x20); + if (!IsFfs(buf) || fvSize > rem) + { + pos++; + continue; + } + } + + RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL)); + + if (pos != prevEnd) + { + CItem item; + item.Offset = 0; + item.Size = pos - prevEnd; + item.BufIndex = AddBuf(item.Size); + CByteBuffer &buf0 = _bufs[item.BufIndex]; + RINOK(ReadStream_FALSE(stream, buf0, item.Size)); + item.Name = UInt32ToString(volIndex++); + AddItem(item); + } + + prevEnd = pos; + RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); + UInt32 fvSize32 = (UInt32)fvSize; + CItem item; + item.BufIndex = AddBuf(fvSize32); + CByteBuffer &buf0 = _bufs[item.BufIndex]; + item.Name = UInt32ToString(volIndex++); + int parent = AddDirItem(item); + ReadStream_FALSE(stream, buf0, fvSize32); + RINOK(ParseVolume(item.BufIndex, 0, fvSize32, parent, -1, 0)); + pos += fvSize32; + prevEnd = pos; + + if (callback) + { + UInt64 pos64 = pos; + RINOK(callback->SetCompleted(NULL, &pos64)); + } + } + if (_items.Size() == 0) + return S_FALSE; + + if (pos <= fileSize) + { + pos = (UInt32)fileSize; + if (prevEnd < pos) + { + CItem item; + item.Offset = 0; + item.Size = pos - prevEnd; + item.BufIndex = AddBuf(item.Size); + CByteBuffer &buf0 = _bufs[item.BufIndex]; + RINOK(stream->Seek(prevEnd, STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(stream, buf0, item.Size)); + item.Name = UInt32ToString(volIndex++); + AddItem(item); + } + } + _h.CapsuleImageSize = pos; + return S_OK; +} + +HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) +{ + if (_capsuleMode) + { + RINOK(OpenCapsule(stream)); + } + else + { + RINOK(OpenFv(stream, maxCheckStartPosition, callback)); + } + + CIntVector numChilds; + numChilds.Reserve(_items.Size()); + int i; + for (i = 0; i < _items.Size(); i++) + { + numChilds.Add(0); + int parent = _items[i].Parent; + if (parent >= 0) + numChilds[parent]++; + } + + for (i = 0; i < _items.Size(); i++) + { + CItem &item = _items[i]; + int parent = item.Parent; + if (parent >= 0) + { + CItem &parentItem = _items[parent]; + if (numChilds[parent] == 1) + if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs) + parentItem.Skip = true; + } + } + + CIntVector mainToReduced; + for (i = 0; i < _items.Size(); i++) + { + mainToReduced.Add(_items2.Size()); + const CItem &item = _items[i]; + if (item.Skip) + continue; + AString name; + int numItems = -1; + int parent = item.Parent; + if (parent >= 0) + numItems = numChilds[parent]; + AString name2 = item.GetName(numItems); + AString characts2 = item.Characts; + if (item.KeepName) + name = name2; + while (parent >= 0) + { + const CItem &item3 = _items[parent]; + if (!item3.Skip) + break; + if (item3.KeepName) + { + AString name3 = item3.GetName(-1); + if (name.IsEmpty()) + name = name3; + else + name = name3 + '.' + name; + } + AddSpaceAndString(characts2, item3.Characts); + parent = item3.Parent; + } + if (name.IsEmpty()) + name = name2; + + CItem2 item2; + item2.MainIndex = i; + item2.Name = name; + item2.Characts = characts2; + if (parent >= 0) + item2.Parent = mainToReduced[parent]; + _items2.Add(item2); + /* + CItem2 item2; + item2.MainIndex = i; + item2.Name = item.Name; + item2.Parent = item.Parent; + _items2.Add(item2); + */ + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + try + { + if (Open2(inStream, maxCheckStartPosition, callback) != S_OK) + return S_FALSE; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _totalBufsSize = 0; + _methodsMask = 0; + _items.Clear(); + _items2.Clear(); + _bufs.Clear(); + _comment.Empty(); + _h.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items2.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _items2.Size(); + if (numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size; + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + for (i = 0; i < numItems; i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CItem &item = _items[_items2[index].MainIndex]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + currentTotalSize += item.Size; + + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (testMode || item.IsDir) + { + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + int res = NExtract::NOperationResult::kDataError; + CMyComPtr<ISequentialInStream> inStream; + GetStream(index, &inStream); + if (inStream) + { + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); + if (copyCoderSpec->TotalSize == item.Size) + res = NExtract::NOperationResult::kOK; + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CItem &item = _items[_items2[index].MainIndex]; + if (item.IsDir) + return S_FALSE; + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr<IInStream> streamTemp = streamSpec; + const CByteBuffer &buf = _bufs[item.BufIndex]; + /* + if (item.Offset + item.Size > buf.GetCapacity()) + return S_FALSE; + */ + streamSpec->Init(buf + item.Offset, item.Size, (IInArchive *)this); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + + +namespace UEFIc +{ + static IInArchive *CreateArc() { return new CHandler(true); } + static CArcInfo g_ArcInfo = + { L"UEFIc", L"scap", 0, 0xD0, CAPSULE_SIGNATURE, kCapsuleSigSize, false, CreateArc, 0 }; + REGISTER_ARC(UEFIc) +} + +namespace UEFIs +{ + static IInArchive *CreateArc() { return new CHandler(false); } + static CArcInfo g_ArcInfo = + { L"UEFIs", L"", 0, 0xD1, FFS_SIGNATURE, kGuidSize, false, CreateArc, 0 }; + REGISTER_ARC(UEFIs) +} + +}} diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 50b879e7..85f0771c 100755 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -465,7 +465,8 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream, RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } } - + lps->InSize = lps->OutSize = complexity; + RINOK(lps->SetCur()); CUpdateItem ri; FILETIME ft; diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 64b7a586..8383488b 100755 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -8,6 +8,7 @@ #include "../../Common/ComTry.h" #include "../../Common/IntToString.h" +#include "../../Common/StringConvert.h" #include "../ICoder.h" @@ -40,13 +41,15 @@ namespace NXz { struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; +static const wchar_t *k_LZMA2_Name = L"LZMA2"; + class CHandler: public IInArchive, public IArchiveOpenSeq, #ifndef EXTRACT_ONLY public IOutArchive, public ISetProperties, - public COutHandler, + public CMultiMethodProps, #endif public CMyUnknownImp { @@ -62,12 +65,12 @@ class CHandler: CMyComPtr<IInStream> _stream; CMyComPtr<ISequentialInStream> _seqStream; - UInt32 _crcSize; + UInt32 _filterId; void Init() { - _crcSize = 4; - COutHandler::Init(); + _filterId = 0; + CMultiMethodProps::Init(); } HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback); @@ -98,14 +101,14 @@ CHandler::CHandler() Init(); } -STATPROPSTG kProps[] = +static STATPROPSTG const kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_BSTR} }; -STATPROPSTG kArcProps[] = +static STATPROPSTG const kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidNumBlocks, VT_UI4} @@ -160,11 +163,11 @@ struct CMethodNamePair const char *Name; }; -static CMethodNamePair g_NamePairs[] = +static const CMethodNamePair g_NamePairs[] = { { XZ_ID_Subblock, "SB" }, { XZ_ID_Delta, "Delta" }, - { XZ_ID_X86, "x86" }, + { XZ_ID_X86, "BCJ" }, { XZ_ID_PPC, "PPC" }, { XZ_ID_IA64, "IA64" }, { XZ_ID_ARM, "ARM" }, @@ -439,7 +442,10 @@ struct CXzUnpackerCPP Byte *InBuf; Byte *OutBuf; CXzUnpacker p; - CXzUnpackerCPP(): InBuf(0), OutBuf(0) {} + CXzUnpackerCPP(): InBuf(0), OutBuf(0) + { + XzUnpacker_Construct(&p, &g_Alloc); + } ~CXzUnpackerCPP() { XzUnpacker_Free(&p); @@ -483,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CCompressProgressWrap progressWrap(progress); - SRes res; + SRes res = S_OK; const UInt32 kInBufSize = 1 << 15; const UInt32 kOutBufSize = 1 << 21; @@ -492,8 +498,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 inSize = 0; UInt32 outPos = 0; CXzUnpackerCPP xzu; - res = XzUnpacker_Create(&xzu.p, &g_Alloc); - if (res == SZ_OK) + XzUnpacker_Init(&xzu.p); { xzu.InBuf = (Byte *)MyAlloc(kInBufSize); xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); @@ -534,6 +539,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } outPos = 0; } + RINOK(lps->SetCur()); if (finished) { _packSize = lps->InSize; @@ -553,7 +559,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } break; } - RINOK(lps->SetCur()); } Int32 opRes; @@ -573,8 +578,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return SResToHRESULT(res); } realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(opRes)); - return S_OK; + return extractCallback->SetOperationResult(opRes); COM_TRY_END } @@ -619,8 +623,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (IntToBool(newData)) { + UInt64 size; { - UInt64 size; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); if (prop.vt != VT_UI8) @@ -632,22 +636,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CLzma2EncProps lzma2Props; Lzma2EncProps_Init(&lzma2Props); - lzma2Props.lzmaProps.level = _level; + lzma2Props.lzmaProps.level = GetLevel(); CMyComPtr<ISequentialInStream> fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)); CSeqInStreamWrap seqInStream(fileInStream); + { + NCOM::CPropVariant prop = (UInt64)size; + RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); + } + for (int i = 0; i < _methods.Size(); i++) { COneMethodInfo &m = _methods[i]; - SetCompressionMethod2(m + SetGlobalLevelAndThreads(m #ifndef _7ZIP_ST , _numThreads #endif ); - if (m.IsLzma()) { for (int j = 0; j < m.Props.Size(); j++) { @@ -666,7 +674,40 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt lps->Init(updateCallback, true); CCompressProgressWrap progressWrap(progress); - SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p); + CXzProps xzProps; + CXzFilterProps filter; + XzProps_Init(&xzProps); + XzFilterProps_Init(&filter); + xzProps.lzma2Props = &lzma2Props; + xzProps.filterProps = (_filterId != 0 ? &filter : NULL); + switch (_crcSize) + { + case 0: xzProps.checkId = XZ_CHECK_NO; break; + case 4: xzProps.checkId = XZ_CHECK_CRC32; break; + case 8: xzProps.checkId = XZ_CHECK_CRC64; break; + case 32: xzProps.checkId = XZ_CHECK_SHA256; break; + default: return E_INVALIDARG; + } + filter.id = _filterId; + if (_filterId == XZ_ID_Delta) + { + bool deltaDefined = false; + for (int j = 0; j < _filterMethod.Props.Size(); j++) + { + const CProp &prop = _filterMethod.Props[j]; + if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) + { + UInt32 delta = (UInt32)prop.Value.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + filter.delta = delta; + deltaDefined = true; + } + } + if (!deltaDefined) + return E_INVALIDARG; + } + SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p); if (res == SZ_OK) return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); return SResToHRESULT(res); @@ -678,14 +719,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return NCompress::CopyStream(_stream, outStream, 0); } +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) { COM_TRY_BEGIN - BeforeSetProperty(); + Init(); for (int i = 0; i < numProps; i++) { RINOK(SetProperty(names[i], values[i])); } + + if (!_filterMethod.MethodName.IsEmpty()) + { + int k; + for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++) + { + const CMethodNamePair &pair = g_NamePairs[k]; + UString m = GetUnicodeString(pair.Name); + if (_filterMethod.MethodName.CompareNoCase(m) == 0) + { + _filterId = pair.Id; + break; + } + } + if (k == ARRAY_SIZE(g_NamePairs)) + return E_INVALIDARG; + } + + int numEmptyMethods = GetNumEmptyMethods(); + _methods.Delete(0, numEmptyMethods); + if (_methods.Size() > 1) + return E_INVALIDARG; + if (_methods.Size() == 1) + { + UString &methodName = _methods[0].MethodName; + if (methodName.IsEmpty()) + methodName = k_LZMA2_Name; + else if (methodName.CompareNoCase(k_LZMA2_Name) != 0) + return E_INVALIDARG; + } return S_OK; COM_TRY_END } diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 4c5fd38d..da42f3bd 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -33,6 +33,7 @@ static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize; class CLzmaEncoder: public ICompressCoder, + public ICompressSetCoderProperties, public CMyUnknownImp { NCompress::NLzma::CEncoder *EncoderSpec; @@ -41,12 +42,12 @@ class CLzmaEncoder: public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) }; -HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) { if (!Encoder) { @@ -67,7 +68,7 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN return S_OK; } -HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, +STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(WriteStream(outStream, Header, kLzmaHeaderSize)); @@ -210,52 +211,12 @@ HRESULT CAddCommon::Compress( _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA; CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder(); _compressEncoder = _lzmaEncoder; - NWindows::NCOM::CPropVariant props[] = - { - #ifndef _7ZIP_ST - _options.NumThreads, - #endif - _options.Algo, - _options.DicSize, - _options.NumFastBytes, - const_cast<BSTR>((const wchar_t *)_options.MatchFinder), - _options.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - #ifndef _7ZIP_ST - NCoderPropID::kNumThreads, - #endif - NCoderPropID::kAlgorithm, - NCoderPropID::kDictionarySize, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinder, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!_options.NumMatchFinderCyclesDefined) - numProps--; - RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps)); } else if (method == NFileHeader::NCompressionMethod::kPPMd) { _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd; NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder(); _compressEncoder = encoder; - NWindows::NCOM::CPropVariant props[] = - { - _options.Algo, - _options.MemSize, - _options.Order - - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kUsedMemorySize, - NCoderPropID::kOrder - }; - RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); } else { @@ -282,56 +243,20 @@ HRESULT CAddCommon::Compress( if (method == NFileHeader::NCompressionMethod::kDeflated || method == NFileHeader::NCompressionMethod::kDeflated64) { - NWindows::NCOM::CPropVariant props[] = - { - _options.Algo, - _options.NumPasses, - _options.NumFastBytes, - _options.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kNumPasses, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!_options.NumMatchFinderCyclesDefined) - numProps--; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); - if (setCoderProperties) - { - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps)); - } } else if (method == NFileHeader::NCompressionMethod::kBZip2) { - NWindows::NCOM::CPropVariant props[] = - { - _options.DicSize, - _options.NumPasses - #ifndef _7ZIP_ST - , _options.NumThreads - #endif - }; - PROPID propIDs[] = - { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumPasses - #ifndef _7ZIP_ST - , NCoderPropID::kNumThreads - #endif - }; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); - if (setCoderProperties) + } + } + { + CMyComPtr<ICompressSetCoderProperties> setCoderProps; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps); + if (setCoderProps) { - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); + RINOK(_options.MethodInfo.SetCoderProps(setCoderProps, + _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL)); } } - } } CMyComPtr<ISequentialOutStream> outStreamNew; if (_options.PasswordIsDefined) diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 7ef7cfb2..5be33166 100755 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -5,36 +5,54 @@ #include "Common/MyString.h" +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +#include "../Common/HandlerOut.h" + namespace NArchive { namespace NZip { -struct CCompressionMethodMode +struct CBaseProps { - CRecordVector<Byte> MethodSequence; - UString MatchFinder; - UInt32 Algo; - UInt32 NumPasses; - UInt32 NumFastBytes; - bool NumMatchFinderCyclesDefined; - UInt32 NumMatchFinderCycles; - UInt32 DicSize; - UInt32 MemSize; - UInt32 Order; + CMethodProps MethodInfo; + Int32 Level; #ifndef _7ZIP_ST UInt32 NumThreads; + bool NumThreadsWasChanged; #endif - bool PasswordIsDefined; - AString Password; bool IsAesMode; Byte AesKeyMode; + + void Init() + { + MethodInfo.Clear(); + Level = -1; + #ifndef _7ZIP_ST + NumThreads = NWindows::NSystem::GetNumberOfProcessors();; + NumThreadsWasChanged = false; + #endif + IsAesMode = false; + AesKeyMode = 3; + } +}; + +struct CCompressionMethodMode: public CBaseProps +{ + CRecordVector<Byte> MethodSequence; + bool PasswordIsDefined; + AString Password; + + UInt64 _dataSizeReduce; + bool _dataSizeReduceDefined; - CCompressionMethodMode(): - NumMatchFinderCyclesDefined(false), - PasswordIsDefined(false), - IsAesMode(false), - AesKeyMode(3) - {} + CCompressionMethodMode(): PasswordIsDefined(false) + { + _dataSizeReduceDefined = false; + _dataSizeReduce = 0; + } }; }} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index bd156322..2281ed5b 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -107,7 +107,7 @@ static struct CStrongCryptoPair { NStrongCryptoFlags::kRC4, "RC4" } }; -static STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -117,6 +117,7 @@ static STATPROPSTG kProps[] = { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, + // { NULL, kpidPosixAttrib, VT_UI4}, { NULL, kpidEncrypted, VT_BOOL}, { NULL, kpidComment, VT_BSTR}, { NULL, kpidCRC, VT_UI4}, @@ -125,7 +126,7 @@ static STATPROPSTG kProps[] = { NULL, kpidUnpackVer, VT_UI4} }; -static STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidBit64, VT_BOOL}, { NULL, kpidComment, VT_BSTR}, @@ -135,7 +136,7 @@ static STATPROPSTG kArcProps[] = CHandler::CHandler() { - InitMethodProperties(); + InitMethodProps(); } static AString BytesToString(const CByteBuffer &data) @@ -165,6 +166,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break; case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break; + case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break; } prop.Detach(value); COM_TRY_END @@ -194,7 +196,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UInt32 unixTime; if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) prop = (UInt32)NFileTimeType::kWindows; - else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) prop = (UInt32)NFileTimeType::kUnix; else prop = (UInt32)NFileTimeType::kDOS; @@ -220,7 +222,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { UInt32 unixTime; - if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) NTime::UnixTimeToFileTime(unixTime, utc); else { @@ -233,7 +235,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = utc; break; } - case kpidAttrib: prop = item.GetWinAttributes(); break; + case kpidAttrib: prop = item.GetWinAttrib(); break; + case kpidPosixAttrib: + { + UInt32 attrib; + if (item.GetPosixAttrib(attrib)) + prop = attrib; + break; + } case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break; case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break; @@ -435,7 +444,10 @@ public: ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, - UInt32 numThreads, Int32 &res); + #ifndef _7ZIP_ST + UInt32 numThreads, + #endif + Int32 &res); }; HRESULT CZipDecoder::Decode( @@ -444,7 +456,10 @@ HRESULT CZipDecoder::Decode( ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, - UInt32 numThreads, Int32 &res) + #ifndef _7ZIP_ST + UInt32 numThreads, + #endif + Int32 &res) { res = NExtract::NOperationResult::kDataError; CInStreamReleaser inStreamReleaser; @@ -805,15 +820,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); Int32 res; - RINOK(myDecoder.Decode( + HRESULT hres = myDecoder.Decode( EXTERNAL_CODECS_VARS m_Archive, item, realOutStream, extractCallback, - progress, _numThreads, res)); + progress, + #ifndef _7ZIP_ST + _props.NumThreads, + #endif + res); + RINOK(hres); realOutStream.Release(); RINOK(extractCallback->SetOperationResult(res)) } - return S_OK; + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + return lps->SetCur(); COM_TRY_END } diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index fdb60aaf..33cf6fdc 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -12,10 +12,6 @@ #include "ZipIn.h" #include "ZipCompressionMode.h" -#ifndef _7ZIP_ST -#include "../../../Windows/System.h" -#endif - namespace NArchive { namespace NZip { @@ -46,53 +42,24 @@ private: CObjectVector<CItemEx> m_Items; CInArchive m_Archive; - int m_Level; - int m_MainMethod; - UInt32 m_DicSize; - UInt32 m_Algo; - UInt32 m_NumPasses; - UInt32 m_NumFastBytes; - UInt32 m_NumMatchFinderCycles; - UInt32 m_MemSize; - UInt32 m_Order; - - bool m_NumMatchFinderCyclesDefined; + CBaseProps _props; + int m_MainMethod; bool m_ForceAesMode; - bool m_IsAesMode; - Byte m_AesKeyMode; - bool m_WriteNtfsTimeExtra; bool m_ForceLocal; bool m_ForceUtf8; - #ifndef _7ZIP_ST - UInt32 _numThreads; - #endif - DECL_EXTERNAL_CODECS_VARS - void InitMethodProperties() + void InitMethodProps() { - m_Level = -1; + _props.Init(); m_MainMethod = -1; - m_Algo = - m_DicSize = - m_NumPasses = - m_NumFastBytes = - m_Order = - m_MemSize = - m_NumMatchFinderCycles = 0xFFFFFFFF; - m_NumMatchFinderCyclesDefined = false; m_ForceAesMode = false; - m_IsAesMode = false; - m_AesKeyMode = 3; // aes-256 m_WriteNtfsTimeExtra = true; m_ForceLocal = false; m_ForceUtf8 = false; - #ifndef _7ZIP_ST - _numThreads = NWindows::NSystem::GetNumberOfProcessors();; - #endif } }; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index a5e0f59d..427b0c31 100755 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -28,37 +28,6 @@ using namespace NTime; namespace NArchive { namespace NZip { -static const UInt32 kLzAlgoX1 = 0; -static const UInt32 kLzAlgoX5 = 1; - -static const UInt32 kDeflateNumPassesX1 = 1; -static const UInt32 kDeflateNumPassesX7 = 3; -static const UInt32 kDeflateNumPassesX9 = 10; - -static const UInt32 kDeflateNumFastBytesX1 = 32; -static const UInt32 kDeflateNumFastBytesX7 = 64; -static const UInt32 kDeflateNumFastBytesX9 = 128; - -static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; -static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; - -static const UInt32 kLzmaNumFastBytesX1 = 32; -static const UInt32 kLzmaNumFastBytesX7 = 64; - -static const UInt32 kLzmaDicSizeX1 = 1 << 16; -static const UInt32 kLzmaDicSizeX3 = 1 << 20; -static const UInt32 kLzmaDicSizeX5 = 1 << 24; -static const UInt32 kLzmaDicSizeX7 = 1 << 25; -static const UInt32 kLzmaDicSizeX9 = 1 << 26; - -static const UInt32 kBZip2NumPassesX1 = 1; -static const UInt32 kBZip2NumPassesX7 = 2; -static const UInt32 kBZip2NumPassesX9 = 7; - -static const UInt32 kBZip2DicSizeX1 = 100000; -static const UInt32 kBZip2DicSizeX3 = 500000; -static const UInt32 kBZip2DicSizeX5 = 900000; - STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) { *timeType = NFileTimeType::kDOS; @@ -99,6 +68,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_BEGIN2 CObjectVector<CUpdateItem> updateItems; bool thereAreAesUpdates = false; + UInt64 largestSize = 0; + bool largestSizeDefined = false; for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; @@ -178,7 +149,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt const wchar_t kSlash = L'/'; if (!name.IsEmpty()) { - if (name[name.Length() - 1] == kSlash) + if (name.Back() == kSlash) { if (!ui.IsDir) return E_INVALIDARG; @@ -235,6 +206,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; + if (largestSize < size) + largestSize = size; + largestSizeDefined = true; } ui.Size = size; } @@ -247,6 +221,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } CCompressionMethodMode options; + (CBaseProps &)options = _props; + options._dataSizeReduce = largestSize; + options._dataSizeReduceDefined = largestSizeDefined; if (getTextPassword) { @@ -256,8 +233,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.PasswordIsDefined = IntToBool(passwordIsDefined); if (options.PasswordIsDefined) { - options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates); - options.AesKeyMode = m_AesKeyMode; + if (!m_ForceAesMode) + options.IsAesMode = thereAreAesUpdates; if (!IsAsciiString((const wchar_t *)password)) return E_INVALIDARG; @@ -272,13 +249,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt else options.PasswordIsDefined = false; - int level = m_Level; - if (level < 0) - level = 5; - Byte mainMethod; if (m_MainMethod < 0) - mainMethod = (Byte)(((level == 0) ? + mainMethod = (Byte)(((_props.Level == 0) ? NFileHeader::NCompressionMethod::kStored : NFileHeader::NCompressionMethod::kDeflated)); else @@ -286,83 +259,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.MethodSequence.Add(mainMethod); if (mainMethod != NFileHeader::NCompressionMethod::kStored) options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored); - bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) || - (mainMethod == NFileHeader::NCompressionMethod::kDeflated64); - bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA); - bool isLz = (isLZMA || isDeflate); - options.NumPasses = m_NumPasses; - options.DicSize = m_DicSize; - options.NumFastBytes = m_NumFastBytes; - options.NumMatchFinderCycles = m_NumMatchFinderCycles; - options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined; - options.Algo = m_Algo; - options.MemSize = m_MemSize; - options.Order = m_Order; - #ifndef _7ZIP_ST - options.NumThreads = _numThreads; - #endif - if (isLz) - { - if (isDeflate) - { - if (options.NumPasses == 0xFFFFFFFF) - options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 : - (level >= 7 ? kDeflateNumPassesX7 : - kDeflateNumPassesX1)); - if (options.NumFastBytes == 0xFFFFFFFF) - options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 : - (level >= 7 ? kDeflateNumFastBytesX7 : - kDeflateNumFastBytesX1)); - } - else if (isLZMA) - { - if (options.DicSize == 0xFFFFFFFF) - options.DicSize = - (level >= 9 ? kLzmaDicSizeX9 : - (level >= 7 ? kLzmaDicSizeX7 : - (level >= 5 ? kLzmaDicSizeX5 : - (level >= 3 ? kLzmaDicSizeX3 : - kLzmaDicSizeX1)))); - - if (options.NumFastBytes == 0xFFFFFFFF) - options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 : - kLzmaNumFastBytesX1); - - options.MatchFinder = - (level >= 5 ? kLzmaMatchFinderX5 : - kLzmaMatchFinderX1); - } - - if (options.Algo == 0xFFFFFFFF) - options.Algo = (level >= 5 ? kLzAlgoX5 : - kLzAlgoX1); - } - if (mainMethod == NFileHeader::NCompressionMethod::kBZip2) - { - if (options.NumPasses == 0xFFFFFFFF) - options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : - (level >= 7 ? kBZip2NumPassesX7 : - kBZip2NumPassesX1)); - if (options.DicSize == 0xFFFFFFFF) - options.DicSize = (level >= 5 ? kBZip2DicSizeX5 : - (level >= 3 ? kBZip2DicSizeX3 : - kBZip2DicSizeX1)); - } - if (mainMethod == NFileHeader::NCompressionMethod::kPPMd) - { - int level2 = level; - if (level2 < 1) level2 = 1; - if (level2 > 9) level2 = 9; - - if (options.MemSize == 0xFFFFFFFF) - options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2))); - - if (options.Order == 0xFFFFFFFF) - options.Order = 3 + level2; - - if (options.Algo == 0xFFFFFFFF) - options.Algo = (level2 >= 7 ? 1 : 0); - } return Update( EXTERNAL_CODECS_VARS @@ -371,16 +267,34 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_END2 } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +struct CMethodIndexToName +{ + unsigned Method; + const wchar_t *Name; +}; + +static const CMethodIndexToName k_SupportedMethods[] = { + { NFileHeader::NCompressionMethod::kStored, L"COPY" }, + { NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" }, + { NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" }, + { NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" }, + { NFileHeader::NCompressionMethod::kLZMA, L"LZMA" }, + { NFileHeader::NCompressionMethod::kPPMd, L"PPMD" } +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProps(); #ifndef _7ZIP_ST - const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); - _numThreads = numProcessors; + const UInt32 numProcessors = _props.NumThreads; #endif - InitMethodProperties(); - for (int i = 0; i < numProperties; i++) + + for (int i = 0; i < numProps; i++) { - UString name = UString(names[i]); + UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; @@ -390,140 +304,112 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v if (name[0] == L'X') { UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - m_Level = level; - continue; + RINOK(ParsePropToUInt32(name.Mid(1), prop, level)); + _props.Level = level; + _props.MethodInfo.AddLevelProp(level); } else if (name == L"M") { if (prop.vt == VT_BSTR) { - UString m = prop.bstrVal; + UString m = prop.bstrVal, m2; m.MakeUpper(); - if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored; - else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated; - else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64; - else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2; - else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA; - else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd; - else return E_INVALIDARG; + int colonPos = m.Find(L':'); + if (colonPos >= 0) + { + m2 = m.Mid(colonPos + 1); + m = m.Left(colonPos); + } + int k; + for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) + { + const CMethodIndexToName &pair = k_SupportedMethods[k]; + if (m == pair.Name) + { + if (!m2.IsEmpty()) + { + RINOK(_props.MethodInfo.ParseParamsFromString(m2)); + } + m_MainMethod = pair.Method; + break; + } + } + if (k == ARRAY_SIZE(k_SupportedMethods)) + return E_INVALIDARG; } else if (prop.vt == VT_UI4) { - switch(prop.ulVal) + int k; + for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) { - case NFileHeader::NCompressionMethod::kStored: - case NFileHeader::NCompressionMethod::kDeflated: - case NFileHeader::NCompressionMethod::kDeflated64: - case NFileHeader::NCompressionMethod::kBZip2: - case NFileHeader::NCompressionMethod::kLZMA: - m_MainMethod = (Byte)prop.ulVal; + unsigned method = k_SupportedMethods[k].Method; + if (prop.ulVal == method) + { + m_MainMethod = method; break; - default: - return E_INVALIDARG; + } } + if (k == ARRAY_SIZE(k_SupportedMethods)) + return E_INVALIDARG; } else return E_INVALIDARG; } else if (name.Left(2) == L"EM") { - if (prop.vt == VT_BSTR) + if (prop.vt != VT_BSTR) + return E_INVALIDARG; { - UString valueString = prop.bstrVal; - valueString.MakeUpper(); - if (valueString.Left(3) == L"AES") + UString m = prop.bstrVal; + m.MakeUpper(); + if (m.Left(3) == L"AES") { - valueString = valueString.Mid(3); - if (valueString == L"128") - m_AesKeyMode = 1; - else if (valueString == L"192") - m_AesKeyMode = 2; - else if (valueString == L"256" || valueString.IsEmpty()) - m_AesKeyMode = 3; + m = m.Mid(3); + if (m == L"128") + _props.AesKeyMode = 1; + else if (m == L"192") + _props.AesKeyMode = 2; + else if (m == L"256" || m.IsEmpty()) + _props.AesKeyMode = 3; else return E_INVALIDARG; - m_IsAesMode = true; + _props.IsAesMode = true; m_ForceAesMode = true; } - else if (valueString == L"ZIPCRYPTO") + else if (m == L"ZIPCRYPTO") { - m_IsAesMode = false; + _props.IsAesMode = false; m_ForceAesMode = true; } else return E_INVALIDARG; } - else - return E_INVALIDARG; - } - else if (name[0] == L'D') - { - UInt32 dicSize = kBZip2DicSizeX5; - RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); - m_DicSize = dicSize; - } - else if (name.Left(3) == L"MEM") - { - UInt32 memSize = 1 << 24; - RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize)); - m_MemSize = memSize; - } - else if (name[0] == L'O') - { - UInt32 order = 8; - RINOK(ParsePropValue(name.Mid(1), prop, order)); - m_Order = order; - } - else if (name.Left(4) == L"PASS") - { - UInt32 num = kDeflateNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - m_NumPasses = num; - } - else if (name.Left(2) == L"FB") - { - UInt32 num = kDeflateNumFastBytesX9; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_NumFastBytes = num; - } - else if (name.Left(2) == L"MC") - { - UInt32 num = 0xFFFFFFFF; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_NumMatchFinderCycles = num; - m_NumMatchFinderCyclesDefined = true; } else if (name.Left(2) == L"MT") { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads)); + _props.NumThreadsWasChanged = true; #endif } - else if (name.Left(1) == L"A") - { - UInt32 num = kLzAlgoX5; - RINOK(ParsePropValue(name.Mid(1), prop, num)); - m_Algo = num; - } else if (name.CompareNoCase(L"TC") == 0) { - RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra)); } else if (name.CompareNoCase(L"CL") == 0) { - RINOK(SetBoolProperty(m_ForceLocal, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal)); if (m_ForceLocal) m_ForceUtf8 = false; } else if (name.CompareNoCase(L"CU") == 0) { - RINOK(SetBoolProperty(m_ForceUtf8, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8)); if (m_ForceUtf8) m_ForceLocal = false; } else - return E_INVALIDARG; + return _props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop); } return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index b36b61be..e930488f 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -756,6 +756,7 @@ void CEcd64::Parse(const Byte *p) HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress) { + IsOkHeaders = true; // m_Signature must be kLocalFileHeaderSignature or // kEndOfCentralDirSignature // m_Position points to next byte after signature @@ -852,6 +853,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if (numCdItems != items.Size()) + IsOkHeaders = false; if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) || (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) || (UInt32)ecd64.cdSize != (UInt32)cdSize || @@ -861,7 +864,6 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr _inBufMode = false; _inBuffer.Free(); - IsOkHeaders = (numCdItems == items.Size()); ArcInfo.FinishPosition = m_Position; return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 139b0129..ad89f558 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -51,7 +51,7 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const return false; } -bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const +bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const { res = 0; UInt32 size = (UInt32)Data.GetCapacity(); @@ -60,6 +60,15 @@ bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const const Byte *p = (const Byte *)Data; Byte flags = *p++; size--; + if (isCentral) + { + if (index != NFileHeader::NUnixTime::kMTime || + (flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 || + size < 4) + return false; + res = GetUi32(p); + return true; + } for (int i = 0; i < 3; i++) if ((flags & (1 << i)) != 0) { @@ -88,7 +97,7 @@ bool CItem::IsDir() const if (!FromCentral) return false; WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF); - switch(MadeByVersion.HostOS) + switch (MadeByVersion.HostOS) { case NFileHeader::NHostOS::kAMIGA: switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT) @@ -109,44 +118,41 @@ bool CItem::IsDir() const case NFileHeader::NHostOS::kAcorn: case NFileHeader::NHostOS::kMVS: return false; // change it throw kUnknownAttributes; + case NFileHeader::NHostOS::kUnix: + return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0; default: - /* - switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT) - { - case NFileHeader::NUnixAttribute::kIFDIR: - return true; - default: - return false; - } - */ return false; } } -UInt32 CLocalItem::GetWinAttributes() const -{ - DWORD winAttributes = 0; - if (IsDir()) - winAttributes |= FILE_ATTRIBUTE_DIRECTORY; - return winAttributes; -} - -UInt32 CItem::GetWinAttributes() const +UInt32 CItem::GetWinAttrib() const { - DWORD winAttributes = 0; - switch(MadeByVersion.HostOS) + DWORD winAttrib = 0; + switch (MadeByVersion.HostOS) { case NFileHeader::NHostOS::kFAT: case NFileHeader::NHostOS::kNTFS: if (FromCentral) - winAttributes = ExternalAttributes; + winAttrib = ExternalAttributes; break; - default: - winAttributes = 0; // must be converted from unix value; } - if (IsDir()) // test it; - winAttributes |= FILE_ATTRIBUTE_DIRECTORY; - return winAttributes; + if (IsDir()) // test it; + winAttrib |= FILE_ATTRIBUTE_DIRECTORY; + return winAttrib; +} + +bool CItem::GetPosixAttrib(UInt32 &attrib) const +{ + // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT. + if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix) + { + attrib = ExternalAttributes >> 16; + return (attrib != 0); + } + attrib = 0; + if (IsDir()) + attrib = NFileHeader::NUnixAttribute::kIFDIR; + return false; } void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value) diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 31f2de73..5efd433a 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -3,7 +3,6 @@ #ifndef __ARCHIVE_ZIP_ITEM_H #define __ARCHIVE_ZIP_ITEM_H -#include "Common/Types.h" #include "Common/MyString.h" #include "Common/Buffer.h" #include "Common/UTFConvert.h" @@ -28,7 +27,7 @@ struct CExtraSubBlock UInt16 ID; CByteBuffer Data; bool ExtractNtfsTime(int index, FILETIME &ft) const; - bool ExtractUnixTime(int index, UInt32 &res) const; + bool ExtractUnixTime(bool isCentral, int index, UInt32 &res) const; }; struct CWzAesExtraField @@ -152,13 +151,13 @@ struct CExtraBlock return false; } - bool GetUnixTime(int index, UInt32 &res) const + bool GetUnixTime(bool isCentral, int index, UInt32 &res) const { for (int i = 0; i < SubBlocks.Size(); i++) { const CExtraSubBlock &sb = SubBlocks[i]; if (sb.ID == NFileHeader::NExtraID::kUnixTime) - return sb.ExtractUnixTime(index, res); + return sb.ExtractUnixTime(isCentral, index, res); } return false; } @@ -205,7 +204,6 @@ public: bool IsDir() const; bool IgnoreItem() const { return false; } - UInt32 GetWinAttributes() const; bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } @@ -252,7 +250,8 @@ public: bool NtfsTimeIsDefined; bool IsDir() const; - UInt32 GetWinAttributes() const; + UInt32 GetWinAttrib() const; + bool GetPosixAttrib(UInt32 &attrib) const; bool IsThereCrc() const { @@ -277,5 +276,3 @@ public: }} #endif - - diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index d4fdee3d..490d9e26 100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -473,6 +473,9 @@ static HRESULT Update2St( items.Add(item); lps->ProgressOffset += NFileHeader::kLocalBlockSize; } + lps->InSize = unpackSizeTotal; + lps->OutSize = packSizeTotal; + RINOK(lps->SetCur()); archive.WriteCentralDir(items, comment); return S_OK; } @@ -493,7 +496,7 @@ static HRESULT Update2( UInt64 numBytesToCompress = 0; int i; - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) @@ -527,6 +530,10 @@ static HRESULT Update2( complexity = 0; + CCompressionMethodMode options2; + if (options != 0) + options2 = *options; + #ifndef _7ZIP_ST const size_t kNumMaxThreads = (1 << 10); @@ -537,53 +544,58 @@ static HRESULT Update2( const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; - CCompressionMethodMode options2; - if (options != 0) - options2 = *options; - bool mtMode = ((options != 0) && (numThreads > 1)); if (numFilesToCompress <= 1) mtMode = false; - if (mtMode) + if (!mtMode) + { + if (numThreads < 2) + if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 && + options2.NumThreadsWasChanged) + options2.MethodInfo.AddNumThreadsProp(1); + } + else { Byte method = options->MethodSequence.Front(); if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) - mtMode = false; + numThreads = 1; if (method == NFileHeader::NCompressionMethod::kBZip2) { - UInt64 averageSize = numBytesToCompress / numFilesToCompress; - UInt32 blockSize = options->DicSize; - if (blockSize == 0) - blockSize = 1; - UInt64 averageNumberOfBlocks = averageSize / blockSize; - UInt32 numBZip2Threads = 32; - if (averageNumberOfBlocks < numBZip2Threads) - numBZip2Threads = (UInt32)averageNumberOfBlocks; - if (numBZip2Threads < 1) - numBZip2Threads = 1; - numThreads = numThreads / numBZip2Threads; - options2.NumThreads = numBZip2Threads; - if (numThreads <= 1) - mtMode = false; + bool fixedNumber; + UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber); + if (!fixedNumber) + { + UInt64 averageSize = numBytesToCompress / numFilesToCompress; + UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize(); + UInt64 averageNumberOfBlocks = averageSize / blockSize + 1; + numBZip2Threads = 32; + if (averageNumberOfBlocks < numBZip2Threads) + numBZip2Threads = (UInt32)averageNumberOfBlocks; + options2.MethodInfo.AddNumThreadsProp(numBZip2Threads); + } + numThreads /= numBZip2Threads; } if (method == NFileHeader::NCompressionMethod::kLZMA) { - UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1); + bool fixedNumber; + // we suppose that default LZMA is 2 thread. So we don't change it + UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber); numThreads /= numLZMAThreads; - options2.NumThreads = numLZMAThreads; - if (numThreads <= 1) - mtMode = false; } + if (numThreads > numFilesToCompress) + numThreads = (UInt32)numFilesToCompress; + if (numThreads <= 1) + mtMode = false; } if (!mtMode) #endif return Update2St( EXTERNAL_CODECS_LOC_VARS - archive, inArchive,inStream, - inputItems, updateItems, options, comment, updateCallback); + archive, inArchive, inStream, + inputItems, updateItems, &options2, comment, updateCallback); #ifndef _7ZIP_ST @@ -606,7 +618,7 @@ static HRESULT Update2( { RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize))); - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) refs.Refs.Add(CMemBlocks2()); UInt32 i; @@ -796,6 +808,7 @@ static HRESULT Update2( mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); itemIndex++; } + RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL)); archive.WriteCentralDir(items, comment); return S_OK; #endif diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index e6328f7e..5e0e3e51 100755 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -1771,14 +1771,6 @@ SOURCE=..\..\UI\Common\UpdateProduce.cpp SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File -# Begin Source File - -SOURCE=..\..\UI\Common\WorkDir.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\UI\Common\WorkDir.h -# End Source File # End Group # Begin Group "Crypto" diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 862d695a..a99c61ec 100755 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -90,7 +90,6 @@ UI_COMMON_OBJS = \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ - $O\WorkDir.obj \ AR_OBJS = \ $O\Bz2Handler.obj \ diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index 2aefcbd0..8de884f7 100755 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -88,7 +88,6 @@ UI_COMMON_OBJS = \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ - $O\WorkDir.obj \ AR_OBJS = \ $O\LzmaHandler.obj \ diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp index 44cc6398..dded8b1d 100755 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -613,6 +613,14 @@ SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile index 02ee7af1..b8f9133f 100755 --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile @@ -181,6 +181,7 @@ AR_OBJS = \ $O\SplitHandler.obj \ $O\SquashfsHandler.obj \ $O\SwfHandler.obj \ + $O\UefiHandler.obj \ $O\VhdHandler.obj \ $O\XarHandler.obj \ $O\XzHandler.obj \ diff --git a/CPP/7zip/Bundles/Fm/resource.rc b/CPP/7zip/Bundles/Fm/resource.rc index c2aab047..dd2058a1 100755 --- a/CPP/7zip/Bundles/Fm/resource.rc +++ b/CPP/7zip/Bundles/Fm/resource.rc @@ -3,5 +3,5 @@ STRINGTABLE BEGIN - 100 "7z zip bz2 bzip2 tbz2 tbz rar arj z taz lzh lha cab iso 001 rpm deb cpio tar gz gzip tgz tpz4 wim swm lzma dmg hfs xar vhd fat ntfs xz" + 100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd wim swm fat ntfs dmg hfs xar squashfs" END diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index d3609f7b..3b04c5e7 100755 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -109,7 +109,6 @@ CRYPTO_OBJS = \ $O\7zAesRegister.obj \ $O\MyAes.obj \ $O\RandGen.obj \ - $O\Sha1.obj \ C_OBJS = \ $O\Alloc.obj \ diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile index fb76cbc0..5598adc2 100755 --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ + $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index b13ea42a..5bf1277d 100755 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -2436,6 +2436,10 @@ SOURCE=..\..\Archive\SwfHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\UefiHandler.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Archive\VhdHandler.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile index 11c74872..2601f1d6 100755 --- a/CPP/7zip/Bundles/Format7zF/makefile +++ b/CPP/7zip/Bundles/Format7zF/makefile @@ -79,6 +79,7 @@ AR_OBJS = \ $O\SplitHandler.obj \ $O\SwfHandler.obj \ $O\SquashfsHandler.obj \ + $O\UefiHandler.obj \ $O\VhdHandler.obj \ $O\XarHandler.obj \ $O\XzHandler.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index df492020..1caf7301 100755 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -1,6 +1,6 @@ #include "../../MyVersionInfo.rc" -MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") +MY_VERSION_INFO_DLL("7z Plugin", "7z") 0 ICON "../../Archive/Icons/7z.ico" @@ -33,5 +33,5 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za") STRINGTABLE 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 squashfs:24" + 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24" END diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index efda09d7..e0f4dcba 100755 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -49,6 +49,8 @@ enum Enum { kHelp1 = 0, kHelp2, + kMethod, + kLevel, kAlgo, kDict, kFb, @@ -69,6 +71,8 @@ static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, + { L"MM", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"X", NSwitchType::kUnLimitedPostString, false, 1 }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, @@ -186,7 +190,7 @@ int main2(int numArgs, const char *args[]) IncorrectCommand(); } - if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; @@ -198,21 +202,38 @@ int main2(int numArgs, const char *args[]) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; + CObjectVector<CProperty> props; bool dictDefined = false; - UInt32 dict = (UInt32)-1; - if(parser[NKey::kDict].ThereIs) + UInt32 dict = (UInt32)(Int32)-1; + if (parser[NKey::kDict].ThereIs) { UInt32 dicLog; - if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) + const UString &s = parser[NKey::kDict].PostStrings[0]; + if (!GetNumber(s, dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; + CProperty prop; + prop.Name = L"d"; + prop.Value = s; + props.Add(prop); + } + if (parser[NKey::kLevel].ThereIs) + { + UInt32 level = 5; + const UString &s = parser[NKey::kLevel].PostStrings[0]; + if (!GetNumber(s, level)) + IncorrectCommand(); + CProperty prop; + prop.Name = L"x"; + prop.Value = s; + props.Add(prop); } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; - UInt32 numThreads = (UInt32)-1; + UInt32 numThreads = (UInt32)(Int32)-1; #ifndef _7ZIP_ST if (parser[NKey::kMultiThread].ThereIs) @@ -224,9 +245,24 @@ int main2(int numArgs, const char *args[]) else if (!GetNumber(s, numThreads)) IncorrectCommand(); + CProperty prop; + prop.Name = L"mt"; + prop.Value = s; + props.Add(prop); } #endif + if (parser[NKey::kMethod].ThereIs) + { + UString s = parser[NKey::kMethod].PostStrings[0]; + if (s.IsEmpty() || s[0] != '=') + IncorrectCommand(); + CProperty prop; + prop.Name = L"m"; + prop.Value = s.Mid(1); + props.Add(prop); + } + if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; @@ -236,10 +272,19 @@ int main2(int numArgs, const char *args[]) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } - return LzmaBenchCon(stderr, numIterations, numThreads, dict); + HRESULT res = BenchCon(props, numIterations, stderr); + if (res != S_OK) + { + if (res != E_ABORT) + { + PrintMessage("Benchmark Error"); + return 1; + } + } + return 0; } - if (numThreads == (UInt32)-1) + if (numThreads == (UInt32)(Int32)-1) numThreads = 1; bool encodeMode = false; @@ -267,7 +312,7 @@ int main2(int numArgs, const char *args[]) const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; - if (!inStreamSpec->Open(GetSystemString(inputName))) + if (!inStreamSpec->Open(us2fs(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); @@ -289,7 +334,7 @@ int main2(int numArgs, const char *args[]) const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; - if (!outStreamSpec->Create(GetSystemString(outputName), true)) + if (!outStreamSpec->Create(us2fs(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); @@ -398,7 +443,7 @@ int main2(int numArgs, const char *args[]) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); - PROPID propIDs[] = + const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, @@ -512,7 +557,7 @@ int main2(int numArgs, const char *args[]) int MY_CDECL main(int numArgs, const char *args[]) { try { return main2(numArgs, args); } - catch(const char *s) + catch (const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp index e171539d..6111aa7e 100755 --- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp @@ -132,6 +132,14 @@ SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -280,6 +288,14 @@ SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile index 4a76bbde..35d031af 100755 --- a/CPP/7zip/Bundles/LzmaCon/makefile +++ b/CPP/7zip/Bundles/LzmaCon/makefile @@ -21,6 +21,7 @@ COMMON_OBJS = \ WIN_OBJS = \ $O\FileIO.obj \ + $O\PropVariant.obj \ $O\System.obj 7ZIP_COMMON_OBJS = \ @@ -28,6 +29,7 @@ WIN_OBJS = \ $O\CreateCoder.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ + $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc index 32c85f15..0f9f498c 100755 --- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc +++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc @@ -30,15 +30,18 @@ OBJS = \ CWrappers.o \ FileStreams.o \ FilterCoder.o \ + MethodProps.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ + MyVector.o \ + MyWindows.o \ StringConvert.o \ StringToInt.o \ - MyVector.o \ + PropVariant.o \ 7zCrc.o \ 7zCrcOpt.o \ Alloc.o \ @@ -89,6 +92,9 @@ FileStreams.o: ../../Common/FileStreams.cpp FilterCoder.o: ../../Common/FilterCoder.cpp $(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp +MethodProps.o: ../../Common/MethodProps.cpp + $(CXX) $(CFLAGS) ../../Common/MethodProps.cpp + StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp @@ -102,23 +108,26 @@ CommandLineParser.o: ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp -MyWindows.o: ../../../Common/MyWindows.cpp - $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp - IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp +MyVector.o: ../../../Common/MyVector.cpp + $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp + +MyWindows.o: ../../../Common/MyWindows.cpp + $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp + StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp -MyVector.o: ../../../Common/MyVector.cpp - $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp +PropVariant.o: ../../../Windows/PropVariant.cpp + $(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp index b136ae7c..3e9a8162 100755 --- a/CPP/7zip/Bundles/SFXCon/Main.cpp +++ b/CPP/7zip/Bundles/SFXCon/Main.cpp @@ -11,6 +11,7 @@ #include "Windows/DLL.h" #include "Windows/FileDir.h" #endif +#include "Windows/FileName.h" #include "../../UI/Common/ExitCode.h" #include "../../UI/Common/Extract.h" @@ -25,6 +26,9 @@ using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; +#ifdef _WIN32 +HINSTANCE g_hInstance = 0; +#endif int g_CodePage = -1; extern CStdOutStream *g_StdStream; @@ -261,12 +265,11 @@ int Main2( #ifdef _WIN32 - UString arcPath; + FString arcPath; { - UString path; - NDLL::MyGetModuleFileName(NULL, path); - int fileNamePartStartIndex; - if (!NDirectory::MyGetFullPathName(path, arcPath, fileNamePartStartIndex)) + FString path; + NDLL::MyGetModuleFileName(path); + if (!NDirectory::MyGetFullPathName(path, arcPath)) { g_StdOut << "GetFullPathName Error"; return NExitCode::kFatalError; @@ -291,7 +294,7 @@ int Main2( PrintHelpAndExit(); } - if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; @@ -330,23 +333,23 @@ int Main2( bool passwordEnabled = parser[NKey::kPassword].ThereIs; UString password; - if(passwordEnabled) + if (passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; if (!NFind::DoesFileExist(arcPath)) throw kCantFindSFX; - UString outputDir; + FString outputDir; if (parser[NKey::kOutputDir].ThereIs) { - outputDir = parser[NKey::kOutputDir].PostStrings[0]; + outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); NName::NormalizeDirPathPrefix(outputDir); } { UStringVector v1, v2; - v1.Add(arcPath); - v2.Add(arcPath); + v1.Add(fs2us(arcPath)); + v2.Add(fs2us(arcPath)); const NWildcard::CCensorNode &wildcardCensorHead = wildcardCensor.Pairs.Front().Head; @@ -362,7 +365,7 @@ int Main2( if (result != S_OK) throw CSystemException(result); - if(command.CommandType != NCommandType::kList) + if (command.CommandType != NCommandType::kList) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp index a28e82d3..9b733da0 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.cpp @@ -6,6 +6,7 @@ #include "Windows/FileDir.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "ExtractCallback.h" @@ -18,7 +19,7 @@ static LPCWSTR kCantOpenFile = L"Can not open output file"; static LPCWSTR kUnsupportedMethod = L"Unsupported Method"; void CExtractCallbackImp::Init(IInArchive *archiveHandler, - const UString &directoryPath, + const FString &directoryPath, const UString &itemDefaultName, const FILETIME &defaultMTime, UInt32 defaultAttributes) @@ -76,12 +77,12 @@ STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) { - UString fullPath = _directoryPath; - for(int i = 0; i < dirPathParts.Size(); i++) + FString fullPath = _directoryPath; + for (int i = 0; i < dirPathParts.Size(); i++) { - fullPath += dirPathParts[i]; + fullPath += us2fs(dirPathParts[i]); NDirectory::MyCreateDirectory(fullPath); - fullPath += NName::kDirDelimiter; + fullPath += FCHAR_PATH_SEPARATOR; } } @@ -153,7 +154,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, CreateComplexDirectory(pathParts); } - UString fullProcessedPath = _directoryPath + processedPath; + FString fullProcessedPath = _directoryPath + us2fs(processedPath); if (_processedFileInfo.IsDir) { @@ -166,7 +167,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, return S_OK; } - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { if (!NDirectory::DeleteFileAlways(fullProcessedPath)) diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h index c78ff22b..128988f9 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallback.h @@ -31,9 +31,9 @@ public: private: CMyComPtr<IInArchive> _archiveHandler; - UString _directoryPath; + FString _directoryPath; UString _filePath; - UString _diskFilePath; + FString _diskFilePath; bool _extractMode; struct CProcessedFileInfo @@ -60,7 +60,7 @@ public: UString _message; void Init(IInArchive *archiveHandler, - const UString &directoryPath, + const FString &directoryPath, const UString &itemDefaultName, const FILETIME &defaultMTime, UInt32 defaultAttributes); diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp index cc561090..8f830de5 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" #include "Windows/Thread.h" #include "../../UI/Common/OpenArchive.h" @@ -20,8 +21,8 @@ static LPCWSTR kCantOpenArchive = L"Can not open the file as archive"; struct CThreadExtracting { CCodecs *Codecs; - UString FileName; - UString DestFolder; + FString FileName; + FString DestFolder; CExtractCallbackImp *ExtractCallbackSpec; CMyComPtr<IArchiveExtractCallback> ExtractCallback; @@ -32,7 +33,7 @@ struct CThreadExtracting void Process2() { - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; if (!fi.Find(FileName)) { ErrorMessage = kCantFindArchive; @@ -40,7 +41,7 @@ struct CThreadExtracting return; } - Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec); + Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, fs2us(FileName), ExtractCallbackSpec); if (Result != S_OK) { if (Result != S_OK) @@ -48,7 +49,7 @@ struct CThreadExtracting return; } - UString dirPath = DestFolder; + FString dirPath = DestFolder; NFile::NName::NormalizeDirPathPrefix(dirPath); if (!NFile::NDirectory::CreateComplexDirectory(dirPath)) @@ -57,7 +58,7 @@ struct CThreadExtracting #ifdef LANG 0x02000603, #endif - dirPath); + fs2us(dirPath)); Result = E_FAIL; return; } @@ -86,7 +87,7 @@ struct CThreadExtracting } }; -HRESULT ExtractArchive(CCodecs *codecs,const UString &fileName, const UString &destFolder, +HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, bool showProgress, bool &isCorrupt, UString &errorMessage) { isCorrupt = false; diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h index 56d69686..295d77b9 100755 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h @@ -1,11 +1,11 @@ // ExtractEngine.h -#ifndef __EXTRACTENGINE_H -#define __EXTRACTENGINE_H +#ifndef __EXTRACT_ENGINE_H +#define __EXTRACT_ENGINE_H #include "../../UI/Common/LoadCodecs.h" -HRESULT ExtractArchive(CCodecs *codecs, const UString &fileName, const UString &destFolder, - bool showProgress, bool &isCorrupt, UString &errorMessage); +HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, + bool showProgress, bool &isCorrupt, UString &errorMessage); #endif diff --git a/CPP/7zip/Bundles/SFXSetup/Main.cpp b/CPP/7zip/Bundles/SFXSetup/Main.cpp index 80e23c4e..008c0e42 100755 --- a/CPP/7zip/Bundles/SFXSetup/Main.cpp +++ b/CPP/7zip/Bundles/SFXSetup/Main.cpp @@ -12,6 +12,7 @@ #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileIO.h" +#include "Windows/FileName.h" #include "Windows/NtCheck.h" #include "Windows/ResourceString.h" @@ -25,11 +26,11 @@ using namespace NWindows; HINSTANCE g_hInstance; -static LPCTSTR kTempDirPrefix = TEXT("7zS"); +static CFSTR kTempDirPrefix = FTEXT("7zS"); #define _SHELL_EXECUTE -static bool ReadDataString(LPCWSTR fileName, LPCSTR startID, +static bool ReadDataString(CFSTR fileName, LPCSTR startID, LPCSTR endID, AString &stringResult) { stringResult.Empty(); @@ -107,11 +108,11 @@ public: #ifndef UNDER_CE class CCurrentDirRestorer { - CSysString m_CurrentDirectory; + FString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} - bool RestoreDirectory() { return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); } + bool RestoreDirectory() const { return NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory); } }; #endif @@ -137,8 +138,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #endif NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); - UString fullPath; - NDLL::MyGetModuleFileName(g_hInstance, fullPath); + FString fullPath; + NDLL::MyGetModuleFileName(fullPath); switches.Trim(); bool assumeYes = false; @@ -191,7 +192,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #endif } - NFile::NDirectory::CTempDirectory tempDir; + NFile::NDirectory::CTempDir tempDir; if (!tempDir.Create(kTempDirPrefix)) { if (!assumeYes) @@ -208,7 +209,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, return 1; } - UString tempDirPath = GetUnicodeString(tempDir.GetPath()); + FString tempDirPath = tempDir.GetPath(); { bool isCorrupt = false; UString errorMessage; @@ -233,7 +234,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifndef UNDER_CE CCurrentDirRestorer currentDirRestorer; - if (!SetCurrentDirectory(tempDir.GetPath())) + if (!NFile::NDirectory::MySetCurrentDirectory(tempDir.GetPath())) return 1; #endif @@ -281,7 +282,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (appLaunched.IsEmpty()) { appLaunched = L"setup.exe"; - if (!NFile::NFind::DoesFileExist(GetSystemString(appLaunched))) + if (!NFile::NFind::DoesFileExist(us2fs(appLaunched))) { if (!assumeYes) ShowErrorMessage(L"Can not find setup.exe"); @@ -290,12 +291,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, } { - UString s2 = tempDirPath; + FString s2 = tempDirPath; NFile::NName::NormalizeDirPathPrefix(s2); - appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, s2); + appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); } - appLaunched.Replace(L"%%T", tempDirPath); + appLaunched.Replace(L"%%T", fs2us(tempDirPath)); if (!switches.IsEmpty()) { diff --git a/CPP/7zip/Bundles/SFXWin/Main.cpp b/CPP/7zip/Bundles/SFXWin/Main.cpp index ec5098dd..bb7318a1 100755 --- a/CPP/7zip/Bundles/SFXWin/Main.cpp +++ b/CPP/7zip/Bundles/SFXWin/Main.cpp @@ -41,7 +41,7 @@ int APIENTRY WinMain2() UString password; bool assumeYes = false; bool outputFolderDefined = false; - UString outputFolder; + FString outputFolder; UStringVector commandStrings; NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); @@ -57,7 +57,7 @@ int APIENTRY WinMain2() assumeYes = true; else if (s.Left(2).CompareNoCase(L"-o") == 0) { - outputFolder = s.Mid(2); + outputFolder = us2fs(s.Mid(2)); NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder); outputFolderDefined = !outputFolder.IsEmpty(); } @@ -67,12 +67,11 @@ int APIENTRY WinMain2() } } - UString path; - NWindows::NDLL::MyGetModuleFileName(g_hInstance, path); + FString path; + NWindows::NDLL::MyGetModuleFileName(path); - UString fullPath; - int fileNamePartStartIndex; - if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath, fileNamePartStartIndex)) + FString fullPath; + if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath)) { ShowErrorMessage(L"Error 1329484"); return 1; @@ -102,8 +101,15 @@ int APIENTRY WinMain2() #endif CExtractOptions eo; - eo.OutputDir = outputFolderDefined ? outputFolder : - fullPath.Left(fileNamePartStartIndex); + + FString dirPrefix; + if (!NWindows::NFile::NDirectory::GetOnlyDirPrefix(path, dirPrefix)) + { + ShowErrorMessage(L"Error 1329485"); + return 1; + } + + eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; eo.YesToAll = assumeYes; eo.OverwriteMode = assumeYes ? NExtract::NOverwriteMode::kWithoutPrompt : @@ -112,8 +118,8 @@ int APIENTRY WinMain2() eo.TestMode = false; UStringVector v1, v2; - v1.Add(fullPath); - v2.Add(fullPath); + v1.Add(fs2us(fullPath)); + v2.Add(fs2us(fullPath)); NWildcard::CCensorNode wildcardCensor; wildcardCensor.AddItem(true, L"*", true, true, true); @@ -170,4 +176,3 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, return NExitCode::kFatalError; } } - diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp index 358f0b50..ef21228e 100755 --- a/CPP/7zip/Common/CWrappers.cpp +++ b/CPP/7zip/Common/CWrappers.cpp @@ -37,6 +37,7 @@ SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) case E_INVALIDARG: return SZ_ERROR_PARAM; case E_ABORT: return SZ_ERROR_PROGRESS; case S_FALSE: return SZ_ERROR_DATA; + case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; } return defaultRes; } @@ -90,6 +91,7 @@ HRESULT SResToHRESULT(SRes res) case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; } return E_FAIL; } diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index 7d6e36f1..495f886b 100755 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -11,10 +11,10 @@ using namespace NWindows; -static bool MakeAutoName(const UString &name, - const UString &extension, unsigned value, UString &path) +static bool MakeAutoName(const FString &name, + const FString &extension, unsigned value, FString &path) { - wchar_t number[16]; + FChar number[16]; ConvertUInt32ToString(value, number); path = name; path += number; @@ -22,18 +22,18 @@ static bool MakeAutoName(const UString &name, return NFile::NFind::DoesFileOrDirExist(path); } -bool AutoRenamePath(UString &fullProcessedPath) +bool AutoRenamePath(FString &fullProcessedPath) { - UString path; - int dotPos = fullProcessedPath.ReverseFind(L'.'); + FString path; + int dotPos = fullProcessedPath.ReverseFind(FTEXT('.')); - int slashPos = fullProcessedPath.ReverseFind(L'/'); + int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); #ifdef _WIN32 - int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); + int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); slashPos = MyMax(slashPos, slash1Pos); #endif - UString name, extension; + FString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h index 3ef87f48..eee0aba7 100755 --- a/CPP/7zip/Common/FilePathAutoRename.h +++ b/CPP/7zip/Common/FilePathAutoRename.h @@ -1,10 +1,10 @@ -// Util/FilePathAutoRename.h +// FilePathAutoRename.h -#ifndef __FILEPATHAUTORENAME_H -#define __FILEPATHAUTORENAME_H +#ifndef __FILE_PATH_AUTO_RENAME_H +#define __FILE_PATH_AUTO_RENAME_H #include "Common/MyString.h" -bool AutoRenamePath(UString &fullProcessedPath); +bool AutoRenamePath(FString &fullProcessedPath); #endif diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 426a0d3d..a8be8aa4 100755 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -29,34 +29,6 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -bool CInFileStream::Open(LPCTSTR fileName) -{ - return File.Open(fileName); -} - -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::Open(LPCWSTR fileName) -{ - return File.Open(fileName); -} -#endif -#endif - -bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ - return File.OpenShared(fileName, shareForWrite); -} - -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) -{ - return File.OpenShared(fileName, shareForWrite); -} -#endif -#endif - #ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; @@ -279,7 +251,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, #else - off_t res = File.Seek(offset, seekOrigin); + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; if (newPosition != NULL) @@ -343,7 +315,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo #else - off_t res = File.Seek(offset, seekOrigin); + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; if (newPosition != NULL) diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 895745d3..bb2b1d41 100755 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -1,12 +1,14 @@ // FileStreams.h -#ifndef __FILESTREAMS_H -#define __FILESTREAMS_H +#ifndef __FILE_STREAMS_H +#define __FILE_STREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif +#include "../../Common/MyString.h" + #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else @@ -41,19 +43,15 @@ public: CInFileStream(); #endif - bool Open(LPCTSTR fileName); - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool Open(LPCWSTR fileName); - #endif - #endif - - bool OpenShared(LPCTSTR fileName, bool shareForWrite); - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - #endif - #endif + bool Open(CFSTR fileName) + { + return File.Open(fileName); + } + + bool OpenShared(CFSTR fileName, bool shareForWrite) + { + return File.OpenShared(fileName, shareForWrite); + } MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) @@ -78,37 +76,23 @@ class COutFileStream: public IOutStream, public CMyUnknownImp { +public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif -public: virtual ~COutFileStream() {} - bool Create(LPCTSTR fileName, bool createAlways) + bool Create(CFSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } - bool Open(LPCTSTR fileName, DWORD creationDisposition) + bool Open(CFSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } - #ifdef USE_WIN_FILE - #ifndef _UNICODE - bool Create(LPCWSTR fileName, bool createAlways) - { - ProcessedSize = 0; - return File.Create(fileName, createAlways); - } - bool Open(LPCWSTR fileName, DWORD creationDisposition) - { - ProcessedSize = 0; - return File.Open(fileName, creationDisposition); - } - #endif - #endif HRESULT Close(); diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index dfe8b3d3..442374da 100755 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -13,7 +13,7 @@ using namespace NDirectory; static const UInt32 kTempBufSize = (1 << 20); -static LPCTSTR kTempFilePrefixString = TEXT("7zt"); +static CFSTR kTempFilePrefixString = FTEXT("7zt"); CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } @@ -42,12 +42,7 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) return true; if (!_tempFileCreated) { - CSysString tempDirPath; - if (!MyGetTempPath(tempDirPath)) - return false; - if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0) - return false; - if (!_outFile.Create(_tempFileName, true)) + if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) return false; _tempFileCreated = true; } @@ -91,7 +86,7 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) if (_tempFileCreated) { NIO::CInFile inFile; - if (!inFile.Open(_tempFileName)) + if (!inFile.Open(_tempFile.GetPath())) return E_FAIL; while (size < _size) { diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h index 073f95ac..bdf937de 100755 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -5,7 +5,6 @@ #include "../../Common/MyCom.h" #include "../../Windows/FileDir.h" -#include "../../Windows/FileIO.h" #include "../IStream.h" @@ -15,7 +14,6 @@ class CInOutTempBuffer NWindows::NFile::NIO::COutFile _outFile; Byte *_buf; UInt32 _bufPos; - CSysString _tempFileName; bool _tempFileCreated; UInt64 _size; UInt32 _crc; diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp index b797b685..1566c97c 100755 --- a/CPP/7zip/Common/MethodId.cpp +++ b/CPP/7zip/Common/MethodId.cpp @@ -1,27 +1,3 @@ // MethodId.cpp #include "StdAfx.h" - -#include "MethodId.h" -#include "../../Common/MyString.h" - -static inline wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); -} - -UString ConvertMethodIdToString(UInt64 id) -{ - wchar_t s[32]; - int len = 32; - s[--len] = 0; - do - { - s[--len] = GetHex((Byte)id & 0xF); - id >>= 4; - s[--len] = GetHex((Byte)id & 0xF); - id >>= 4; - } - while (id != 0); - return s + len; -} diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index 5836d0f8..e15a3cc8 100755 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -2,98 +2,447 @@ #include "StdAfx.h" -#include "../../Common/MyCom.h" - -#include "../ICoder.h" +#include "../../Common/StringToInt.h" #include "MethodProps.h" -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_LZMA2 = 0x21; +using namespace NWindows; + +bool StringToBool(const UString &s, bool &res) +{ + if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) + { + res = true; + return true; + } + if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) + { + res = false; + return true; + } + return false; +} + +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest) +{ + switch (prop.vt) + { + case VT_EMPTY: dest = true; return S_OK; + case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK; + case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG; + } + return E_INVALIDARG; +} + +int ParseStringToUInt32(const UString &srcString, UInt32 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number64 = ConvertStringToUInt64(start, &end); + if (number64 > (UInt32)0xFFFFFFFF) + { + number = 0; + return 0; + } + number = (UInt32)number64; + return (int)(end - start); +} + +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + // =VT_UI4 + // =VT_EMPTY + // {stringUInt32}=VT_EMPTY -HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) + if (prop.vt == VT_UI4) + { + if (!name.IsEmpty()) + return E_INVALIDARG; + resValue = prop.ulVal; + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (name.IsEmpty()) + return S_OK; + UInt32 v; + if (ParseStringToUInt32(name, v) != name.Length()) + return E_INVALIDARG; + resValue = v; + return S_OK; +} + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { - bool tryReduce = false; - UInt32 reducedDictionarySize = 1 << 10; - if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2)) + if (name.IsEmpty()) { - for (;;) + switch (prop.vt) { - const UInt32 step = (reducedDictionarySize >> 1); - if (reducedDictionarySize >= *inSizeForReduce) - { - tryReduce = true; + case VT_UI4: + numThreads = prop.ulVal; break; - } - reducedDictionarySize += step; - if (reducedDictionarySize >= *inSizeForReduce) + default: { - tryReduce = true; + bool val; + RINOK(PROPVARIANT_to_bool(prop, val)); + numThreads = (val ? defaultNumThreads : 1); break; } - if (reducedDictionarySize >= ((UInt32)3 << 30)) - break; - reducedDictionarySize += step; } + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return ParsePropToUInt32(name, prop, numThreads); +} + +static HRESULT StringToDictSize(const UString &srcStringSpec, UInt32 &dicSize) +{ + UString srcString = srcStringSpec; + srcString.MakeUpper(); + const wchar_t *start = srcString; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(start, &end); + int numDigits = (int)(end - start); + if (numDigits == 0 || srcString.Length() > numDigits + 1) + return E_INVALIDARG; + const unsigned kLogDictSizeLimit = 32; + if (srcString.Length() == numDigits) + { + if (number >= kLogDictSizeLimit) + return E_INVALIDARG; + dicSize = (UInt32)1 << (int)number; + return S_OK; + } + unsigned numBits; + switch (srcString[numDigits]) + { + case 'B': numBits = 0; break; + case 'K': numBits = 10; break; + case 'M': numBits = 20; break; + case 'G': numBits = 30; break; + default: return E_INVALIDARG; + } + if (number >= ((UInt64)1 << (kLogDictSizeLimit - numBits))) + return E_INVALIDARG; + dicSize = (UInt32)number << numBits; + return S_OK; +} + +static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue) +{ + if (prop.vt == VT_UI4) + { + UInt32 v = prop.ulVal; + if (v >= 32) + return E_INVALIDARG; + resValue = (UInt32)1 << v; + return S_OK; + } + if (prop.vt == VT_BSTR) + return StringToDictSize(prop.bstrVal, resValue); + return E_INVALIDARG; +} + +void CProps::AddProp32(PROPID propid, UInt32 level) +{ + CProp prop; + prop.IsOptional = true; + prop.Id = propid; + prop.Value = (UInt32)level; + Props.Add(prop); +} + +class CCoderProps +{ + PROPID *_propIDs; + NCOM::CPropVariant *_props; + unsigned _numProps; + unsigned _numPropsMax; +public: + CCoderProps(unsigned numPropsMax) + { + _numPropsMax = numPropsMax; + _numProps = 0; + _propIDs = new PROPID[numPropsMax]; + _props = new NCOM::CPropVariant[numPropsMax]; + } + ~CCoderProps() + { + delete []_propIDs; + delete []_props; + } + void AddProp(const CProp &prop); + HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties) + { + return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps); + } +}; + +void CCoderProps::AddProp(const CProp &prop) +{ + if (_numProps >= _numPropsMax) + throw 1; + _propIDs[_numProps] = prop.Id; + _props[_numProps] = prop.Value; + _numProps++; +} + +HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const +{ + CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0)); + for (int i = 0; i < Props.Size(); i++) + coderProps.AddProp(Props[i]); + if (dataSizeReduce) + { + CProp prop; + prop.Id = NCoderPropID::kReduceSize; + prop.Value = *dataSizeReduce; + coderProps.AddProp(prop); + } + return coderProps.SetProps(scp); +} + + +int CMethodProps::FindProp(PROPID id) const +{ + for (int i = Props.Size() - 1; i >= 0; i--) + if (Props[i].Id == id) + return i; + return -1; +} + +int CMethodProps::GetLevel() const +{ + int i = FindProp(NCoderPropID::kLevel); + if (i < 0) + return 5; + if (Props[i].Value.vt != VT_UI4) + return 9; + UInt32 level = Props[i].Value.ulVal; + return level > 9 ? 9 : (int)level; +} + +struct CNameToPropID +{ + VARTYPE VarType; + const wchar_t *Name; +}; + +static const CNameToPropID g_NameToPropID[] = +{ + { VT_UI4, L"" }, + { VT_UI4, L"d" }, + { VT_UI4, L"mem" }, + { VT_UI4, L"o" }, + { VT_UI4, L"c" }, + { VT_UI4, L"pb" }, + { VT_UI4, L"lc" }, + { VT_UI4, L"lp" }, + { VT_UI4, L"fb" }, + { VT_BSTR, L"mf" }, + { VT_UI4, L"mc" }, + { VT_UI4, L"pass" }, + { VT_UI4, L"a" }, + { VT_UI4, L"mt" }, + { VT_BOOL, L"eos" }, + { VT_UI4, L"x" }, + { VT_UI4, L"reduceSize" } +}; + +static int FindPropIdExact(const UString &name) +{ + for (unsigned i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) + if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) + return i; + return -1; +} + +static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) +{ + if (varType == srcProp.vt) + { + destProp = srcProp; + return true; + } + if (varType == VT_BOOL) + { + bool res; + if (PROPVARIANT_to_bool(srcProp, res) != S_OK) + return false; + destProp = res; + return true; + } + if (srcProp.vt == VT_EMPTY) + { + destProp = srcProp; + return true; + } + return false; +} + +static void SplitParams(const UString &srcString, UStringVector &subStrings) +{ + subStrings.Clear(); + UString s; + int len = srcString.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L':') + { + subStrings.Add(s); + s.Empty(); + } + else + s += c; } + subStrings.Add(s); +} +static void SplitParam(const UString ¶m, UString &name, UString &value) +{ + int eqPos = param.Find(L'='); + if (eqPos >= 0) { - int numProps = method.Props.Size(); - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); - if (setCoderProperties == NULL) + name = param.Left(eqPos); + value = param.Mid(eqPos + 1); + return; + } + int i; + for (i = 0; i < param.Length(); i++) + { + wchar_t c = param[i]; + if (c >= L'0' && c <= L'9') + break; + } + name = param.Left(i); + value = param.Mid(i); +} + +static bool IsLogSizeProp(PROPID propid) +{ + switch (propid) + { + case NCoderPropID::kDictionarySize: + case NCoderPropID::kUsedMemorySize: + case NCoderPropID::kBlockSize: + case NCoderPropID::kReduceSize: + return true; + } + return false; +} + +HRESULT CMethodProps::SetParam(const UString &name, const UString &value) +{ + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = index; + + if (IsLogSizeProp(prop.Id)) + { + UInt32 dicSize; + RINOK(StringToDictSize(value, dicSize)); + prop.Value = dicSize; + } + else + { + NCOM::CPropVariant propValue; + if (nameToPropID.VarType == VT_BSTR) + propValue = value; + else if (nameToPropID.VarType == VT_BOOL) { - if (numProps != 0) + bool res; + if (!StringToBool(value, res)) return E_INVALIDARG; + propValue = res; } - else + else if (!value.IsEmpty()) { - CRecordVector<PROPID> propIDs; - NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; - HRESULT res = S_OK; - try - { - for (int i = 0; i < numProps; i++) - { - const CProp &prop = method.Props[i]; - propIDs.Add(prop.Id); - NWindows::NCOM::CPropVariant &value = values[i]; - value = prop.Value; - // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) - if (tryReduce) - if (prop.Id == NCoderPropID::kDictionarySize) - if (value.vt == VT_UI4) - if (reducedDictionarySize < value.ulVal) - value.ulVal = reducedDictionarySize; - } - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); - res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); - } - catch(...) - { - delete []values; - throw; - } - delete []values; - RINOK(res); + UInt32 number; + if (ParseStringToUInt32(value, number) == value.Length()) + propValue = number; + else + propValue = value; } + if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); + return S_OK; +} + +HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) +{ + UStringVector params; + SplitParams(srcString, params); + for (int i = 0; i < params.Size(); i++) + { + const UString ¶m = params[i]; + UString name, value; + SplitParam(param, name, value); + RINOK(SetParam(name, value)); } - - /* - CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; - coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); - if (writeCoderProperties != NULL) - { - CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); - outStreamSpec->Init(); - RINOK(writeCoderProperties->WriteCoderProperties(outStream)); - size_t size = outStreamSpec->GetSize(); - filterProps.SetCapacity(size); - memmove(filterProps, outStreamSpec->GetBuffer(), size); - } - */ return S_OK; } +HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (realName.Length() == 0) + { + // [empty]=method + return E_INVALIDARG; + } + if (value.vt == VT_EMPTY) + { + // {realName}=[empty] + UString name, value; + SplitParam(realName, name, value); + return SetParam(name, value); + } + + // {realName}=value + int index = FindPropIdExact(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[index]; + CProp prop; + prop.Id = index; + + if (IsLogSizeProp(prop.Id)) + { + UInt32 dicSize; + RINOK(PROPVARIANT_to_DictSize(value, dicSize)); + prop.Value = dicSize; + } + else + { + if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); + return S_OK; +} + +HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (!realName.IsEmpty() && realName.CompareNoCase(L"m") != 0) + return ParseParamsFromPROPVARIANT(realName, value); + // -m{N}=method + if (value.vt != VT_BSTR) + return E_INVALIDARG; + const UString s = value.bstrVal; + int splitPos = s.Find(':'); + if (splitPos < 0) + { + MethodName = s; + return S_OK; + } + MethodName = s.Left(splitPos); + return ParseParamsFromString(s.Mid(splitPos + 1)); +} diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 8127e21e..0bdddc6b 100755 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -3,39 +3,182 @@ #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H -#include "../../Common/MyVector.h" +#include "../../Common/MyString.h" #include "../../Windows/PropVariant.h" -#include "MethodId.h" +#include "../ICoder.h" + +bool StringToBool(const UString &s, bool &res); +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); +int ParseStringToUInt32(const UString &srcString, UInt32 &number); +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); struct CProp { PROPID Id; + bool IsOptional; NWindows::NCOM::CPropVariant Value; + CProp(): IsOptional(false) {} }; -struct CMethod +struct CProps { - CMethodId Id; CObjectVector<CProp> Props; + + void Clear() { Props.Clear(); } + + bool AreThereNonOptionalProps() const + { + for (int i = 0; i < Props.Size(); i++) + if (!Props[i].IsOptional) + return true; + return false; + } + + void AddProp32(PROPID propid, UInt32 level); + + void AddPropString(PROPID propid, const wchar_t *s) + { + CProp prop; + prop.IsOptional = true; + prop.Id = propid; + prop.Value = s; + Props.Add(prop); + } + + HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; }; -struct CMethodsMode +class CMethodProps: public CProps { - CObjectVector<CMethod> Methods; - #ifndef _7ZIP_ST - UInt32 NumThreads; - #endif - - CMethodsMode() - #ifndef _7ZIP_ST - : NumThreads(1) - #endif - {} - bool IsEmpty() const { return Methods.IsEmpty() ; } + HRESULT SetParam(const UString &name, const UString &value); +public: + int GetLevel() const; + int Get_NumThreads() const + { + int i = FindProp(NCoderPropID::kNumThreads); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return (int)Props[i].Value.ulVal; + return -1; + } + + bool Get_DicSize(UInt32 &res) const + { + res = 0; + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + { + res = Props[i].Value.ulVal; + return true; + } + return false; + } + + int FindProp(PROPID id) const; + + UInt32 Get_Lzma_Algo() const + { + int i = FindProp(NCoderPropID::kAlgorithm); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + return GetLevel() >= 5 ? 1 : 0; + } + + UInt32 Get_Lzma_DicSize() const + { + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + int level = GetLevel(); + return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); + } + + UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const + { + fixedNumber = false; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + { + fixedNumber = true; + return numThreads < 2 ? 1 : 2; + } + return Get_Lzma_Algo() == 0 ? 1 : 2; + } + + UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const + { + fixedNumber = false; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + { + fixedNumber = true; + if (numThreads < 1) return 1; + if (numThreads > 64) return 64; + return numThreads; + } + return 1; + } + + UInt32 Get_BZip2_BlockSize() const + { + int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + { + UInt32 blockSize = Props[i].Value.ulVal; + const UInt32 kDicSizeMin = 100000; + const UInt32 kDicSizeMax = 900000; + if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; + if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; + return blockSize; + } + int level = GetLevel(); + return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); + } + + UInt32 Get_Ppmd_MemSize() const + { + int i = FindProp(NCoderPropID::kUsedMemorySize); + if (i >= 0) + if (Props[i].Value.vt == VT_UI4) + return Props[i].Value.ulVal; + int level = GetLevel(); + return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); + } + + void AddLevelProp(UInt32 level) + { + AddProp32(NCoderPropID::kLevel, level); + } + + void AddNumThreadsProp(UInt32 numThreads) + { + AddProp32(NCoderPropID::kNumThreads, numThreads); + } + + HRESULT ParseParamsFromString(const UString &srcString); + HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); }; -HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); +class COneMethodInfo: public CMethodProps +{ +public: + UString MethodName; + + void Clear() + { + CMethodProps::Clear(); + MethodName.Empty(); + } + bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } + HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); +}; #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp index 03f88625..7a4c0ed2 100755 --- a/CPP/7zip/Common/StreamBinder.cpp +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -2,149 +2,125 @@ #include "StdAfx.h" -#include "StreamBinder.h" -#include "../../Common/Defs.h" #include "../../Common/MyCom.h" -using namespace NWindows; -using namespace NSynchronization; +#include "StreamBinder.h" -class CSequentialInStreamForBinder: +class CBinderInStream: public ISequentialInStream, public CMyUnknownImp { + CStreamBinder *_binder; public: MY_UNKNOWN_IMP - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -private: - CStreamBinder *m_StreamBinder; -public: - ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } - void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } + ~CBinderInStream() { _binder->CloseRead(); } + CBinderInStream(CStreamBinder *binder): _binder(binder) {} }; -STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->Read(data, size, processedSize); } +STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Read(data, size, processedSize); } -class CSequentialOutStreamForBinder: +class CBinderOutStream: public ISequentialOutStream, public CMyUnknownImp { + CStreamBinder *_binder; public: MY_UNKNOWN_IMP - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - -private: - CStreamBinder *m_StreamBinder; -public: - ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } - void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } + ~CBinderOutStream() { _binder->CloseWrite(); } + CBinderOutStream(CStreamBinder *binder): _binder(binder) {} }; -STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->Write(data, size, processedSize); } +STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Write(data, size, processedSize); } -////////////////////////// -// CStreamBinder -// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. -HRes CStreamBinder::CreateEvents() +WRes CStreamBinder::CreateEvents() { - RINOK(_allBytesAreWritenEvent.Create(true)); - RINOK(_thereAreBytesToReadEvent.Create()); - return _readStreamIsClosedEvent.Create(); + RINOK(_canWrite_Event.Create(true)); + RINOK(_canRead_Event.Create()); + return _readingWasClosed_Event.Create(); } void CStreamBinder::ReInit() { - _thereAreBytesToReadEvent.Reset(); - _readStreamIsClosedEvent.Reset(); + _waitWrite = true; + _canRead_Event.Reset(); + _readingWasClosed_Event.Reset(); ProcessedSize = 0; } - -void CStreamBinder::CreateStreams(ISequentialInStream **inStream, - ISequentialOutStream **outStream) +void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { - CSequentialInStreamForBinder *inStreamSpec = new - CSequentialInStreamForBinder; + _waitWrite = true; + _bufSize = 0; + _buf = NULL; + ProcessedSize = 0; + + CBinderInStream *inStreamSpec = new CBinderInStream(this); CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); - inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); - CSequentialOutStreamForBinder *outStreamSpec = new - CSequentialOutStreamForBinder; + CBinderOutStream *outStreamSpec = new CBinderOutStream(this); CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); - outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); - - _buffer = NULL; - _bufferSize= 0; - ProcessedSize = 0; } +// (_canRead_Event && _bufSize == 0) means that stream is finished. + HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 sizeToRead = size; - if (size > 0) + if (processedSize) + *processedSize = 0; + if (size != 0) { - RINOK(_thereAreBytesToReadEvent.Lock()); - sizeToRead = MyMin(_bufferSize, size); - if (_bufferSize > 0) + if (_waitWrite) { - memcpy(data, _buffer, sizeToRead); - _buffer = ((const Byte *)_buffer) + sizeToRead; - _bufferSize -= sizeToRead; - if (_bufferSize == 0) + RINOK(_canRead_Event.Lock()); + _waitWrite = false; + } + if (size > _bufSize) + size = _bufSize; + if (size != 0) + { + memcpy(data, _buf, size); + _buf = ((const Byte *)_buf) + size; + ProcessedSize += size; + if (processedSize) + *processedSize = size; + _bufSize -= size; + if (_bufSize == 0) { - _thereAreBytesToReadEvent.Reset(); - _allBytesAreWritenEvent.Set(); + _waitWrite = true; + _canRead_Event.Reset(); + _canWrite_Event.Set(); } } } - if (processedSize != NULL) - *processedSize = sizeToRead; - ProcessedSize += sizeToRead; return S_OK; } -void CStreamBinder::CloseRead() -{ - _readStreamIsClosedEvent.Set(); -} - HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (size > 0) + if (processedSize) + *processedSize = 0; + if (size != 0) { - _buffer = data; - _bufferSize = size; - _allBytesAreWritenEvent.Reset(); - _thereAreBytesToReadEvent.Set(); - - HANDLE events[2]; - events[0] = _allBytesAreWritenEvent; - events[1] = _readStreamIsClosedEvent; + _buf = data; + _bufSize = size; + _canWrite_Event.Reset(); + _canRead_Event.Set(); + + HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) - { - // ReadingWasClosed = true; return S_FALSE; - } - // if(!_allBytesAreWritenEvent.Lock()) - // return E_FAIL; + if (processedSize) + *processedSize = size; } - if (processedSize != NULL) - *processedSize = size; return S_OK; } - -void CStreamBinder::CloseWrite() -{ - // _bufferSize must be = 0 - _thereAreBytesToReadEvent.Set(); -} diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h index 48f68e60..f3fb5322 100755 --- a/CPP/7zip/Common/StreamBinder.h +++ b/CPP/7zip/Common/StreamBinder.h @@ -1,32 +1,34 @@ // StreamBinder.h -#ifndef __STREAMBINDER_H -#define __STREAMBINDER_H +#ifndef __STREAM_BINDER_H +#define __STREAM_BINDER_H -#include "../IStream.h" #include "../../Windows/Synchronization.h" +#include "../IStream.h" + class CStreamBinder { - NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; - NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; - NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; - UInt32 _bufferSize; - const void *_buffer; + NWindows::NSynchronization::CManualResetEvent _canWrite_Event; + NWindows::NSynchronization::CManualResetEvent _canRead_Event; + NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + bool _waitWrite; + UInt32 _bufSize; + const void *_buf; public: - // bool ReadingWasClosed; UInt64 ProcessedSize; - CStreamBinder() {} - HRes CreateEvents(); - void CreateStreams(ISequentialInStream **inStream, - ISequentialOutStream **outStream); + WRes CreateEvents(); + void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void ReInit(); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); - void CloseRead(); - HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseWrite(); - void ReInit(); + void CloseRead() { _readingWasClosed_Event.Set(); } + void CloseWrite() + { + // _bufSize must be = 0 + _canRead_Event.Set(); + } }; #endif diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 3c86c3ae..1b6b0af0 100755 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <stdlib.h> + #include "../../../C/Alloc.h" #include "StreamObjects.h" @@ -78,7 +80,7 @@ Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const { dest.SetCapacity(_size); - memcpy(dest, _buffer, _size); + memcpy(dest, (const Byte *)_buffer, _size); } STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp index cf39bd02..77e3c1ac 100755 --- a/CPP/7zip/Common/VirtThread.cpp +++ b/CPP/7zip/Common/VirtThread.cpp @@ -10,7 +10,7 @@ static THREAD_FUNC_DECL CoderThread(void *p) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); - if (t->ExitEvent) + if (t->Exit) return 0; t->Execute(); t->FinishedEvent.Set(); @@ -23,7 +23,7 @@ WRes CVirtThread::Create() RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); - ExitEvent = false; + Exit = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); @@ -31,16 +31,18 @@ WRes CVirtThread::Create() void CVirtThread::Start() { - ExitEvent = false; + Exit = false; StartEvent.Set(); } -CVirtThread::~CVirtThread() +void CVirtThread::WaitThreadFinish() { - ExitEvent = true; + Exit = true; if (StartEvent.IsCreated()) StartEvent.Set(); if (Thread.IsCreated()) + { Thread.Wait(); + Thread.Close(); + } } - diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h index f14a1f22..ebee158c 100755 --- a/CPP/7zip/Common/VirtThread.h +++ b/CPP/7zip/Common/VirtThread.h @@ -1,7 +1,7 @@ // VirtThread.h -#ifndef __VIRTTHREAD_H -#define __VIRTTHREAD_H +#ifndef __VIRT_THREAD_H +#define __VIRT_THREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" @@ -11,13 +11,14 @@ struct CVirtThread NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; - bool ExitEvent; + bool Exit; - ~CVirtThread(); + ~CVirtThread() { WaitThreadFinish(); } + void WaitThreadFinish(); // call it in destructor of child class ! WRes Create(); void Start(); - void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; + void WaitExecuteFinish() { FinishedEvent.Lock(); } }; #endif diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index eaa10855..6dafc45f 100755 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -122,11 +122,24 @@ DWORD CThreadInfo::ThreadFunc() #endif -CEncoder::CEncoder(): - NumPasses(1), - m_OptimizeNumTables(false), - m_BlockSizeMult(kBlockSizeMultMax) +void CEncProps::Normalize(int level) { + if (level < 0) level = 5; + if (level > 9) level = 9; + if (NumPasses == (UInt32)(Int32)-1) + NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1)); + if (NumPasses < kBlockSizeMultMin) NumPasses = kBlockSizeMultMin; + if (NumPasses > kBlockSizeMultMax) NumPasses = kBlockSizeMultMax; + if (BlockSizeMult == (UInt32)(Int32)-1) + BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); + if (BlockSizeMult == 0) BlockSizeMult = 1; + if (BlockSizeMult > kNumPassesMax) BlockSizeMult = kNumPassesMax; +} + +CEncoder::CEncoder() +{ + _props.Normalize(-1); + #ifndef _7ZIP_ST ThreadsInfo = 0; m_NumThreadsPrev = 0; @@ -198,7 +211,7 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer) Byte prevByte; if (m_InStream.ReadByte(prevByte)) { - UInt32 blockSize = m_BlockSizeMult * kBlockSizeStep - 1; + UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; int numReps = 1; buffer[i++] = prevByte; while (i < blockSize) // "- 1" to support RLE @@ -678,7 +691,7 @@ HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize) m_NumCrcs = 0; - EncodeBlock2(m_Block, blockSize, Encoder->NumPasses); + EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses); #ifndef _7ZIP_ST if (Encoder->MtMode) @@ -738,7 +751,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * ti.Encoder = this; #endif - ti.m_OptimizeNumTables = m_OptimizeNumTables; + ti.m_OptimizeNumTables = _props.DoOptimizeNumTables(); if (!ti.Alloc()) return E_OUTOFMEMORY; @@ -770,7 +783,7 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * WriteByte(kArSig0); WriteByte(kArSig1); WriteByte(kArSig2); - WriteByte((Byte)(kArSig3 + m_BlockSizeMult)); + WriteByte((Byte)(kArSig3 + _props.BlockSizeMult)); #ifndef _7ZIP_ST @@ -832,62 +845,46 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream catch(...) { return S_FALSE; } } -HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { - for(UInt32 i = 0; i < numProps; i++) + int level = -1; + CEncProps props; + for (UInt32 i = 0; i < numProps; i++) { - const PROPVARIANT &prop = props[i]; - switch(propIDs[i]) + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch (propID) { - case NCoderPropID::kNumPasses: - { - if (prop.vt != VT_UI4) - return E_INVALIDARG; - UInt32 numPasses = prop.ulVal; - if (numPasses == 0) - numPasses = 1; - if (numPasses > kNumPassesMax) - numPasses = kNumPassesMax; - NumPasses = numPasses; - m_OptimizeNumTables = (NumPasses > 1); - break; - } - case NCoderPropID::kDictionarySize: - { - if (prop.vt != VT_UI4) - return E_INVALIDARG; - UInt32 dictionary = prop.ulVal / kBlockSizeStep; - if (dictionary < kBlockSizeMultMin) - dictionary = kBlockSizeMultMin; - else if (dictionary > kBlockSizeMultMax) - dictionary = kBlockSizeMultMax; - m_BlockSizeMult = dictionary; - break; - } + case NCoderPropID::kNumPasses: props.NumPasses = v; break; + case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break; + case NCoderPropID::kLevel: level = v; break; case NCoderPropID::kNumThreads: { #ifndef _7ZIP_ST - if (prop.vt != VT_UI4) - return E_INVALIDARG; - NumThreads = prop.ulVal; - if (NumThreads < 1) - NumThreads = 1; + SetNumberOfThreads(v); #endif break; } - default: - return E_INVALIDARG; + default: return E_INVALIDARG; } } + props.Normalize(level); + _props = props; return S_OK; } #ifndef _7ZIP_ST STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads) { + const UInt32 kNumThreadsMax = 64; + if (numThreads < 1) numThreads = 1; + if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax; NumThreads = numThreads; - if (NumThreads < 1) - NumThreads = 1; return S_OK; } #endif diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index a863172f..5aa8a786 100755 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -145,6 +145,20 @@ public: HRESULT EncodeBlock3(UInt32 blockSize); }; +struct CEncProps +{ + UInt32 BlockSizeMult; + UInt32 NumPasses; + + CEncProps() + { + BlockSizeMult = (UInt32)(Int32)-1; + NumPasses = (UInt32)(Int32)-1; + } + void Normalize(int level); + bool DoOptimizeNumTables() const { return NumPasses > 1; } +}; + class CEncoder : public ICompressCoder, public ICompressSetCoderProperties, @@ -153,17 +167,12 @@ class CEncoder : #endif public CMyUnknownImp { - UInt32 m_BlockSizeMult; - bool m_OptimizeNumTables; - - UInt32 m_NumPassesPrev; - UInt32 m_NumThreadsPrev; public: CInBuffer m_InStream; Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. CBitmEncoder<COutBuffer> m_OutStream; - UInt32 NumPasses; + CEncProps _props; CBZip2CombinedCrc CombinedCrc; #ifndef _7ZIP_ST diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 35a81cae..813b6de4 100755 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -21,12 +21,12 @@ namespace NCompress { namespace NDeflate { namespace NEncoder { -const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. -const UInt32 kNumTables = (1 << kNumDivPassesMax); +static const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. +static const UInt32 kNumTables = (1 << kNumDivPassesMax); -static UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. -static UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. -static UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. +static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. +static const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. +static const UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio. static const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32)) static const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32)) @@ -37,9 +37,9 @@ static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize static const int kMaxCodeBitLength = 11; static const int kMaxLevelBitLength = 7; -static Byte kNoLiteralStatPrice = 11; -static Byte kNoLenStatPrice = 11; -static Byte kNoPosStatPrice = 6; +static const Byte kNoLiteralStatPrice = 11; +static const Byte kNoLenStatPrice = 11; +static const Byte kNoPosStatPrice = 6; static Byte g_LenSlots[kNumLenSymbolsMax]; static Byte g_FastPos[1 << 9]; @@ -83,21 +83,61 @@ static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; +void CEncProps::Normalize() +{ + int level = Level; + if (level < 0) level = 5; + Level = level; + if (algo < 0) algo = (level < 5 ? 0 : 1); + if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128)); + if (btMode < 0) btMode = (algo == 0 ? 0 : 1); + if (mc == 0) mc = (16 + (fb >> 1)); + if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10)); +} + +void CCoder::SetProps(const CEncProps *props2) +{ + CEncProps props = *props2; + props.Normalize(); + + m_MatchFinderCycles = props.mc; + { + unsigned fb = props.fb; + if (fb < kMatchMinLen) + fb = kMatchMinLen; + if (fb > m_MatchMaxLen) + fb = m_MatchMaxLen; + m_NumFastBytes = fb; + } + _fastMode = (props.algo == 0); + _btMode = (props.btMode != 0); + + m_NumDivPasses = props.numPasses; + if (m_NumDivPasses == 0) + m_NumDivPasses = 1; + if (m_NumDivPasses == 1) + m_NumPasses = 1; + else if (m_NumDivPasses <= kNumDivPassesMax) + m_NumPasses = 2; + else + { + m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax); + m_NumDivPasses = kNumDivPassesMax; + } +} + CCoder::CCoder(bool deflate64Mode): m_Deflate64Mode(deflate64Mode), - m_NumPasses(1), - m_NumDivPasses(1), - m_NumFastBytes(32), - _fastMode(false), - _btMode(true), m_OnePosMatchesMemory(0), m_DistanceMemory(0), m_Created(false), m_Values(0), - m_Tables(0), - m_MatchFinderCycles(0) - // m_SetMfPasses(0) + m_Tables(0) { + { + CEncProps props; + SetProps(&props); + } m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32; m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32; m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32; @@ -160,56 +200,30 @@ HRESULT CCoder::Create() COM_TRY_END } -HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +HRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { + CEncProps props; for (UInt32 i = 0; i < numProps; i++) { - const PROPVARIANT &prop = props[i]; - switch(propIDs[i]) + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch (propID) { - case NCoderPropID::kNumPasses: - if (prop.vt != VT_UI4) - return E_INVALIDARG; - m_NumDivPasses = prop.ulVal; - if (m_NumDivPasses == 0) - m_NumDivPasses = 1; - if (m_NumDivPasses == 1) - m_NumPasses = 1; - else if (m_NumDivPasses <= kNumDivPassesMax) - m_NumPasses = 2; - else - { - m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax); - m_NumDivPasses = kNumDivPassesMax; - } - break; - case NCoderPropID::kNumFastBytes: - if (prop.vt != VT_UI4) - return E_INVALIDARG; - m_NumFastBytes = prop.ulVal; - if(m_NumFastBytes < kMatchMinLen || m_NumFastBytes > m_MatchMaxLen) - return E_INVALIDARG; - break; - case NCoderPropID::kMatchFinderCycles: - { - if (prop.vt != VT_UI4) - return E_INVALIDARG; - m_MatchFinderCycles = prop.ulVal; - break; - } - case NCoderPropID::kAlgorithm: - { - if (prop.vt != VT_UI4) - return E_INVALIDARG; - UInt32 maximize = prop.ulVal; - _fastMode = (maximize == 0); - _btMode = !_fastMode; - break; - } - default: - return E_INVALIDARG; + case NCoderPropID::kNumPasses: props.numPasses = v; break; + case NCoderPropID::kNumFastBytes: props.fb = v; break; + case NCoderPropID::kMatchFinderCycles: props.mc = v; break; + case NCoderPropID::kAlgorithm: props.algo = v; break; + case NCoderPropID::kLevel: props.Level = v; break; + case NCoderPropID::kNumThreads: break; + default: return E_INVALIDARG; } } + SetProps(&props); return S_OK; } diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index 71c39e4e..f25d802e 100755 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -52,6 +52,25 @@ typedef struct _CSeqInStream CMyComPtr<ISequentialInStream> RealStream; } CSeqInStream; +struct CEncProps +{ + int Level; + int algo; + int fb; + int btMode; + UInt32 mc; + UInt32 numPasses; + + CEncProps() + { + Level = -1; + mc = 0; + algo = fb = btMode = -1; + numPasses = (UInt32)(Int32)-1; + } + void Normalize(); +}; + class CCoder { CMatchFinder _lzInWindow; @@ -116,7 +135,6 @@ public: COptimal m_Optimum[kNumOpts]; UInt32 m_MatchFinderCycles; - // IMatchFinderSetNumPasses *m_SetMfPasses; void GetMatches(); void MovePos(UInt32 num); @@ -164,6 +182,7 @@ public: UInt32 GetBlockPrice(int tableIndex, int numDivPasses); void CodeBlock(int tableIndex, bool finalBlock); + void SetProps(const CEncProps *props2); public: CCoder(bool deflate64Mode = false); ~CCoder(); diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp index 2e421acf..d8378a60 100755 --- a/CPP/7zip/Compress/DeltaFilter.cpp +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -62,9 +62,22 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = props[i]; - if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256) + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + if (prop.vt != VT_UI4) return E_INVALIDARG; - delta = prop.ulVal; + switch (propID) + { + case NCoderPropID::kDefaultProp: + delta = (UInt32)prop.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + break; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: break; + default: return E_INVALIDARG; + } } _delta = delta; return S_OK; diff --git a/CPP/7zip/Compress/DllExports2.cpp b/CPP/7zip/Compress/DllExports2.cpp index 836f3fa4..286ef08b 100755 --- a/CPP/7zip/Compress/DllExports2.cpp +++ b/CPP/7zip/Compress/DllExports2.cpp @@ -9,7 +9,13 @@ #include "../Common/RegisterCodec.h" extern "C" -BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/) +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/) { return TRUE; } @@ -25,4 +31,3 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { return CreateCoder(clsid, iid, outObject); } - diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 9bdedaeb..80e12f18 100755 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -73,6 +73,8 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) return 1; } +#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; + HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) { if (propID == NCoderPropID::kMatchFinder) @@ -81,18 +83,29 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) return E_INVALIDARG; return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; } + if (propID > NCoderPropID::kReduceSize) + return S_OK; + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) + ep.reduceSize = (UInt32)prop.uhVal.QuadPart; + return S_OK; + } if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = prop.ulVal; switch (propID) { - case NCoderPropID::kNumFastBytes: ep.fb = v; break; - case NCoderPropID::kMatchFinderCycles: ep.mc = v; break; - case NCoderPropID::kAlgorithm: ep.algo = v; break; - case NCoderPropID::kDictionarySize: ep.dictSize = v; break; - case NCoderPropID::kPosStateBits: ep.pb = v; break; - case NCoderPropID::kLitPosBits: ep.lp = v; break; - case NCoderPropID::kLitContextBits: ep.lc = v; break; + case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break; + SET_PROP_32(kLevel, level) + SET_PROP_32(kNumFastBytes, fb) + SET_PROP_32(kMatchFinderCycles, mc) + SET_PROP_32(kAlgorithm, algo) + SET_PROP_32(kDictionarySize, dictSize) + SET_PROP_32(kPosStateBits, pb) + SET_PROP_32(kLitPosBits, lp) + SET_PROP_32(kLitContextBits, lc) + SET_PROP_32(kNumThreads, numThreads) default: return E_INVALIDARG; } return S_OK; @@ -112,8 +125,6 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, { case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; - case NCoderPropID::kNumThreads: - if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; default: RINOK(SetLzmaProp(propID, prop, props)); } diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp index d1027f1f..924229e9 100755 --- a/CPP/7zip/Compress/LzxDecoder.cpp +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -360,6 +360,9 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { if (outSize == NULL) return E_FAIL; + // flush calls m_x86ConvertOutStreamSpec->flush, so we must init x86Convert. + if (!_keepHistory) + m_x86ConvertOutStreamSpec->Init(false, 0); _remainLen = kLenIdNeedInit; m_OutWindowStream.Init(_keepHistory); return S_OK; diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index d823ffe8..5bf83529 100755 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -1,5 +1,4 @@ // PpmdEncoder.cpp -// 2009-03-11 : Igor Pavlov : Public domain #include "StdAfx.h" @@ -19,11 +18,35 @@ static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; +static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 }; + +void CEncProps::Normalize(int level) +{ + if (level < 0) level = 5; + if (level > 9) level = 9; + if (MemSize == (UInt32)(Int32)-1) + MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19)); + const unsigned kMult = 16; + if (MemSize / kMult > ReduceSize) + { + for (unsigned i = 16; i <= 31; i++) + { + UInt32 m = (UInt32)1 << i; + if (ReduceSize <= m / kMult) + { + if (MemSize > m) + MemSize = m; + break; + } + } + } + if (Order == -1) Order = kOrders[level]; +} + CEncoder::CEncoder(): - _inBuf(NULL), - _usedMemSize(1 << 24), - _order(6) + _inBuf(NULL) { + _props.Normalize(-1); _rangeEnc.Stream = &_outStream.p; Ppmd7_Construct(&_ppmd); } @@ -34,30 +57,44 @@ CEncoder::~CEncoder() Ppmd7_Free(&_ppmd, &g_BigAlloc); } -STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { + int level = -1; + CEncProps props; for (UInt32 i = 0; i < numProps; i++) { - const PROPVARIANT &prop = props[i]; + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID > NCoderPropID::kReduceSize) + continue; + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) + props.ReduceSize = (UInt32)prop.uhVal.QuadPart; + continue; + } if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = (UInt32)prop.ulVal; - switch(propIDs[i]) + switch (propID) { case NCoderPropID::kUsedMemorySize: if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0) return E_INVALIDARG; - _usedMemSize = v; + props.MemSize = v; break; case NCoderPropID::kOrder: if (v < 2 || v > 32) return E_INVALIDARG; - _order = (Byte)v; + props.Order = (Byte)v; break; - default: - return E_INVALIDARG; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: level = (int)v; break; + default: return E_INVALIDARG; } } + props.Normalize(level); + _props = props; return S_OK; } @@ -65,8 +102,8 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte props[kPropSize]; - props[0] = _order; - SetUi32(props + 1, _usedMemSize); + props[0] = (Byte)_props.Order; + SetUi32(props + 1, _props.MemSize); return WriteStream(outStream, props, kPropSize); } @@ -81,14 +118,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS } if (!_outStream.Alloc(1 << 20)) return E_OUTOFMEMORY; - if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc)) + if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc)) return E_OUTOFMEMORY; _outStream.Stream = outStream; _outStream.Init(); Ppmd7z_RangeEnc_Init(&_rangeEnc); - Ppmd7_Init(&_ppmd, _order); + Ppmd7_Init(&_ppmd, _props.Order); UInt64 processed = 0; for (;;) diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index ed8b3713..fb74cf57 100755 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -1,5 +1,4 @@ // PpmdEncoder.h -// 2009-03-11 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_ENCODER_H #define __COMPRESS_PPMD_ENCODER_H @@ -15,6 +14,21 @@ namespace NCompress { namespace NPpmd { +struct CEncProps +{ + UInt32 MemSize; + UInt32 ReduceSize; + int Order; + + CEncProps() + { + MemSize = (UInt32)(Int32)-1; + ReduceSize = (UInt32)(Int32)-1; + Order = -1; + } + void Normalize(int level); +}; + class CEncoder : public ICompressCoder, public ICompressSetCoderProperties, @@ -25,20 +39,15 @@ class CEncoder : CByteOutBufWrap _outStream; CPpmd7z_RangeEnc _rangeEnc; CPpmd7 _ppmd; - - UInt32 _usedMemSize; - Byte _order; - + CEncProps _props; public: MY_UNKNOWN_IMP2( ICompressSetCoderProperties, ICompressWriteCoderProperties) - STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); - CEncoder(); ~CEncoder(); }; diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp index e83d979c..036f3c72 100755 --- a/CPP/7zip/Compress/PpmdZip.cpp +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -1,10 +1,10 @@ // PpmdZip.cpp -// 2010-03-24 : Igor Pavlov : Public domain #include "StdAfx.h" #include "../../../C/CpuArch.h" +#include "../Common/RegisterCodec.h" #include "../Common/StreamUtils.h" #include "PpmdZip.h" @@ -128,69 +128,109 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream // ---------- Encoder ---------- +void CEncProps::Normalize(int level) +{ + if (level < 0) level = 5; + if (level == 0) level = 1; + if (level > 9) level = 9; + if (MemSizeMB == (UInt32)(Int32)-1) + MemSizeMB = (1 << ((level > 8 ? 8 : level) - 1)); + const unsigned kMult = 16; + if ((MemSizeMB << 20) / kMult > ReduceSize) + { + for (UInt32 m = (1 << 20); m <= (1 << 28); m <<= 1) + { + if (ReduceSize <= m / kMult) + { + m >>= 20; + if (MemSizeMB > m) + MemSizeMB = m; + break; + } + } + } + if (Order == -1) Order = 3 + level; + if (Restor == -1) + Restor = level < 7 ? + PPMD8_RESTORE_METHOD_RESTART : + PPMD8_RESTORE_METHOD_CUT_OFF; +} + CEncoder::~CEncoder() { Ppmd8_Free(&_ppmd, &g_BigAlloc); } -HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { + int level = -1; + CEncProps props; for (UInt32 i = 0; i < numProps; i++) { - const PROPVARIANT &prop = props[i]; + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID > NCoderPropID::kReduceSize) + continue; + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) + props.ReduceSize = (UInt32)prop.uhVal.QuadPart; + continue; + } if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 v = (UInt32)prop.ulVal; - switch(propIDs[i]) + switch (propID) { - case NCoderPropID::kAlgorithm: - if (v > 1) - return E_INVALIDARG; - _restor = v; - break; case NCoderPropID::kUsedMemorySize: if (v < (1 << 20) || v > (1 << 28)) return E_INVALIDARG; - _usedMemInMB = v >> 20; + props.MemSizeMB = v >> 20; break; case NCoderPropID::kOrder: if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER) return E_INVALIDARG; - _order = (Byte)v; + props.Order = (Byte)v; + break; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: level = (int)v; break; + case NCoderPropID::kAlgorithm: + if (v > 1) + return E_INVALIDARG; + props.Restor = v; break; - default: - return E_INVALIDARG; + default: return E_INVALIDARG; } } + props.Normalize(level); + _props = props; return S_OK; } -CEncoder::CEncoder(): - _usedMemInMB(16), - _order(6), - _restor(PPMD8_RESTORE_METHOD_RESTART) +CEncoder::CEncoder() { + _props.Normalize(-1); _ppmd.Stream.Out = &_outStream.p; Ppmd8_Construct(&_ppmd); } -HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { if (!_inStream.Alloc()) return E_OUTOFMEMORY; if (!_outStream.Alloc(1 << 20)) return E_OUTOFMEMORY; - if (!Ppmd8_Alloc(&_ppmd, _usedMemInMB << 20, &g_BigAlloc)) + if (!Ppmd8_Alloc(&_ppmd, _props.MemSizeMB << 20, &g_BigAlloc)) return E_OUTOFMEMORY; _outStream.Stream = outStream; _outStream.Init(); Ppmd8_RangeEnc_Init(&_ppmd); - Ppmd8_Init(&_ppmd, _order, _restor); + Ppmd8_Init(&_ppmd, _props.Order, _props.Restor); - UInt32 val = (UInt32)((_order - 1) + ((_usedMemInMB - 1) << 4) + (_restor << 12)); + UInt32 val = (UInt32)((_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + (_props.Restor << 12)); _outStream.WriteByte((Byte)(val & 0xFF)); _outStream.WriteByte((Byte)(val >> 8)); RINOK(_outStream.Res); @@ -220,4 +260,14 @@ HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS } } +/* +static void *CreateCodec() { return (void *)(ICompressCoder *)(new CDecoder(false)); } +static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new CEncoder); } + +static CCodecInfo g_CodecInfo = + { CreateCodec, CreateCodecOut, 0x040162, L"PPMdZIP", 1, false }; + +REGISTER_CODEC(PPMdZIP) +*/ + }} diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h index c2288b5a..e15a060d 100755 --- a/CPP/7zip/Compress/PpmdZip.h +++ b/CPP/7zip/Compress/PpmdZip.h @@ -1,5 +1,4 @@ // PpmdZip.h -// 2010-03-11 : Igor Pavlov : Public domain #ifndef __COMPRESS_PPMD_ZIP_H #define __COMPRESS_PPMD_ZIP_H @@ -48,21 +47,37 @@ public: ~CDecoder(); }; +struct CEncProps +{ + UInt32 MemSizeMB; + UInt32 ReduceSize; + int Order; + int Restor; + + CEncProps() + { + MemSizeMB = (UInt32)(Int32)-1; + ReduceSize = (UInt32)(Int32)-1; + Order = -1; + Restor = -1; + } + void Normalize(int level); +}; + class CEncoder : public ICompressCoder, + public ICompressSetCoderProperties, public CMyUnknownImp { CByteOutBufWrap _outStream; CBuf _inStream; CPpmd8 _ppmd; - UInt32 _usedMemInMB; - unsigned _order; - unsigned _restor; + CEncProps _props; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); CEncoder(); ~CEncoder(); }; diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp index 501bd0e1..63da32cc 100755 --- a/CPP/7zip/Compress/QuantumDecoder.cpp +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -33,14 +33,6 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_remainLen == kLenIdNeedInit) { - if (!_keepHistory) - { - if (!_outWindowStream.Create((UInt32)1 << _numDictBits)) - return E_OUTOFMEMORY; - Init(); - } - if (!_rangeDecoder.Create(1 << 20)) - return E_OUTOFMEMORY; _rangeDecoder.Init(); _remainLen = 0; } @@ -169,6 +161,20 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) return E_FAIL; _remainLen = kLenIdNeedInit; _outWindowStream.Init(_keepHistory); + if (!_keepHistory) + Init(); + return S_OK; +} + +HRESULT CDecoder::SetParams(int numDictBits) +{ + if (numDictBits > 21) + return E_INVALIDARG; + _numDictBits = numDictBits; + if (!_outWindowStream.Create((UInt32)1 << _numDictBits)) + return E_OUTOFMEMORY; + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; return S_OK; } diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h index e9ab023b..a5f78358 100755 --- a/CPP/7zip/Compress/QuantumDecoder.h +++ b/CPP/7zip/Compress/QuantumDecoder.h @@ -253,7 +253,7 @@ public: STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); - void SetParams(int numDictBits) { _numDictBits = numDictBits; } + HRESULT SetParams(int numDictBits); void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } CDecoder(): _keepHistory(false) {} virtual ~CDecoder() {} diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp index e0e2e3ab..3a8c9fbd 100755 --- a/CPP/7zip/Crypto/RandGen.cpp +++ b/CPP/7zip/Crypto/RandGen.cpp @@ -2,8 +2,8 @@ #include "StdAfx.h" -#include <stdio.h> #include "Windows/Synchronization.h" + #include "RandGen.h" #ifndef _WIN32 @@ -25,29 +25,31 @@ // Other generated data blocks depend from previous state // Maybe it's possible to restore original timer value from generated value. +#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x)); + void CRandomGenerator::Init() { - NCrypto::NSha1::CContext hash; - hash.Init(); + CSha256 hash; + Sha256_Init(&hash); #ifdef _WIN32 DWORD w = ::GetCurrentProcessId(); - hash.Update((const Byte *)&w, sizeof(w)); + HASH_UPD(w); w = ::GetCurrentThreadId(); - hash.Update((const Byte *)&w, sizeof(w)); + HASH_UPD(w); #else pid_t pid = getpid(); - hash.Update((const Byte *)&pid, sizeof(pid)); + HASH_UPD(pid); pid = getppid(); - hash.Update((const Byte *)&pid, sizeof(pid)); + HASH_UPD(pid); #endif - for (int i = 0; i < 1000; i++) + for (unsigned i = 0; i < 1000; i++) { #ifdef _WIN32 LARGE_INTEGER v; if (::QueryPerformanceCounter(&v)) - hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart)); + HASH_UPD(v.QuadPart); #endif #ifdef USE_POSIX_TIME @@ -55,50 +57,50 @@ void CRandomGenerator::Init() timeval v; if (gettimeofday(&v, 0) == 0) { - hash.Update((const Byte *)&v.tv_sec, sizeof(v.tv_sec)); - hash.Update((const Byte *)&v.tv_usec, sizeof(v.tv_usec)); + HASH_UPD(v.tv_sec); + HASH_UPD(v.tv_usec); } #endif time_t v2 = time(NULL); - hash.Update((const Byte *)&v2, sizeof(v2)); + HASH_UPD(v2); #endif DWORD tickCount = ::GetTickCount(); - hash.Update((const Byte *)&tickCount, sizeof(tickCount)); + HASH_UPD(tickCount); - for (int j = 0; j < 100; j++) + for (unsigned j = 0; j < 100; j++) { - hash.Final(_buff); - hash.Init(); - hash.Update(_buff, NCrypto::NSha1::kDigestSize); + Sha256_Final(&hash, _buff); + Sha256_Init(&hash); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); } } - hash.Final(_buff); + Sha256_Final(&hash, _buff); _needInit = false; } static NWindows::NSynchronization::CCriticalSection g_CriticalSection; -void CRandomGenerator::Generate(Byte *data, unsigned int size) +void CRandomGenerator::Generate(Byte *data, unsigned size) { g_CriticalSection.Enter(); if (_needInit) Init(); while (size > 0) { - NCrypto::NSha1::CContext hash; + CSha256 hash; - hash.Init(); - hash.Update(_buff, NCrypto::NSha1::kDigestSize); - hash.Final(_buff); + Sha256_Init(&hash); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + Sha256_Final(&hash, _buff); - hash.Init(); + Sha256_Init(&hash); UInt32 salt = 0xF672ABD1; - hash.Update((const Byte *)&salt, sizeof(salt)); - hash.Update(_buff, NCrypto::NSha1::kDigestSize); - Byte buff[NCrypto::NSha1::kDigestSize]; - hash.Final(buff); - for (unsigned int i = 0; i < NCrypto::NSha1::kDigestSize && size > 0; i++, size--) + HASH_UPD(salt); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + Byte buff[SHA256_DIGEST_SIZE]; + Sha256_Final(&hash, buff); + for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--) *data++ = buff[i]; } g_CriticalSection.Leave(); diff --git a/CPP/7zip/Crypto/RandGen.h b/CPP/7zip/Crypto/RandGen.h index 209445c4..cfdcd60d 100755 --- a/CPP/7zip/Crypto/RandGen.h +++ b/CPP/7zip/Crypto/RandGen.h @@ -3,11 +3,11 @@ #ifndef __CRYPTO_RAND_GEN_H #define __CRYPTO_RAND_GEN_H -#include "Sha1.h" +#include "../../../C/Sha256.h" class CRandomGenerator { - Byte _buff[NCrypto::NSha1::kDigestSize]; + Byte _buff[SHA256_DIGEST_SIZE]; bool _needInit; void Init(); diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 59a743b9..0db316a5 100755 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -84,7 +84,7 @@ 03 IFolderGetPath 04 IFolderWasChanged 05 // IFolderReload - 06 IFolderOperations + 06 // IFolderOperations old 07 IFolderGetSystemIconIndex 08 IFolderGetItemFullSize 09 IFolderClone @@ -96,6 +96,7 @@ 0F 10 IFolderArcProps 11 IGetFolderArcProps + 12 IFolderOperations 09 IFolder.h :: FOLDER_MANAGER_INTERFACE @@ -128,6 +129,9 @@ Handler GUIDs: 0C xz 0D ppmd + CF TE + D0 UEFIc + D1 UEFIs D2 SquashFS D3 CramFS D4 APM @@ -150,7 +154,7 @@ Handler GUIDs: E5 Compound E6 Wim E7 Iso - E8 Bkf + E8 E9 Chm EA Split EB Rpm diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index a518de46..b43997d4 100755 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -44,7 +44,9 @@ namespace NCoderPropID kNumPasses, kAlgorithm, kNumThreads, - kEndMarker + kEndMarker, + kLevel, + kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size. }; } diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h index eda88db0..b6f541c1 100755 --- a/CPP/7zip/MyVersion.h +++ b/CPP/7zip/MyVersion.h @@ -1,8 +1,8 @@ #define MY_VER_MAJOR 9 -#define MY_VER_MINOR 20 -#define MY_VER_BUILD 0 -#define MY_VERSION "9.20" -#define MY_7ZIP_VERSION "7-Zip 9.20" -#define MY_DATE "2010-11-18" -#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov" +#define MY_VER_MINOR 21 +#define MY_VER_BUILD 00 +#define MY_VERSION "9.21 beta" +#define MY_7ZIP_VERSION "7-Zip 9.21 beta" +#define MY_DATE "2011-04-11" +#define MY_COPYRIGHT "Copyright (c) 1999-2011 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index 4a099308..c11bd490 100755 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -18,7 +18,7 @@ STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) return S_OK; } -void CAgentFolder::LoadFolder(CProxyFolder *folder) +void CAgentFolder::LoadFolder(const CProxyFolder *folder) { int i; CProxyItem item; @@ -56,22 +56,15 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems) return S_OK; } +#define SET_realIndex_AND_folder \ + UInt32 realIndex; const CProxyFolder *folder; \ + if (_flatMode) { const CProxyItem &item = _items[index]; folder = item.Folder; realIndex = item.Index; } \ + else { folder = _proxyFolderItem; realIndex = index; } + + UString CAgentFolder::GetName(UInt32 index) const { - UInt32 realIndex; - const CProxyFolder *folder; - if (_flatMode) - { - const CProxyItem &item = _items[index]; - folder = item.Folder; - realIndex = item.Index; - } - else - { - folder = _proxyFolderItem; - realIndex = index; - } - + SET_realIndex_AND_folder if (realIndex < (UInt32)folder->Folders.Size()) return folder->Folders[realIndex].Name; return folder->Files[realIndex - folder->Folders.Size()].Name; @@ -97,32 +90,17 @@ UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index); } -void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &prop) const -{ - if (!_flatMode) - return; - prop = GetPrefix(index); -} - - -STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { + COM_TRY_BEGIN NCOM::CPropVariant prop; - const CProxyFolder *folder; - UInt32 realIndex; - if (_flatMode) + SET_realIndex_AND_folder + if (propID == kpidPrefix) { - const CProxyItem &item = _items[itemIndex]; - folder = item.Folder; - realIndex = item.Index; + if (_flatMode) + prop = GetPrefix(index); } - else - { - folder = _proxyFolderItem; - realIndex = itemIndex; - } - - if (realIndex < (UInt32)folder->Folders.Size()) + else if (realIndex < (UInt32)folder->Folders.Size()) { const CProxyFolder &item = folder->Folders[realIndex]; if (!_flatMode && propID == kpidSize) @@ -130,12 +108,12 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARI else if (!_flatMode && propID == kpidPackSize) prop = item.PackSize; else - switch(propID) + switch (propID) { - case kpidIsDir: prop = true; break; + case kpidIsDir: prop = true; break; case kpidNumSubDirs: prop = item.NumSubFolders; break; - case kpidNumSubFiles: prop = item.NumSubFiles; break; - case kpidName: prop = item.Name; break; + case kpidNumSubFiles: prop = item.NumSubFiles; break; + case kpidName: prop = item.Name; break; case kpidCRC: { if (item.IsLeaf) @@ -146,8 +124,6 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARI prop = item.Crc; break; } - case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break; - default: if (item.IsLeaf) return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); @@ -155,22 +131,21 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARI } else { - realIndex -= folder->Folders.Size(); - const CProxyFile &item = folder->Files[realIndex]; - switch(propID) + const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + switch (propID) { case kpidIsDir: prop = false; break; case kpidName: prop = item.Name; break; - case kpidPrefix: GetPrefixIfAny(itemIndex, prop); break; default: return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); } } prop.Detach(value); return S_OK; + COM_TRY_END } -HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder) +HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder) { CMyComPtr<IFolderFolder> parentFolder; if (folder->Parent != _proxyFolderItem) @@ -189,20 +164,7 @@ HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultF STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { COM_TRY_BEGIN - - CProxyFolder *folder; - UInt32 realIndex; - if (_flatMode) - { - const CProxyItem &item = _items[index]; - folder = item.Folder; - realIndex = item.Index; - } - else - { - folder = _proxyFolderItem; - realIndex = index; - } + SET_realIndex_AND_folder if (realIndex >= (UInt32)folder->Folders.Size()) return E_INVALIDARG; return BindToFolder(&folder->Folders[realIndex], resultFolder); @@ -235,19 +197,7 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) if (!getStream) return S_OK; - const CProxyFolder *folder; - UInt32 realIndex; - if (_flatMode) - { - const CProxyItem &item = _items[index]; - folder = item.Folder; - realIndex = item.Index; - } - else - { - folder = _proxyFolderItem; - realIndex = index; - } + SET_realIndex_AND_folder UInt32 indexInArchive; if (realIndex < (UInt32)folder->Folders.Size()) @@ -262,7 +212,7 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) return getStream->GetStream(indexInArchive, stream); } -STATPROPSTG kProperties[] = +static const STATPROPSTG kProperties[] = { { NULL, kpidNumSubDirs, VT_UI4}, { NULL, kpidNumSubFiles, VT_UI4}, @@ -325,7 +275,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro COM_TRY_END } -STATPROPSTG kFolderProps[] = +static const STATPROPSTG kFolderProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, @@ -340,7 +290,7 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: prop = _proxyFolderItem->Size; break; case kpidPackSize: prop = _proxyFolderItem->PackSize; break; @@ -399,7 +349,7 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntV return; } realIndices.Clear(); - for(UInt32 i = 0; i < numItems; i++) + for (UInt32 i = 0; i < numItems; i++) { const CProxyItem &item = _items[indices[i]]; const CProxyFolder *folder = item.Folder; @@ -423,13 +373,8 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UStringVector pathParts; - CProxyFolder *currentProxyFolder = _proxyFolderItem; - while (currentProxyFolder->Parent) - { - pathParts.Insert(0, currentProxyFolder->Name); - currentProxyFolder = currentProxyFolder->Parent; - } - + _proxyFolderItem->GetPathParts(pathParts); + /* if (_flatMode) pathMode = NExtract::NPathMode::kNoPathnames; @@ -437,10 +382,13 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode); + FString pathU; + if (path) + pathU = us2fs(path); extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), extractCallback2, false, testMode ? true : false, false, - (path ? path : L""), + path ? pathU : FTEXT(""), pathParts, (UInt64)(Int64)-1); CUIntVector realIndices; @@ -474,10 +422,10 @@ STDMETHODIMP CAgent::Open( { COM_TRY_BEGIN _archiveFilePath = filePath; - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; if (!inStream) { - if (!fi.Find(_archiveFilePath)) + if (!fi.Find(us2fs(_archiveFilePath))) return ::GetLastError(); if (fi.IsDir()) return E_FAIL; @@ -571,7 +519,7 @@ STDMETHODIMP CAgent::Extract( extractCallbackSpec->Init(NULL, &GetArc(), extractCallback2, false, testMode ? true : false, false, - path, + us2fs(path), UStringVector(), (UInt64)(Int64)-1); return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback); @@ -607,7 +555,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; CArc &arc = _archiveLink.Arcs[level]; - switch(propID) + switch (propID) { case kpidType: prop = GetTypeOfArc(arc); break; case kpidPath: prop = arc.Path; break; diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index 454964bc..cc92b0dd 100755 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -27,12 +27,21 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) struct CProxyItem { - CProxyFolder *Folder; + const CProxyFolder *Folder; UInt32 Index; }; class CAgent; +enum AGENT_OP +{ + AGENT_OP_Uni, + AGENT_OP_Delete, + AGENT_OP_CreateFolder, + AGENT_OP_Rename, + AGENT_OP_CopyFromFile +}; + class CAgentFolder: public IFolderFolder, public IFolderProperties, @@ -46,6 +55,7 @@ class CAgentFolder: #endif public CMyUnknownImp { + void LoadFolder(const CProxyFolder *folder); public: MY_QUERYINTERFACE_BEGIN2(IFolderFolder) @@ -61,8 +71,7 @@ public: MY_QUERYINTERFACE_END MY_ADDREF_RELEASE - void LoadFolder(CProxyFolder *folder); - HRESULT BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder); + HRESULT BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder); void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const; INTERFACE_FolderFolder(;) @@ -90,8 +99,8 @@ public: CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {} - void Init(CProxyArchive *proxyHandler, - CProxyFolder *proxyFolderItem, + void Init(const CProxyArchive *proxyHandler, + const CProxyFolder *proxyFolderItem, IFolderFolder *parentFolder, CAgent *agent) { @@ -104,9 +113,7 @@ public: void GetPathParts(UStringVector &pathParts); HRESULT CommonUpdateOperation( - bool deleteOperation, - bool createFolderOperation, - bool renameOperation, + AGENT_OP operation, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, const UINT32 *indices, UINT32 numItems, @@ -116,11 +123,10 @@ public: UString GetPrefix(UInt32 index) const; UString GetName(UInt32 index) const; UString GetFullPathPrefixPlusPrefix(UInt32 index) const; - void GetPrefixIfAny(UInt32 index, NWindows::NCOM::CPropVariant &propVariant) const; public: - CProxyArchive *_proxyArchive; - CProxyFolder *_proxyFolderItem; + const CProxyArchive *_proxyArchive; + const CProxyFolder *_proxyFolderItem; CMyComPtr<IFolderFolder> _parentFolder; CMyComPtr<IInFolderArchive> _agent; CAgent *_agentSpec; @@ -156,21 +162,19 @@ public: #ifndef EXTRACT_ONLY INTERFACE_IOutFolderArchive(;) - HRESULT CommonUpdate( - const wchar_t *newArchiveName, - int numUpdateItems, - IArchiveUpdateCallback *updateCallback); + HRESULT CommonUpdate(ISequentialOutStream *outArchiveStream, + int numUpdateItems, IArchiveUpdateCallback *updateCallback); - HRESULT CreateFolder( - const wchar_t *newArchiveName, - const wchar_t *folderName, - IFolderArchiveUpdateCallback *updateCallback100); + HRESULT CreateFolder(ISequentialOutStream *outArchiveStream, + const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100); - HRESULT RenameItem( - const wchar_t *newArchiveName, - const UINT32 *indices, UINT32 numItems, - const wchar_t *newItemName, - IFolderArchiveUpdateCallback *updateCallback100); + HRESULT RenameItem(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName, + IFolderArchiveUpdateCallback *updateCallback100); + + HRESULT UpdateOneFile(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath, + IFolderArchiveUpdateCallback *updateCallback100); // ISetProperties STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); @@ -190,8 +194,8 @@ public: UString ArchiveType; - UStringVector _names; - UString _folderPrefix; + FStringVector _names; + FString _folderPrefix; UString _archiveNamePrefix; CAgentFolder *_agentFolder; @@ -203,8 +207,8 @@ public: CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues; #endif - const CArc &GetArc() { return _archiveLink.Arcs.Back(); } - IInArchive *GetArchive() { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } + const CArc &GetArc() const { return _archiveLink.Arcs.Back(); } + IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; } UString GetTypeOfArc(const CArc &arc) const { return _codecs->Formats[arc.FormatIndex].Name; } diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 5d9ae62d..17f5443a 100755 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -2,23 +2,14 @@ #include "StdAfx.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" - #include "Windows/FileDir.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "Windows/FileName.h" #include "Windows/Time.h" #include "../../Compress/CopyCoder.h" #include "../../Common/FileStreams.h" -#include "../Common/EnumDirItems.h" -#include "../Common/OpenArchive.h" -#include "../Common/UpdateCallback.h" -#include "../Common/UpdatePair.h" - #include "Agent.h" #include "UpdateCallbackAgent.h" @@ -33,7 +24,7 @@ STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) _agentFolder = NULL; return S_OK; } - else + { CMyComPtr<IFolderFolder> archiveFolder = folder; CMyComPtr<IArchiveFolderInternal> archiveFolderInternal; @@ -41,40 +32,18 @@ STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); } - UStringVector pathParts; - pathParts.Clear(); - CMyComPtr<IFolderFolder> folderItem = folder; - if (folderItem != NULL) - for (;;) - { - CMyComPtr<IFolderFolder> newFolder; - folderItem->BindToParentFolder(&newFolder); - if (newFolder == NULL) - break; - - NCOM::CPropVariant prop; - if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) - if (prop.vt == VT_BSTR) - pathParts.Insert(0, (const wchar_t *)prop.bstrVal); - folderItem = newFolder; - } - - for (int i = 0; i < pathParts.Size(); i++) - { - _archiveNamePrefix += pathParts[i]; - _archiveNamePrefix += WCHAR_PATH_SEPARATOR; - } + _archiveNamePrefix = _agentFolder->_proxyFolderItem->GetFullPathPrefix(); return S_OK; } STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) { - _folderPrefix = folderPrefix; + _folderPrefix = us2fs(folderPrefix); _names.Clear(); _names.Reserve(numNames); for (UInt32 i = 0; i < numNames; i++) - _names.Add(names[i]); + _names.Add(us2fs(names[i])); return S_OK; } @@ -89,12 +58,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent, const CProxyFile &fileItem = item.Files[i]; CArcItem ai; RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined)); - - CPropVariant property; - agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property); - ai.SizeDefined = (property.vt != VT_EMPTY); - if (ai.SizeDefined) - ai.Size = ConvertPropVariantToUInt64(property); + RINOK(agent->GetArc().GetItemSize(fileItem.Index, ai.Size, ai.SizeDefined)); ai.IsDir = false; ai.Name = prefix + fileItem.Name; ai.Censored = true; // test it @@ -139,7 +103,7 @@ HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex) STDMETHODIMP CAgent::DoOperation( CCodecs *codecs, int formatIndex, - const wchar_t *newArchiveName, + ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100) @@ -154,9 +118,9 @@ STDMETHODIMP CAgent::DoOperation( CDirItems dirItems; { - UString folderPrefix = _folderPrefix; + FString folderPrefix = _folderPrefix; NFile::NName::NormalizeDirPathPrefix(folderPrefix); - UStringVector errorPaths; + FStringVector errorPaths; CRecordVector<DWORD> errorCodes; dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes); if (errorCodes.Size() > 0) @@ -239,22 +203,6 @@ STDMETHODIMP CAgent::DoOperation( updateCallbackSpec->Archive = GetArchive(); updateCallbackSpec->Callback = &updateCallbackAgent; - COutFileStream *outStreamSpec = new COutFileStream; - CMyComPtr<IOutStream> outStream(outStreamSpec); - UString archiveName = newArchiveName; - { - UString resultPath; - int pos; - if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) - return E_FAIL; - NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); - } - if (!outStreamSpec->Create(archiveName, true)) - { - // ShowLastErrorMessage(); - return E_FAIL; - } - CMyComPtr<ISetProperties> setProperties; if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) { @@ -268,7 +216,7 @@ STDMETHODIMP CAgent::DoOperation( for(i = 0; i < m_PropNames.Size(); i++) names.Add((const wchar_t *)m_PropNames[i]); - NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()]; + CPropVariant *propValues = new CPropVariant[m_PropValues.Size()]; try { for (int i = 0; i < m_PropValues.Size(); i++) @@ -290,88 +238,38 @@ STDMETHODIMP CAgent::DoOperation( { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); - if (!sfxStreamSpec->Open(sfxModule)) + if (!sfxStreamSpec->Open(us2fs(sfxModule))) return E_FAIL; // throw "Can't open sfx module"; - RINOK(NCompress::CopyStream(sfxStream, outStream, NULL)); + RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL)); } - RINOK(outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback)); - return outStreamSpec->Close(); + return outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(),updateCallback); } -STDMETHODIMP CAgent::DoOperation2( - const wchar_t *newArchiveName, - const Byte *stateActions, - const wchar_t *sfxModule, - IFolderArchiveUpdateCallback *updateCallback100) +STDMETHODIMP CAgent::DoOperation2(ISequentialOutStream *outArchiveStream, + const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100) { - return DoOperation(_codecs, -1, newArchiveName, - stateActions, sfxModule, updateCallback100); + return DoOperation(_codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100); } -HRESULT CAgent::CommonUpdate( - const wchar_t *newArchiveName, - int numUpdateItems, - IArchiveUpdateCallback *updateCallback) +HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream, + int numUpdateItems, IArchiveUpdateCallback *updateCallback) { if (!CanUpdate()) return E_NOTIMPL; CMyComPtr<IOutArchive> outArchive; RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); - - COutFileStream *outStreamSpec = new COutFileStream; - CMyComPtr<IOutStream> outStream(outStreamSpec); - - UString archiveName = newArchiveName; - { - UString resultPath; - int pos; - if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) - throw 141716; - NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); - } - - /* - bool isOK = false; - for (int i = 0; i < (1 << 16); i++) - { - resultName = newArchiveName; - if (i > 0) - { - wchar_t s[16]; - ConvertUInt32ToString(i, s); - resultName += s; - } - if (outStreamSpec->Open(realPath)) - { - isOK = true; - break; - } - if (::GetLastError() != ERROR_FILE_EXISTS) - return ::GetLastError(); - } - if (!isOK) - return ::GetLastError(); - */ - if (!outStreamSpec->Create(archiveName, true)) - { - // ShowLastErrorMessage(); - return E_FAIL; - } - - RINOK(outArchive->UpdateItems(outStream, numUpdateItems, updateCallback)); - return outStreamSpec->Close(); + return outArchive->UpdateItems(outArchiveStream, numUpdateItems, updateCallback); } - -STDMETHODIMP CAgent::DeleteItems( - const wchar_t *newArchiveName, +STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream, const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback100) { if (!CanUpdate()) return E_NOTIMPL; + CRecordVector<CUpdatePair2> updatePairs; CUpdateCallbackAgent updateCallbackAgent; updateCallbackAgent.SetCallback(updateCallback100); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; @@ -379,7 +277,6 @@ STDMETHODIMP CAgent::DeleteItems( CUIntVector realIndices; _agentFolder->GetRealIndices(indices, numItems, realIndices); - CRecordVector<CUpdatePair2> updatePairs; int curIndex = 0; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); @@ -400,22 +297,21 @@ STDMETHODIMP CAgent::DeleteItems( updateCallbackSpec->UpdatePairs = &updatePairs; updateCallbackSpec->Archive = GetArchive(); updateCallbackSpec->Callback = &updateCallbackAgent; - return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } -HRESULT CAgent::CreateFolder( - const wchar_t *newArchiveName, - const wchar_t *folderName, - IFolderArchiveUpdateCallback *updateCallback100) +HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, + const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100) { if (!CanUpdate()) return E_NOTIMPL; + CRecordVector<CUpdatePair2> updatePairs; + CDirItems dirItems; CUpdateCallbackAgent updateCallbackAgent; updateCallbackAgent.SetCallback(updateCallback100); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); - CRecordVector<CUpdatePair2> updatePairs; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); for (UInt32 i = 0; i < numItemsInArchive; i++) @@ -435,7 +331,6 @@ HRESULT CAgent::CreateFolder( updatePairs.ReserveDown(); - CDirItems dirItems; CDirItem di; di.Attrib = FILE_ATTRIBUTE_DIRECTORY; @@ -452,20 +347,19 @@ HRESULT CAgent::CreateFolder( updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->UpdatePairs = &updatePairs; updateCallbackSpec->Archive = GetArchive(); - return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } -HRESULT CAgent::RenameItem( - const wchar_t *newArchiveName, - const UInt32 *indices, UInt32 numItems, - const wchar_t *newItemName, +HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName, IFolderArchiveUpdateCallback *updateCallback100) { if (!CanUpdate()) return E_NOTIMPL; if (numItems != 1) return E_INVALIDARG; + CRecordVector<CUpdatePair2> updatePairs; CUpdateCallbackAgent updateCallbackAgent; updateCallbackAgent.SetCallback(updateCallback100); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; @@ -478,7 +372,6 @@ HRESULT CAgent::RenameItem( UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]); UString newItemPath = fullPrefix + newItemName; - CRecordVector<CUpdatePair2> updatePairs; UStringVector newNames; int curIndex = 0; @@ -516,7 +409,64 @@ HRESULT CAgent::RenameItem( updateCallbackSpec->UpdatePairs = &updatePairs; updateCallbackSpec->NewNames = &newNames; updateCallbackSpec->Archive = GetArchive(); - return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback); + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); +} + +HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + CRecordVector<CUpdatePair2> updatePairs; + CDirItems dirItems; + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); + + UInt32 realIndex; + { + CUIntVector realIndices; + _agentFolder->GetRealIndices(indices, numItems, realIndices); + if (realIndices.Size() != 1) + return E_FAIL; + realIndex = realIndices[0]; + } + + { + FStringVector filePaths; + filePaths.Add(us2fs(diskFilePath)); + FStringVector errorPaths; + CRecordVector<DWORD> errorCodes; + dirItems.EnumerateDirItems2(FString(), UString(), filePaths, errorPaths, errorCodes); + if (dirItems.Items.Size() != 1) + return E_FAIL; + } + + UInt32 numItemsInArchive; + RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + for (UInt32 i = 0; i < numItemsInArchive; i++) + { + CUpdatePair2 up2; + up2.ArcIndex = i; + up2.IsAnti = false; + up2.NewData = false; + up2.NewProps = false; + if (realIndex == i) + { + up2.DirIndex = 0; + up2.NewData = true; + up2.NewProps = true; + } + updatePairs.Add(up2); + } + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->Callback = &updateCallbackAgent; + updateCallbackSpec->UpdatePairs = &updatePairs; + updateCallbackSpec->Archive = GetArchive(); + updateCallbackSpec->KeepOriginalItemNames = true; + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } STDMETHODIMP CAgent::SetProperties(const wchar_t **names, diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 9686cf34..ce9b3bfb 100755 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -7,8 +7,6 @@ #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" -#include "../Common/OpenArchive.h" - #include "AgentProxy.h" using namespace NWindows; @@ -79,11 +77,10 @@ void CProxyFolder::Clear() void CProxyFolder::GetPathParts(UStringVector &pathParts) const { pathParts.Clear(); - UString result; const CProxyFolder *current = this; while (current->Parent != NULL) { - pathParts.Insert(0, (const wchar_t *)current->Name); + pathParts.Insert(0, current->Name); current = current->Parent; } } @@ -100,13 +97,6 @@ UString CProxyFolder::GetFullPathPrefix() const return result; } -UString CProxyFolder::GetItemName(UInt32 index) const -{ - if (index < (UInt32)Folders.Size()) - return Folders[index].Name; - return Files[index - Folders.Size()].Name; -} - void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const { if (IsLeaf) diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index d4caca16..dcf52f04 100755 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -3,8 +3,6 @@ #ifndef __AGENT_PROXY_H #define __AGENT_PROXY_H -#include "Common/MyString.h" - #include "../Common/OpenArchive.h" struct CProxyFile @@ -13,8 +11,11 @@ struct CProxyFile UString Name; }; -struct CProxyFolder: public CProxyFile +class CProxyFolder: public CProxyFile { + int FindDirSubItemIndex(const UString &name, int &insertPos) const; + void AddRealIndices(CUIntVector &realIndices) const; +public: CProxyFolder *Parent; CObjectVector<CProxyFolder> Folders; CObjectVector<CProxyFile> Files; @@ -28,7 +29,6 @@ struct CProxyFolder: public CProxyFile UInt32 NumSubFiles; CProxyFolder(): Parent(NULL) {}; - int FindDirSubItemIndex(const UString &name, int &insertPos) const; int FindDirSubItemIndex(const UString &name) const; CProxyFolder* AddDirSubItem(UInt32 index, bool leaf, const UString &name); void AddFileSubItem(UInt32 index, const UString &name); @@ -36,8 +36,6 @@ struct CProxyFolder: public CProxyFile void GetPathParts(UStringVector &pathParts) const; UString GetFullPathPrefix() const; - UString GetItemName(UInt32 index) const; - void AddRealIndices(CUIntVector &realIndices) const; void GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; void CalculateSizes(IInArchive *archive); }; diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp index 57975e7d..237afa05 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp @@ -8,46 +8,20 @@ #include "Agent.h" -using namespace NWindows; -using namespace NCOM; - STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems, const wchar_t *path, IFolderOperationsExtractCallback *callback) { COM_TRY_BEGIN - CArchiveExtractCallback *extractCallbackSpec = new - CArchiveExtractCallback; - CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; - UStringVector pathParts; - CProxyFolder *currentProxyFolder = _proxyFolderItem; - while (currentProxyFolder->Parent) - { - pathParts.Insert(0, currentProxyFolder->Name); - currentProxyFolder = currentProxyFolder->Parent; - } - CMyComPtr<IFolderArchiveExtractCallback> extractCallback2; { CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback; - RINOK(callbackWrap.QueryInterface( - IID_IFolderArchiveExtractCallback, &extractCallback2)); + RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); } - NExtract::NPathMode::EEnum pathMode = _flatMode ? NExtract::NPathMode::kNoPathnames : NExtract::NPathMode::kCurrentPathnames; - - extractCallbackSpec->InitForMulti(false, pathMode, NExtract::NOverwriteMode::kAskBefore); - extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(), - extractCallback2, - false, false, false, - path, - pathParts, - (UInt64)(Int64)-1); - CUIntVector realIndices; - GetRealIndices(indices, numItems, realIndices); - return _agentSpec->GetArchive()->Extract(&realIndices.Front(), - realIndices.Size(), BoolToInt(false), extractCallback); + return Extract(indices,numItems, pathMode, NExtract::NOverwriteMode::kAskBefore, + path, BoolToInt(false), extractCallback2); COM_TRY_END } @@ -56,4 +30,3 @@ STDMETHODIMP CAgentFolder::MoveTo(const UInt32 * /* indices */, UInt32 /* numIte { return E_NOTIMPL; } - diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp index 477e052c..3a16a667 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -1,22 +1,9 @@ -// Zip/ArchiveFolder.cpp +// Agent/ArchiveFolderOpen.cpp #include "StdAfx.h" #include "Agent.h" -#include "Common/StringConvert.h" - -extern HINSTANCE g_hInstance; - -static inline UINT GetCurrentFileCodePage() -{ - #ifdef UNDER_CE - return CP_ACP; - #else - return AreFileApisANSI() ? CP_ACP : CP_OEMCP; - #endif -} - void CArchiveFolderManager::LoadFormats() { if (!_codecs) @@ -39,7 +26,7 @@ STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, IFolderFolder **resultFolder, IProgress *progress) { CMyComPtr<IArchiveOpenCallback> openArchiveCallback; - if (progress != 0) + if (progress) { CMyComPtr<IProgress> progressWrapper = progress; progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback); @@ -104,16 +91,18 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa if (lib.FindIconIndex(ext, ii)) { *iconIndex = ii; - return StringToBstr(GetUnicodeString(lib.Path, GetCurrentFileCodePage()), iconPath); + return StringToBstr(fs2us(lib.Path), iconPath); } } int ii; if (_codecs->InternalIcons.FindIconIndex(ext, ii)) { - *iconIndex = ii; - UString path; - NWindows::NDLL::MyGetModuleFileName(g_hInstance, path); - return StringToBstr(path, iconPath); + FString path; + if (NWindows::NDLL::MyGetModuleFileName(path)) + { + *iconIndex = ii; + return StringToBstr(fs2us(path), iconPath); + } } return S_OK; } diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index cf3e2d5a..656602cb 100755 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -6,6 +6,7 @@ #include "Windows/FileDir.h" +#include "../../Common/FileStreams.h" #include "../Common/WorkDir.h" #include "Agent.h" @@ -14,32 +15,20 @@ using namespace NWindows; using namespace NFile; using namespace NDirectory; -static LPCWSTR kTempArcivePrefix = L"7zA"; - void CAgentFolder::GetPathParts(UStringVector &pathParts) { _proxyFolderItem->GetPathParts(pathParts); } HRESULT CAgentFolder::CommonUpdateOperation( - bool deleteOperation, - bool createFolderOperation, - bool renameOperation, + AGENT_OP operation, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, const UINT32 *indices, UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback100) { - NWorkDir::CInfo workDirInfo; - workDirInfo.Load(); - UString archiveFilePath = _agentSpec->_archiveFilePath; - UString workDir = GetWorkDir(workDirInfo, archiveFilePath); - CreateComplexDirectory(workDir); - - CTempFileW tempFile; - UString tempFileName; - if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) - return E_FAIL; + CWorkDirTempFile tempFile; + RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath))); /* if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK) @@ -53,44 +42,39 @@ HRESULT CAgentFolder::CommonUpdateOperation( GetPathParts(pathParts); HRESULT result; - if (deleteOperation) - result = _agentSpec->DeleteItems(tempFileName, - indices, numItems, updateCallback100); - else if (createFolderOperation) + switch (operation) { - result = _agentSpec->CreateFolder(tempFileName, - newItemName, updateCallback100); - } - else if (renameOperation) - { - result = _agentSpec->RenameItem( - tempFileName, - indices, numItems, - newItemName, - updateCallback100); - } - else - { - Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; - for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) - actionSetByte[i] = (Byte)actionSet->StateActions[i]; - result = _agentSpec->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback100); + case AGENT_OP_Delete: + result = _agentSpec->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback100); + break; + case AGENT_OP_CreateFolder: + result = _agentSpec->CreateFolder(tempFile.OutStream, newItemName, updateCallback100); + break; + case AGENT_OP_Rename: + result = _agentSpec->RenameItem(tempFile.OutStream, indices, numItems, newItemName, updateCallback100); + break; + case AGENT_OP_CopyFromFile: + result = _agentSpec->UpdateOneFile(tempFile.OutStream, indices, numItems, newItemName, updateCallback100); + break; + case AGENT_OP_Uni: + { + Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; + for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSetByte[i] = (Byte)actionSet->StateActions[i]; + result = _agentSpec->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback100); + break; + } + default: + return E_FAIL; } - if (result != S_OK) - return result; + RINOK(result); _agentSpec->Close(); // m_FolderItem = NULL; - if (NFind::DoesFileExist(archiveFilePath)) - if (!DeleteFileAlways(archiveFilePath)) - return GetLastError(); - - tempFile.DisableDeleting(); - if (!MyMoveFile(tempFileName, archiveFilePath)) - return GetLastError(); + RINOK(tempFile.MoveToOriginal(true)); { CMyComPtr<IArchiveOpenCallback> openCallback; @@ -134,7 +118,7 @@ STDMETHODIMP CAgentFolder::CopyFrom( { COM_TRY_BEGIN CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress != 0) + if (progress) { RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); } @@ -142,7 +126,7 @@ STDMETHODIMP CAgentFolder::CopyFrom( { RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); RINOK(_agentSpec->SetFolder(this)); - return CommonUpdateOperation(false, false, false, NULL, + return CommonUpdateOperation(AGENT_OP_Uni, NULL, &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100); } catch(const UString &s) @@ -153,18 +137,43 @@ STDMETHODIMP CAgentFolder::CopyFrom( COM_TRY_END } +STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress * progress) +{ + COM_TRY_BEGIN + CUIntVector indices; + indices.Add(destIndex); + CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; + if (progress) + { + RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); + } + try + { + RINOK(_agentSpec->SetFolder(this)); + return CommonUpdateOperation(AGENT_OP_CopyFromFile, itemPath, + &NUpdateArchive::kAddActionSet, + &indices.Front(), indices.Size(), updateCallback100); + } + catch(const UString &s) + { + RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s)); + return E_FAIL; + } + COM_TRY_END +} + STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress) { COM_TRY_BEGIN RINOK(_agentSpec->SetFolder(this)); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress != 0) + if (progress) { CMyComPtr<IProgress> progressWrapper = progress; RINOK(progressWrapper.QueryInterface( IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(true, false, false, NULL, + return CommonUpdateOperation(AGENT_OP_Delete, NULL, &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100); COM_TRY_END } @@ -176,12 +185,12 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress return ERROR_ALREADY_EXISTS; RINOK(_agentSpec->SetFolder(this)); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress != 0) + if (progress) { CMyComPtr<IProgress> progressWrapper = progress; RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(false, true, false, name, NULL, NULL, 0, updateCallback100); + return CommonUpdateOperation(AGENT_OP_CreateFolder, name, NULL, NULL, 0, updateCallback100); COM_TRY_END } @@ -192,12 +201,12 @@ STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgres indices.Add(index); RINOK(_agentSpec->SetFolder(this)); CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress != 0) + if (progress) { CMyComPtr<IProgress> progressWrapper = progress; RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); } - return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(), + return CommonUpdateOperation(AGENT_OP_Rename, newName, NULL, &indices.Front(), indices.Size(), updateCallback100); COM_TRY_END } diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h index 867ae279..2357af31 100755 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h @@ -3,7 +3,6 @@ #ifndef __IFOLDER_ARCHIVE_H #define __IFOLDER_ARCHIVE_H -#include "../../IDecl.h" #include "../../Archive/IArchive.h" #include "../../UI/Common/LoadCodecs.h" #include "../../UI/FileManager/IFolder.h" @@ -57,13 +56,14 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B) #define INTERFACE_IOutFolderArchive(x) \ STDMETHOD(SetFolder)(IFolderFolder *folder) x; \ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \ - STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, \ + STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \ const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(DoOperation)(CCodecs *codecs, int index, \ - const wchar_t *newArchiveName, const Byte *stateActions, const wchar_t *sfxModule, \ + ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \ + IFolderArchiveUpdateCallback *updateCallback) x; \ + STDMETHOD(DoOperation2)( \ + ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \ IFolderArchiveUpdateCallback *updateCallback) x; \ - STDMETHOD(DoOperation2)(const wchar_t *newArchiveName, const Byte *stateActions, \ - const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback) x; \ FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0A) { diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp index e4aa4438..3687c3d0 100755 --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -66,7 +66,7 @@ HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemErr UString(L"WARNING: ") + NError::MyFormatMessageW(systemError) + UString(L": ") + - UString(name))); + name)); return S_FALSE; } } diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 410b800d..d181843d 100755 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -21,6 +21,10 @@ #include "../../IPassword.h" #include "../../MyVersion.h" +#ifdef _WIN32 +HINSTANCE g_hInstance = 0; +#endif + // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, @@ -30,9 +34,9 @@ using namespace NWindows; #define kDllName "7z.dll" -static const char *kCopyrightString = MY_7ZIP_VERSION +static const char *kCopyrightString = "\n" MY_7ZIP_VERSION " (" kDllName " client) " -MY_COPYRIGHT " " MY_DATE; +MY_COPYRIGHT " " MY_DATE "\n"; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" @@ -48,28 +52,46 @@ typedef UINT32 (WINAPI * CreateObjectFunc)( void **outObject); -void PrintString(const UString &s) +static AString FStringToConsoleString(const FString &s) +{ + return GetOemString(fs2us(s)); +} + +static FString CmdStringToFString(const char *s) +{ + return us2fs(GetUnicodeString(s)); +} + +static void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } -void PrintString(const AString &s) +static void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } -void PrintNewLine() +static void PrintNewLine() { PrintString("\n"); } -void PrintStringLn(const AString &s) +static void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } -void PrintError(const AString &s) +static void PrintError(const char *message, const FString &name) +{ + printf("Error: %s", (LPCSTR)message); + PrintNewLine(); + PrintString(FStringToConsoleString(name)); + PrintNewLine(); +} + +static void PrintError(const AString &s) { PrintNewLine(); PrintString(s); @@ -148,8 +170,6 @@ STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) ////////////////////////////////////////////////////////////// // Archive Extracting callback class -static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; - static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; @@ -181,9 +201,9 @@ public: private: CMyComPtr<IInArchive> _archiveHandler; - UString _directoryPath; // Output directory + FString _directoryPath; // Output directory UString _filePath; // name inside arcvhive - UString _diskFilePath; // full path to file on disk + FString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { @@ -198,7 +218,7 @@ private: CMyComPtr<ISequentialOutStream> _outFileStream; public: - void Init(IInArchive *archiveHandler, const UString &directoryPath); + void Init(IInArchive *archiveHandler, const FString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; @@ -207,7 +227,7 @@ public: CArchiveExtractCallback() : PasswordIsDefined(false) {} }; -void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) +void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; @@ -305,10 +325,10 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) - NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); + NFile::NDirectory::CreateComplexDirectory(_directoryPath + us2fs(_filePath.Left(slashPos))); } - UString fullProcessedPath = _directoryPath + _filePath; + FString fullProcessedPath = _directoryPath + us2fs(_filePath); _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) @@ -317,12 +337,12 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, } else { - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; if (fi.Find(fullProcessedPath)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { - PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); + PrintError("Can not delete output file", fullProcessedPath); return E_ABORT; } } @@ -331,7 +351,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { - PrintString((UString)L"can not open output file " + fullProcessedPath); + PrintError("Can not open output file", fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; @@ -423,7 +443,7 @@ struct CDirItem FILETIME ATime; FILETIME MTime; UString Name; - UString FullPath; + FString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } @@ -458,7 +478,7 @@ public: UString VolName; UString VolExt; - UString DirPrefix; + FString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; @@ -467,7 +487,7 @@ public: bool m_NeedBeClosed; - UStringVector FailedFiles; + FStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; @@ -514,7 +534,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; if (propID == kpidIsAnti) { @@ -571,7 +591,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); - UString path = DirPrefix + dirItem.FullPath; + FString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); @@ -620,7 +640,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); - if (!streamSpec->Create(fileName, false)) + if (!streamSpec->Create(us2fs(fileName), false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; @@ -643,8 +663,6 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDef return StringToBstr(Password, password); } - - ////////////////////////////////////////////////////////////////////////// // Main function @@ -661,8 +679,8 @@ int MY_CDECL main(int numArgs, const char *args[]) PrintStringLn(kHelpString); return 1; } - NWindows::NDLL::CLibrary lib; - if (!lib.Load(TEXT(kDllName))) + NDLL::CLibrary lib; + if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName))) { PrintError("Can not load 7-zip library"); return 1; @@ -682,10 +700,10 @@ int MY_CDECL main(int numArgs, const char *args[]) PrintError("incorrect command"); return 1; } - c = MyCharLower(command[0]); + c = (char)MyCharUpper(command[0]); } - UString archiveName = GetUnicodeString(args[2]); - if (c == 'a') + FString archiveName = CmdStringToFString(args[2]); + if (c == 'A') { // create archive command if (numArgs < 4) @@ -698,12 +716,12 @@ int MY_CDECL main(int numArgs, const char *args[]) for (i = 3; i < numArgs; i++) { CDirItem di; - UString name = GetUnicodeString(args[i]); + FString name = CmdStringToFString(args[i]); - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; if (!fi.Find(name)) { - PrintString(UString(L"Can't find file") + name); + PrintError("Can't find file", name); return 1; } @@ -712,7 +730,7 @@ int MY_CDECL main(int numArgs, const char *args[]) di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; - di.Name = name; + di.Name = fs2us(name); di.FullPath = name; dirItems.Add(di); } @@ -745,7 +763,7 @@ int MY_CDECL main(int numArgs, const char *args[]) L"x" }; const int kNumProps = sizeof(names) / sizeof(names[0]); - NWindows::NCOM::CPropVariant values[kNumProps] = + NCOM::CPropVariant values[kNumProps] = { false, // solid mode OFF (UInt32)9 // compression level = 9 - ultra @@ -771,7 +789,7 @@ int MY_CDECL main(int numArgs, const char *args[]) for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); - PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); + PrintError("Error for file", updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; @@ -785,9 +803,9 @@ int MY_CDECL main(int numArgs, const char *args[]) } bool listCommand; - if (c == 'l') + if (c == 'L') listCommand = true; - else if (c == 'x') + else if (c == 'X') listCommand = false; else { @@ -807,7 +825,7 @@ int MY_CDECL main(int numArgs, const char *args[]) if (!fileSpec->Open(archiveName)) { - PrintError("Can not open archive file"); + PrintError("Can not open archive file", archiveName); return 1; } @@ -820,7 +838,7 @@ int MY_CDECL main(int numArgs, const char *args[]) if (archive->Open(file, 0, openCallback) != S_OK) { - PrintError("Can not open archive"); + PrintError("Can not open file as archive", archiveName); return 1; } } @@ -834,7 +852,7 @@ int MY_CDECL main(int numArgs, const char *args[]) { { // Get uncompressed size of file - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); @@ -842,12 +860,12 @@ int MY_CDECL main(int numArgs, const char *args[]) } { // Get name of file - NWindows::NCOM::CPropVariant prop; + NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } - PrintString("\n"); + PrintNewLine(); } } else @@ -855,7 +873,7 @@ int MY_CDECL main(int numArgs, const char *args[]) // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); - extractCallbackSpec->Init(archive, L""); // second parameter is output folder path + extractCallbackSpec->Init(archive, FTEXT("")); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 8ae2e15e..85ec17b4 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -283,9 +283,9 @@ static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; - if (!NFind::DoesFileExist(fileName)) + if (!NFind::DoesFileExist(us2fs(fileName))) throw kCannotFindListFile; - if (!ReadNamesFromListFile(fileName, names, codePage)) + if (!ReadNamesFromListFile(us2fs(fileName), names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) AddNameToCensor(wildcardCensor, names[i], include, type); @@ -420,9 +420,9 @@ static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; - NFind::CFileInfoW fi; - if (fi.Find(prefix + name)) - name = fi.Name; + NFind::CFileInfo fi; + if (fi.Find(us2fs(prefix + name))) + name = fs2us(fi.Name); } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) @@ -463,7 +463,7 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; - ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); + ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode); } } @@ -647,11 +647,11 @@ static void SetAddCommandOptions( if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else - options.WorkingDir = postString; + options.WorkingDir = us2fs(postString); } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) - options.SfxModule = parser[NKey::kSfx].PostStrings[0]; + options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]); if (parser[NKey::kVolume].ThereIs) { @@ -670,7 +670,6 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr { if (parser[NKey::kProperty].ThereIs) { - // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; @@ -774,7 +773,7 @@ void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, { CDirItems dirItems; { - UStringVector errorPaths; + FStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) @@ -796,9 +795,9 @@ void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor, int i; for (i = 0; i < paths.Size(); i++) { - UString fullPath; - NFile::NDirectory::MyGetFullPathName(paths[i], fullPath); - fullPaths.Add(fullPath); + FString fullPath; + NFile::NDirectory::MyGetFullPathName(us2fs(paths[i]), fullPath); + fullPaths.Add(fs2us(fullPath)); } CIntVector indices; SortFileNames(fullPaths, indices); @@ -886,6 +885,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; + SetMethodOptions(parser, options.Properties); + if (isExtractOrList) { if (!options.WildcardCensor.AllAreRelative()) @@ -924,12 +925,11 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) if (isExtractGroupCommand) { - SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { - options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; + options.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } @@ -946,7 +946,7 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); - SetMethodOptions(parser, updateOptions.MethodMode.Properties); + updateOptions.MethodMode.Properties = options.Properties; if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; @@ -988,50 +988,12 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) } else if (options.Command.CommandType == NCommandType::kBenchmark) { - options.NumThreads = (UInt32)-1; - options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } - for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) - { - UString postString = parser[NKey::kProperty].PostStrings[i]; - postString.MakeUpper(); - if (postString.Length() < 2) - ThrowUserErrorException(); - if (postString[0] == 'D') - { - int pos = 1; - if (postString[pos] == '=') - pos++; - UInt32 logSize; - if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) - ThrowUserErrorException(); - if (logSize > 31) - ThrowUserErrorException(); - options.DictionarySize = 1 << logSize; - } - else if (postString[0] == 'M' && postString[1] == 'T' ) - { - int pos = 2; - if (postString[pos] == '=') - pos++; - if (postString[pos] != 0) - if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) - ThrowUserErrorException(); - } - else if (postString[0] == 'M' && postString[1] == '=' ) - { - int pos = 2; - if (postString[pos] != 0) - options.Method = postString.Mid(2); - } - else - ThrowUserErrorException(); - } } else if (options.Command.CommandType == NCommandType::kInfo) { diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index e8f601df..96646d60 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -75,11 +75,11 @@ struct CArchiveCommandLineOptions // Extract bool CalcCrc; bool AppendName; - UString OutputDir; + FString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; - CObjectVector<CProperty> ExtractProperties; + CObjectVector<CProperty> Properties; CUpdateOptions UpdateOptions; UString ArcType; @@ -87,10 +87,6 @@ struct CArchiveCommandLineOptions // Benchmark UInt32 NumIterations; - UInt32 NumThreads; - UInt32 DictionarySize; - UString Method; - CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 4c0cc90b..9c9c0422 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -3,10 +3,12 @@ #include "StdAfx.h" #include "Common/ComTry.h" +#include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" @@ -18,16 +20,16 @@ using namespace NWindows; -static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; -static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; -static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; +static const char *kCantAutoRename = "ERROR: Can not create file with auto name"; +static const char *kCantRenameFile = "ERROR: Can not rename existing file "; +static const char *kCantDeleteOutputFile = "ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( const NWildcard::CCensorNode *wildcardCensor, const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, bool crcMode, - const UString &directoryPath, + const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize) { @@ -107,14 +109,14 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U COM_TRY_END } -void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) +void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { fullPath = _directoryPath; for (int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) - fullPath += wchar_t(NFile::NName::kDirDelimiter); - fullPath += dirPathParts[i]; + fullPath += FCHAR_PATH_SEPARATOR; + fullPath += us2fs(dirPathParts[i]); NFile::NDirectory::MyCreateDirectory(fullPath); } } @@ -136,12 +138,12 @@ HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil HRESULT CArchiveExtractCallback::GetUnpackSize() { - NCOM::CPropVariant prop; - RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop)); - _curSizeDefined = (prop.vt != VT_EMPTY); - if (_curSizeDefined) - _curSize = ConvertPropVariantToUInt64(prop); - return S_OK; + return _arc->GetItemSize(_index, _curSize, _curSizeDefined); +} + +HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) +{ + return _extractCallback2->MessageError(GetUnicodeString(message) + fs2us(path)); } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) @@ -256,7 +258,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!pathParts.IsEmpty()) { - UString fullPathNew; + FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_fi.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, @@ -267,7 +269,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } - UString fullProcessedPath = _directoryPath + processedPath; + FString fullProcessedPath = _directoryPath + us2fs(processedPath); if (_fi.IsDir) { @@ -279,7 +281,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!_isSplit) { - NFile::NFind::CFileInfoW fileInfo; + NFile::NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { switch(_overwriteMode) @@ -290,7 +292,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( - fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, + fs2us(fullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath, _fi.MTimeDefined ? &_fi.MTime : NULL, _curSizeDefined ? &_curSize : NULL, &overwiteResult)) @@ -321,32 +323,28 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { if (!AutoRenamePath(fullProcessedPath)) { - UString message = UString(kCantAutoRename) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { - UString existPath = fullProcessedPath; + FString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { - UString message = kCantAutoRename + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { - UString message = UString(kCantRenameFile) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantRenameFile, fullProcessedPath)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { - UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath)); return S_OK; // return E_FAIL; } @@ -360,8 +358,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { - UString message = L"can not open output file " + fullProcessedPath; - RINOK(_extractCallback2->MessageError(message)); + RINOK(SendMessageError("can not open output file ", fullProcessedPath)); return S_OK; } } @@ -485,4 +482,3 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } - diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 367e4b07..cee7c5b6 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -31,11 +31,11 @@ class CArchiveExtractCallback: CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; - UString _directoryPath; + FString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; - UString _diskFilePath; + FString _diskFilePath; UString _filePath; UInt64 _position; bool _isSplit; @@ -83,10 +83,12 @@ class CArchiveExtractCallback: UInt64 _packTotal; UInt64 _unpTotal; - void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); + void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); HRESULT GetUnpackSize(); + HRESULT SendMessageError(const char *message, const FString &path); + public: CLocalProgress *LocalProgressSpec; @@ -134,7 +136,7 @@ public: const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, bool crcMode, - const UString &directoryPath, + const FString &directoryPath, const UStringVector &removePathParts, UInt64 packSize); diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index c3684def..17947dce 100755 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -9,19 +9,19 @@ using namespace NWindows; -static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName) +static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName) { - UString resultName = L"Archive"; + FString resultName = FTEXT("Archive"); if (fromPrev) { - UString dirPrefix; + FString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) - if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) + if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR) { - dirPrefix.Delete(dirPrefix.Length() - 1); - NFile::NFind::CFileInfoW fileInfo; + dirPrefix.DeleteBack(); + NFile::NFind::CFileInfo fileInfo; if (fileInfo.Find(dirPrefix)) resultName = fileInfo.Name; } @@ -29,7 +29,7 @@ static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool ke } else { - NFile::NFind::CFileInfoW fileInfo; + NFile::NFind::CFileInfo fileInfo; if (!fileInfo.Find(srcName)) // return resultName; return srcName; @@ -39,8 +39,8 @@ static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool ke int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { - UString archiveName2 = resultName.Left(dotPos); - if (archiveName2.ReverseFind('.') < 0) + FString archiveName2 = resultName.Left(dotPos); + if (archiveName2.ReverseFind(FTEXT('.')) < 0) resultName = archiveName2; } } @@ -50,5 +50,5 @@ static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool ke UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { - return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName)); + return GetCorrectFsPath(fs2us(CreateArchiveName2(us2fs(srcName), fromPrev, keepName))); } diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index e7e61713..be20940c 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -2,7 +2,6 @@ #include "StdAfx.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" @@ -94,7 +93,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; - UString fullPath = _folderPrefix + name; + FString fullPath = _folderPrefix + us2fs(name); if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) @@ -130,4 +129,3 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) COM_TRY_END } #endif - diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index c6651e8f..afada4a6 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -77,8 +77,8 @@ public: } private: - UString _folderPrefix; - NWindows::NFile::NFind::CFileInfoW _fileInfo; + FString _folderPrefix; + NWindows::NFile::NFind::CFileInfo _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: @@ -88,7 +88,7 @@ public: UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} - void Init(const UString &folderPrefix, const UString &fileName) + void Init(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; if (!_fileInfo.Find(_folderPrefix + fileName)) diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index 282f405f..5adfcc20 100755 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "Bench.h" - #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 @@ -31,18 +29,30 @@ #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" +#if !defined(_7ZIP_ST) || defined(_WIN32) +#include "../../../Windows/System.h" +#endif + #ifndef _7ZIP_ST #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif -#include "../../../Windows/PropVariant.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../Common/MethodProps.h" + +#include "Bench.h" + +using namespace NWindows; -static const UInt32 kUncompressMinBlockSize = +static const UInt64 kUncompressMinBlockSize = #ifdef UNDER_CE -1 << 24; +(UInt64)1 << 30; #else -1 << 26; +(UInt64)1 << 33; #endif static const UInt32 kCrcBlockSize = @@ -52,6 +62,8 @@ static const UInt32 kCrcBlockSize = 1 << 30; #endif +static const unsigned kOldLzmaDictBits = 30; + static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; @@ -99,7 +111,7 @@ class CBenchRandomGenerator: public CBenchBuffer CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } - UInt32 GetVal(UInt32 &res, int numBits) + UInt32 GetVal(UInt32 &res, unsigned numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; @@ -110,7 +122,7 @@ public: UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } - void Generate() + void Generate(unsigned dictBits) { UInt32 pos = 0; UInt32 rep0 = 1; @@ -131,7 +143,7 @@ public: { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); - if (ppp > 30) + if (ppp > dictBits) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); @@ -275,15 +287,33 @@ static UInt64 GetFreq() #endif } -#ifndef USE_POSIX_TIME -static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } -#endif +#ifdef USE_POSIX_TIME -static UInt64 GetUserTime() +struct CUserTime +{ + UInt64 Sum; + clock_t Prev; + + void Init() + { + Prev = clock(); + Sum = 0; + } + + UInt64 GetUserTime() + { + clock_t v = clock(); + Sum += v - Prev; + Prev = v; + return Sum; + } +}; + +#else + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } +UInt64 GetWinUserTime() { - #ifdef USE_POSIX_TIME - return clock(); - #else FILETIME creationTime, exitTime, kernelTime, userTime; if ( #ifdef UNDER_CE @@ -294,9 +324,18 @@ static UInt64 GetUserTime() , &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; - #endif } +struct CUserTime +{ + UInt64 StartTime; + + void Init() { StartTime = GetWinUserTime(); } + UInt64 GetUserTime() { return GetWinUserTime() - StartTime; } +}; + +#endif + static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME @@ -309,7 +348,7 @@ static UInt64 GetUserFreq() class CBenchProgressStatus { #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSection CS; + NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; @@ -317,14 +356,14 @@ public: void SetResult(HRESULT res) { #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSectionLock lock(CS); + NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifndef _7ZIP_ST - NWindows::NSynchronization::CCriticalSectionLock lock(CS); + NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } @@ -337,27 +376,31 @@ class CBenchProgressInfo: public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; + CUserTime UserTime; HRESULT Res; - IBenchCallback *callback; - CBenchProgressInfo(): callback(0) {} + IBenchCallback *Callback; + + CBenchProgressInfo(): Callback(0) {} + void SetStartTime(); + void SetFinishTime(CBenchInfo &dest); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; -static void SetStartTime(CBenchInfo &bi) +void CBenchProgressInfo::SetStartTime() { - bi.GlobalFreq = GetFreq(); - bi.UserFreq = GetUserFreq(); - bi.GlobalTime = ::GetTimeCount(); - bi.UserTime = ::GetUserTime(); + BenchInfo.GlobalFreq = GetFreq(); + BenchInfo.UserFreq = GetUserFreq(); + BenchInfo.GlobalTime = ::GetTimeCount(); + BenchInfo.UserTime = 0; + UserTime.Init(); } -static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) +void CBenchProgressInfo::SetFinishTime(CBenchInfo &dest) { - dest.GlobalFreq = GetFreq(); - dest.UserFreq = GetUserFreq(); - dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; - dest.UserTime = ::GetUserTime() - biStart.UserTime; + dest = BenchInfo; + dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime; + dest.UserTime = UserTime.GetUserTime(); } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) @@ -365,21 +408,21 @@ STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 HRESULT res = Status->GetResult(); if (res != S_OK) return res; - if (!callback) + if (!Callback) return res; - CBenchInfo info = BenchInfo; - SetFinishTime(BenchInfo, info); + CBenchInfo info; + SetFinishTime(info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; - res = callback->SetEncodeResult(info, false); + res = Callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; - res = callback->SetDecodeResult(info, false); + res = Callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); @@ -406,12 +449,12 @@ static void NormalizeVals(UInt64 &v1, UInt64 &v2) } } -UInt64 GetUsage(const CBenchInfo &info) +UInt64 CBenchInfo::GetUsage() const { - UInt64 userTime = info.UserTime; - UInt64 userFreq = info.UserFreq; - UInt64 globalTime = info.GlobalTime; - UInt64 globalFreq = info.GlobalFreq; + UInt64 userTime = UserTime; + UInt64 userFreq = UserFreq; + UInt64 globalTime = GlobalTime; + UInt64 globalFreq = GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) @@ -421,19 +464,19 @@ UInt64 GetUsage(const CBenchInfo &info) return userTime * globalFreq * 1000000 / userFreq / globalTime; } -UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) +UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const { - UInt64 userTime = info.UserTime; - UInt64 userFreq = info.UserFreq; - UInt64 globalTime = info.GlobalTime; - UInt64 globalFreq = info.GlobalFreq; + UInt64 userTime = UserTime; + UInt64 userFreq = UserFreq; + UInt64 globalTime = GlobalTime; + UInt64 globalFreq = GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; - return userFreq * globalTime / globalFreq * rating / userTime; + return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) @@ -445,26 +488,74 @@ static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) return value * freq / elTime; } -UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) +struct CBenchProps +{ + bool LzmaRatingMode; + + UInt32 EncComplex; + UInt32 DecComplexCompr; + UInt32 DecComplexUnc; + + CBenchProps(): LzmaRatingMode(false) {} + void SetLzmaCompexity(); + + UInt64 GeDecomprCommands(UInt64 packSize, UInt64 unpackSize) + { + return (packSize * DecComplexCompr + unpackSize * DecComplexUnc); + } + + UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size); + UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); +}; + +void CBenchProps::SetLzmaCompexity() +{ + DecComplexUnc = 4; + DecComplexCompr = 200; + LzmaRatingMode = true; +} + +UInt64 CBenchProps::GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { - UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); - UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); - UInt64 numCommands = (UInt64)(size) * numCommandsForOne; + if (dictSize < (1 << kBenchMinDicLogSize)) + dictSize = (1 << kBenchMinDicLogSize); + UInt64 encComplex = EncComplex; + if (LzmaRatingMode) + { + UInt64 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits); + encComplex = 870 + ((t * t * 5) >> (2 * kSubBits)); + } + UInt64 numCommands = (UInt64)size * encComplex; return MyMultDiv64(numCommands, elapsedTime, freq); } -UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) +UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { - UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; + UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } +UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size) +{ + CBenchProps props; + props.SetLzmaCompexity(); + return props.GetCompressRating(dictSize, elapsedTime, freq, size); +} + +UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) +{ + CBenchProps props; + props.SetLzmaCompexity(); + return props.GetDecompressRating(elapsedTime, freq, outSize, inSize, numIterations); +} + struct CEncoderInfo; struct CEncoderInfo { #ifndef _7ZIP_ST NWindows::CThread thread[2]; + UInt32 NumDecoderSubThreads; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; @@ -490,17 +581,22 @@ struct CEncoderInfo CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; + IBenchPrintCallback *printCallback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; - HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); + HRESULT Init( + const COneMethodInfo &method, + UInt32 uncompressedDataSize, + unsigned generateDictBits, + CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); - CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} + CEncoderInfo(): outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {} #ifndef _7ZIP_ST static THREAD_FUNC_DECL EncodeThreadFunction(void *param) @@ -550,14 +646,20 @@ struct CEncoderInfo #endif }; -HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) +static const UInt32 k_LZMA = 0x030101; + +HRESULT CEncoderInfo::Init( + const COneMethodInfo &method, + UInt32 uncompressedDataSize, + unsigned generateDictBits, + CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); - kBufferSize = dictionarySize + kAdditionalSize; - UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + kBufferSize = uncompressedDataSize; + UInt32 kCompressedBufferSize = (kBufferSize - kBufferSize / 4) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; - rg.Generate(); + rg.Generate(generateDictBits); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; @@ -576,31 +678,26 @@ HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandom return E_OUTOFMEMORY; propStreamSpec->Init(); - PROPID propIDs[] = + { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumThreads - }; - const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); - PROPVARIANT props[kNumProps]; - props[0].vt = VT_UI4; - props[0].ulVal = dictionarySize; - - props[1].vt = VT_UI4; - props[1].ulVal = numThreads; + CMyComPtr<ICompressSetCoderProperties> scp; + encoder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = uncompressedDataSize; + RINOK(method.SetCoderProps(scp, &reduceSize)); + } + else + { + if (method.AreThereNonOptionalProps()) + return E_FAIL; + } - { - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); - if (!setCoderProperties) - return E_FAIL; - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps)); - - CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; - encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); - if (writeCoderProperties) + CMyComPtr<ICompressWriteCoderProperties> writeCoderProps; + encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); + if (writeCoderProps) { - RINOK(writeCoderProperties->WriteCoderProperties(propStream)); + RINOK(writeCoderProps->WriteCoderProperties(propStream)); } } return S_OK; @@ -625,9 +722,9 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; - CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; - decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); - if (!compressSetDecoderProperties) + CMyComPtr<ICompressSetDecoderProperties2> setDecProps; + decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); + if (!setDecProps && propStreamSpec->Pos != 0) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; @@ -637,12 +734,30 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; + #ifndef _7ZIP_ST + { + CMyComPtr<ICompressSetCoderMt> setCoderMt; + decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads)); + } + } + #endif + for (UInt32 j = 0; j < NumIterations; j++) { + if (printCallback) + { + RINOK(printCallback->CheckBreak()); + } inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); - RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + if (setDecProps) + { + RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + } UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) @@ -654,7 +769,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) return S_OK; } -static const UInt32 kNumThreadsMax = (1 << 16); +static const UInt32 kNumThreadsMax = (1 << 12); struct CBenchEncoders { @@ -663,44 +778,66 @@ struct CBenchEncoders ~CBenchEncoders() { delete []encoders; } }; -HRESULT LzmaBench( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) +static HRESULT MethodBench( + DECL_EXTERNAL_CODECS_LOC_VARS + bool oldLzmaBenchMode, + UInt32 numThreads, + const COneMethodInfo &method2, + UInt32 uncompressedDataSize, + unsigned generateDictBits, + IBenchPrintCallback *printCallback, + IBenchCallback *callback, + CBenchProps *benchProps) { - UInt32 numEncoderThreads = - #ifndef _7ZIP_ST - (numThreads > 1 ? numThreads / 2 : 1); - #else - 1; - #endif - UInt32 numSubDecoderThreads = - #ifndef _7ZIP_ST - (numThreads > 1 ? 2 : 1); - #else - 1; - #endif - if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) - { + COneMethodInfo method = method2; + UInt64 methodId; + UInt32 numInStreams, numOutStreams; + if (!FindMethod( + EXTERNAL_CODECS_LOC_VARS + method.MethodName, methodId, numInStreams, numOutStreams)) + return E_NOTIMPL; + if (numInStreams != 1 || numOutStreams != 1) + return E_INVALIDARG; + + UInt32 numEncoderThreads = 1; + UInt32 numSubDecoderThreads = 1; + + #ifndef _7ZIP_ST + numEncoderThreads = numThreads; + + if (oldLzmaBenchMode && methodId == k_LZMA) + { + bool fixedNumber; + UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber); + if (!fixedNumber && numThreads == 1) + method.AddNumThreadsProp(1); + if (numThreads > 1 && numLzmaThreads > 1) + { + numEncoderThreads = numThreads / 2; + numSubDecoderThreads = 2; + } + } + #endif + + if (numThreads < 1 || numEncoderThreads > kNumThreadsMax) return E_INVALIDARG; - } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; - UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; + encoder.printCallback = printCallback; - const UInt32 kLzmaId = 0x030101; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true)); + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, encoder.encoder, true)); if (!encoder.encoder) return E_NOTIMPL; for (UInt32 j = 0; j < numSubDecoderThreads; j++) { - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false)); + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, encoder.decoders[j], false)); if (!encoder.decoders[j]) return E_NOTIMPL; } @@ -710,7 +847,7 @@ HRESULT LzmaBench( rg.Init(); for (i = 0; i < numEncoderThreads; i++) { - RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); + RINOK(encoders[i].Init(method, uncompressedDataSize, generateDictBits, &rg)); } CBenchProgressStatus status; @@ -727,9 +864,10 @@ HRESULT LzmaBench( } if (i == 0) { - encoder.progressInfoSpec[0]->callback = callback; - encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; - SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); + CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; + bpi->Callback = callback; + bpi->BenchInfo.NumIterations = numEncoderThreads; + bpi->SetStartTime(); } #ifndef _7ZIP_ST @@ -756,7 +894,7 @@ HRESULT LzmaBench( CBenchInfo info; - SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); + encoders[0].progressInfoSpec[0]->SetFinishTime(info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; @@ -776,16 +914,24 @@ HRESULT LzmaBench( for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; - encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { - encoder.progressInfoSpec[0]->callback = callback; - encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; - SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); + encoder.NumIterations = (UInt32)(1 + kUncompressMinBlockSize / + benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize)); + CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; + bpi->Callback = callback; + bpi->BenchInfo.NumIterations = numDecoderThreads; + bpi->SetStartTime(); } + else + encoder.NumIterations = encoders[0].NumIterations; #ifndef _7ZIP_ST + { + int numSubThreads = method.Get_NumThreads(); + encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : numSubThreads; + } if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) @@ -818,7 +964,7 @@ HRESULT LzmaBench( RINOK(res); #endif RINOK(status.Res); - SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); + encoders[0].progressInfoSpec[0]->SetFinishTime(info); #ifndef _7ZIP_ST #ifdef UNDER_CE if (numDecoderThreads > 1) @@ -966,7 +1112,7 @@ bool CrcInternalTest() return true; } -HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) +static HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; @@ -1026,3 +1172,462 @@ HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } + +struct CBenchMethod +{ + unsigned dictBits; + UInt32 EncComplex; + UInt32 DecComplexCompr; + UInt32 DecComplexUnc; + const char *Name; +}; + +static const CBenchMethod g_Bench[] = +{ + { 17, 340, 155, 20, "LZMA:x1" }, + { 24, 1182, 155, 20, "LZMA:x5:mt1" }, + { 24, 1182, 155, 20, "LZMA:x5:mt2" }, + { 16, 124, 47, 14, "Deflate:x1" }, + { 16, 376, 47, 14, "Deflate:x5" }, + { 16, 1084, 47, 14, "Deflate:x7" }, + { 17, 420, 47, 14, "Deflate64:x5" }, + { 15, 590, 69, 70, "BZip2:x1" }, + { 19, 792, 119, 119, "BZip2:x5" }, + #ifndef UNDER_CE + { 19, 792, 119, 119, "BZip2:x5:mt2" }, + #endif + { 19, 2500, 118, 118, "BZip2:x7" }, + { 18, 1010, 0, 1155, "PPMD:x1" }, + { 22, 1650, 0, 1830, "PPMD:x5" } +}; + +struct CTotalBenchRes +{ + UInt64 NumIterations; + UInt64 Rating; + UInt64 Usage; + UInt64 RPU; + void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } + void Normalize() + { + if (NumIterations == 0) + return; + Rating /= NumIterations; + Usage /= NumIterations; + RPU /= NumIterations; + NumIterations = 1; + } + void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) + { + Rating = (r1.Rating + r2.Rating) / 2; + Usage = (r1.Usage + r2.Usage) / 2; + RPU = (r1.RPU + r2.RPU) / 2; + NumIterations = (r1.NumIterations + r2.NumIterations) / 2; + } +}; + +static void PrintNumber(IBenchPrintCallback &f, UInt64 value, int size, bool withSpace = true) +{ + char s[128]; + int startPos = (int)sizeof(s) - 32; + memset(s, ' ', startPos); + ConvertUInt64ToString(value, s + startPos); + if (withSpace) + { + startPos--; + size++; + } + int len = (int)strlen(s + startPos); + if (size > len) + { + startPos -= (size - len); + if (startPos < 0) + startPos = 0; + } + f.Print(s + startPos); +} + +static void PrintRating(IBenchPrintCallback &f, UInt64 rating) +{ + PrintNumber(f, rating / 1000000, 6); +} + +static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating) +{ + PrintNumber(f, (usage + 5000) / 10000, 5); + PrintRating(f, rpu); + PrintRating(f, rating); +} + +static void PrintResults(IBenchPrintCallback &f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) +{ + UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); + PrintNumber(f, speed / 1024, 7); + UInt64 usage = info.GetUsage(); + UInt64 rpu = info.GetRatingPerUsage(rating); + PrintResults(f, usage, rpu, rating); + res.NumIterations++; + res.RPU += rpu; + res.Rating += rating; + res.Usage += usage; +} + +static void PrintTotals(IBenchPrintCallback &f, const CTotalBenchRes &res) +{ + f.Print(" "); + PrintResults(f, res.Usage, res.RPU, res.Rating); +} + +static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) +{ + f.Print("RAM "); + f.Print(sizeString); + PrintNumber(f, (size >> 20), 5, true); + f.Print(" MB, # "); + f.Print(threadsString); + PrintNumber(f, numThreads, 3, true); + f.NewLine(); +} + +struct CBenchCallbackToPrint: public IBenchCallback +{ + CBenchProps BenchProps; + CTotalBenchRes EncodeRes; + CTotalBenchRes DecodeRes; + IBenchPrintCallback *_file; + UInt32 DictSize; + + void Init() { EncodeRes.Init(); DecodeRes.Init(); } + void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } + HRESULT SetEncodeResult(const CBenchInfo &info, bool final); + HRESULT SetDecodeResult(const CBenchInfo &info, bool final); + void Print(const char *string); + void NewLine(); + void PrintLeftAligned(const char *string, unsigned size); +}; + +HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final) +{ + RINOK(_file->CheckBreak()); + if (final) + { + UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); + PrintResults(*_file, info, rating, EncodeRes); + } + return S_OK; +} + +static const char *kSep = " | "; + + +HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final) +{ + RINOK(_file->CheckBreak()); + if (final) + { + UInt64 rating = BenchProps.GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); + _file->Print(kSep); + CBenchInfo info2 = info; + info2.UnpackSize *= info2.NumIterations; + info2.PackSize *= info2.NumIterations; + info2.NumIterations = 1; + PrintResults(*_file, info2, rating, DecodeRes); + } + return S_OK; +} + +void CBenchCallbackToPrint::Print(const char *s) +{ + _file->Print(s); +} + +void CBenchCallbackToPrint::NewLine() +{ + _file->NewLine(); +} + +void CBenchCallbackToPrint::PrintLeftAligned(const char *s, unsigned size) +{ + AString s2 = s; + for (unsigned len = (unsigned)strlen(s); len < size; len++) + s2 += ' '; + Print(s2); +} + +static HRESULT TotalBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt32 numThreads, UInt32 unpackSize, IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback) +{ + for (unsigned i = 0; i < sizeof(g_Bench) / sizeof(g_Bench[0]); i++) + { + CBenchMethod bench = g_Bench[i]; + callback->PrintLeftAligned(bench.Name, 12); + callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; + callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; + callback->BenchProps.EncComplex = bench.EncComplex; + COneMethodInfo method; + NCOM::CPropVariant propVariant; + propVariant = bench.Name; + RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant)); + + HRESULT res = MethodBench( + EXTERNAL_CODECS_LOC_VARS + false, numThreads, method, unpackSize, bench.dictBits, + printCallback, callback, &callback->BenchProps); + if (res == E_NOTIMPL) + callback->Print(" ---"); + else + { + RINOK(res); + } + callback->NewLine(); + } + return S_OK; +} + +struct CTempValues +{ + UInt64 *Values; + CTempValues(UInt32 num) { Values = new UInt64[num]; } + ~CTempValues() { delete []Values; } +}; + +static void String_to_PropVariant(const UString &s, NCOM::CPropVariant &prop) +{ + const wchar_t *endPtr; + UInt64 result = ConvertStringToUInt64(s, &endPtr); + if (endPtr - (const wchar_t *)s != s.Length()) + prop = s; + else if (result <= 0xFFFFFFFF) + prop = (UInt32)result; + else + prop = result; +} + +HRESULT Bench( + DECL_EXTERNAL_CODECS_LOC_VARS + IBenchPrintCallback *printCallback, + IBenchCallback *benchCallback, + const CObjectVector<CProperty> props, + UInt32 numIterations, + bool multiDict) +{ + if (!CrcInternalTest()) + return S_FALSE; + + UInt32 numCPUs = 1; + UInt64 ramSize = (UInt64)512 << 20; + #ifndef _7ZIP_ST + numCPUs = NSystem::GetNumberOfProcessors(); + #endif + #if !defined(_7ZIP_ST) || defined(_WIN32) + ramSize = NSystem::GetRamSize(); + #endif + UInt32 numThreads = numCPUs; + + if (printCallback) + PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs); + + COneMethodInfo method; + int i; + for (i = 0; i < props.Size(); i++) + { + const CProperty &property = props[i]; + NCOM::CPropVariant propVariant; + UString name = property.Name; + name.MakeUpper(); + if (!property.Value.IsEmpty()) + String_to_PropVariant(property.Value, propVariant); + if (name.Left(2).CompareNoCase(L"MT") == 0) + { + #ifndef _7ZIP_ST + RINOK(ParseMtProp(name.Mid(2), propVariant, numCPUs, numThreads)); + #endif + continue; + } + RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)); + } + + UInt32 dict; + bool dictIsDefined = method.Get_DicSize(dict); + + if (method.MethodName.IsEmpty()) + method.MethodName = L"LZMA"; + + if (benchCallback) + { + CBenchProps benchProps; + benchProps.SetLzmaCompexity(); + UInt32 dictSize = method.Get_Lzma_DicSize(); + UInt32 uncompressedDataSize = kAdditionalSize + dictSize; + return MethodBench( + EXTERNAL_CODECS_LOC_VARS + true, numThreads, + method, uncompressedDataSize, + kOldLzmaDictBits, printCallback, benchCallback, &benchProps); + } + + if (method.MethodName.CompareNoCase(L"CRC") == 0) + { + if (!printCallback) + return S_FALSE; + IBenchPrintCallback &f = *printCallback; + if (!dictIsDefined) + dict = (1 << 24); + + CTempValues speedTotals(numThreads); + f.NewLine(); + f.Print("Size"); + for (UInt32 ti = 0; ti < numThreads; ti++) + { + PrintNumber(f, ti + 1, 5); + speedTotals.Values[ti] = 0; + } + f.NewLine(); + f.NewLine(); + + UInt64 numSteps = 0; + for (UInt32 i = 0; i < numIterations; i++) + { + for (int pow = 10; pow < 32; pow++) + { + UInt32 bufSize = (UInt32)1 << pow; + if (bufSize > dict) + break; + PrintNumber(f, pow, 2, false); + f.Print(": "); + for (UInt32 ti = 0; ti < numThreads; ti++) + { + RINOK(f.CheckBreak()); + UInt64 speed; + RINOK(CrcBench(ti + 1, bufSize, speed)); + PrintNumber(f, (speed >> 20), 5); + speedTotals.Values[ti] += speed; + } + f.NewLine(); + numSteps++; + } + } + if (numSteps != 0) + { + f.NewLine(); + f.Print("Avg:"); + for (UInt32 ti = 0; ti < numThreads; ti++) + PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); + f.NewLine(); + } + return S_OK; + } + + CBenchCallbackToPrint callback; + callback.Init(); + callback._file = printCallback; + + if (!dictIsDefined) + { + int dicSizeLog; + for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) + if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) + break; + dict = (1 << dicSizeLog); + } + + IBenchPrintCallback &f = *printCallback; + PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dict), "Benchmark threads: ", numThreads); + + bool totalBenchMode = (method.MethodName == L"*"); + f.NewLine(); + f.Print(totalBenchMode ? "Method " : "Dict"); + f.Print(" Compressing | Decompressing"); + f.NewLine(); + const char *kSpaces = totalBenchMode ? " " : " "; + f.Print(kSpaces); + int j; + + for (j = 0; j < 2; j++) + { + f.Print(" Speed Usage R/U Rating"); + if (j == 0) + f.Print(kSep); + } + f.NewLine(); + f.Print(kSpaces); + for (j = 0; j < 2; j++) + { + f.Print(" KB/s % MIPS MIPS"); + if (j == 0) + f.Print(kSep); + } + f.NewLine(); + f.NewLine(); + + if (totalBenchMode) + { + if (!dictIsDefined) + dict = + #ifdef UNDER_CE + (UInt64)1 << 20; + #else + (UInt64)1 << 24; + #endif + for (UInt32 i = 0; i < numIterations; i++) + { + if (i != 0) + printCallback->NewLine(); + HRESULT res = TotalBench( + EXTERNAL_CODECS_LOC_VARS + numThreads, dict, printCallback, &callback); + RINOK(res); + } + } + else + { + + callback.BenchProps.SetLzmaCompexity(); + + for (i = 0; i < (int)numIterations; i++) + { + const int kStartDicLog = 22; + int pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; + if (!multiDict) + pow = 31; + while (((UInt32)1 << pow) > dict) + pow--; + for (; ((UInt32)1 << pow) <= dict; pow++) + { + PrintNumber(f, pow, 2, false); + f.Print(":"); + callback.DictSize = (UInt32)1 << pow; + + UInt32 uncompressedDataSize = kAdditionalSize + callback.DictSize; + + HRESULT res = MethodBench( + EXTERNAL_CODECS_LOC_VARS + true, numThreads, + method, uncompressedDataSize, + kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); + f.NewLine(); + RINOK(res); + if (!multiDict) + break; + } + } + } + callback.Normalize(); + f.Print("----------------------------------------------------------------"); + f.NewLine(); + f.Print("Avr:"); + const char *kSpaces2 = totalBenchMode ? " " : ""; + f.Print(kSpaces2); + PrintTotals(f, callback.EncodeRes); + f.Print(" "); + PrintTotals(f, callback.DecodeRes); + f.NewLine(); + f.Print("Tot:"); + f.Print(kSpaces2); + CTotalBenchRes midRes; + midRes.SetMid(callback.EncodeRes, callback.DecodeRes); + PrintTotals(f, midRes); + f.NewLine(); + return S_OK; +} diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h index a8d02a19..46146e24 100755 --- a/CPP/7zip/UI/Common/Bench.h +++ b/CPP/7zip/UI/Common/Bench.h @@ -4,6 +4,7 @@ #define __7ZIP_BENCH_H #include "../../Common/CreateCoder.h" +#include "../../UI/Common/Property.h" struct CBenchInfo { @@ -14,7 +15,10 @@ struct CBenchInfo UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; + CBenchInfo(): NumIterations(0) {} + UInt64 GetUsage() const; + UInt64 GetRatingPerUsage(UInt64 rating) const; }; struct IBenchCallback @@ -23,20 +27,27 @@ struct IBenchCallback virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; -UInt64 GetUsage(const CBenchInfo &benchOnfo); -UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); -UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); +UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); -HRESULT LzmaBench( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); - const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); -bool CrcInternalTest(); -HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); +struct IBenchPrintCallback +{ + virtual void Print(const char *s) = 0; + virtual void NewLine() = 0; + virtual HRESULT CheckBreak() = 0; +}; + +HRESULT Bench( + DECL_EXTERNAL_CODECS_LOC_VARS + IBenchPrintCallback *printCallback, + IBenchCallback *benchCallback, + const CObjectVector<CProperty> props, + UInt32 numIterations, + bool multiDict + ); #endif diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index c2685f79..eb20d5cc 100755 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -7,12 +7,13 @@ #include "Common/Random.h" #include "Common/StringConvert.h" +#include "Windows/DLL.h" +#include "Windows/Error.h" #include "Windows/FileDir.h" #include "Windows/FileMapping.h" #include "Windows/Process.h" #include "Windows/Synchronization.h" -#include "../FileManager/ProgramLocation.h" #include "../FileManager/RegistryUtils.h" #include "CompressCall.h" @@ -31,10 +32,13 @@ static LPCWSTR kArcIncludeSwitches = L" -an -ai"; static LPCWSTR kStopSwitchParsing = L" --"; static LPCWSTR kLargePagesDisable = L" -slp-"; +extern HWND g_HWND; + UString GetQuotedString(const UString &s) { return UString(L'\"') + s + UString(L'\"'); } + static void ErrorMessage(LPCWSTR message) { MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK); @@ -42,7 +46,7 @@ static void ErrorMessage(LPCWSTR message) static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) { - UString s2 = HResultToMessage(res); + UString s2 = NError::MyFormatMessageW(res); if (s) { s2 += L'\n'; @@ -80,9 +84,7 @@ static void AddLagePagesSwitch(UString ¶ms) static UString Get7zGuiPath() { - UString path; - GetProgramFolderPath(path); - return path + L"7zG.exe"; + return fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zG.exe"; } class CRandNameGenerator @@ -238,9 +240,9 @@ HRESULT TestArchives(const UStringVector &arcPaths) MY_TRY_FINISH } -HRESULT Benchmark() +HRESULT Benchmark(bool totalMode) { MY_TRY_BEGIN - return MyCreateProcess(Get7zGuiPath(), L'b', 0, false, NULL); + return MyCreateProcess(Get7zGuiPath(), totalMode ? L"b -mm=*" : L"b", 0, false, NULL); MY_TRY_FINISH } diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h index fc18df57..f777b9f2 100755 --- a/CPP/7zip/UI/Common/CompressCall.h +++ b/CPP/7zip/UI/Common/CompressCall.h @@ -7,9 +7,6 @@ UString GetQuotedString(const UString &s); -extern HWND g_HWND; -UString HResultToMessage(HRESULT errorCode); - HRESULT CompressFiles( const UString &arcPathPrefix, const UString &arcName, @@ -19,6 +16,6 @@ HRESULT CompressFiles( HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog); HRESULT TestArchives(const UStringVector &arcPaths); -HRESULT Benchmark(); +HRESULT Benchmark(bool totalMode); #endif diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp index 473f7d93..ab483d2f 100755 --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -14,6 +14,8 @@ #include "CompressCall.h" +extern HWND g_HWND; + #define MY_TRY_BEGIN try { #define MY_TRY_FINISH } \ catch(CSystemException &e) { result = e.ErrorCode; } \ @@ -110,7 +112,7 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, CREATE_CODECS CExtractOptions eo; - eo.OutputDir = outFolder; + eo.OutputDir = us2fs(outFolder); eo.TestMode = testMode; CExtractCallbackImp *ecs = new CExtractCallbackImp; @@ -158,7 +160,7 @@ HRESULT TestArchives(const UStringVector &arcPaths) return ExtractGroupCommand(arcPaths, true, UString(), true); } -HRESULT Benchmark() +HRESULT Benchmark(bool totalMode) { HRESULT result; MY_TRY_BEGIN @@ -168,11 +170,19 @@ HRESULT Benchmark() CObjectVector<CCodecInfoEx> externalCodecs; RINOK(LoadExternalCodecs(codecs, externalCodecs)); #endif + CObjectVector<CProperty> props; + if (totalMode) + { + CProperty prop; + prop.Name = L"m"; + prop.Value = L"*"; + props.Add(prop); + } result = Benchmark( #ifdef EXTERNAL_CODECS codecs, &externalCodecs, #endif - (UInt32)-1, (UInt32)-1, g_HWND); + props, g_HWND); MY_TRY_FINISH return result; } diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 29cc60d9..6d6dc673 100755 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -39,14 +39,14 @@ public: int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); - void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, - UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); + void EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( - const UString &phyPrefix, + const FString &phyPrefix, const UString &logPrefix, - const UStringVector &filePaths, - UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); + const FStringVector &filePaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index ba03ea35..8c83a9fb 100755 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "Windows/FileName.h" + #include "EnumDirItems.h" using namespace NWindows; @@ -9,7 +11,7 @@ using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, - const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) + const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; @@ -19,7 +21,7 @@ void AddDirFileInfo(int phyParent, int logParent, di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; - di.Name = fi.Name; + di.Name = fs2us(fi.Name); dirItems.Add(di); } @@ -79,13 +81,13 @@ void CDirItems::DeleteLastPrefix() Prefixes.DeleteBack(); } -void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, - UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) +void CDirItems::EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { - NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); + NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) { - NFind::CFileInfoW fi; + NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { @@ -98,43 +100,43 @@ void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString & AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { - const UString name2 = fi.Name + (wchar_t)kDirDelimiter; - int parent = AddPrefix(phyParent, logParent, name2); + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + int parent = AddPrefix(phyParent, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } -void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, - const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) +void CDirItems::EnumerateDirItems2(const FString &phyPrefix, const UString &logPrefix, + const FStringVector &filePaths, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { - int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); + int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { - const UString &filePath = filePaths[i]; - NFind::CFileInfoW fi; - const UString phyPath = phyPrefix + filePath; + const FString &filePath = filePaths[i]; + NFind::CFileInfo fi; + const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } - int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); - UString phyPrefixCur; + int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); + FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); - phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); + phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { - const UString name2 = fi.Name + (wchar_t)kDirDelimiter; - int parent = AddPrefix(phyParentCur, logParent, name2); + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + int parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } @@ -142,27 +144,27 @@ void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logP } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &phyPrefix, + int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, - UStringVector &errorPaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &curFolderName, - const UString &phyPrefix, + int phyParent, int logParent, const FString &curFolderName, + const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, - UStringVector &errorPaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { - const UString name2 = curFolderName + (wchar_t)kDirDelimiter; - int parent = dirItems.AddPrefix(phyParent, logParent, name2); + const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; + int parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); @@ -173,19 +175,19 @@ static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const UString &phyPrefix, + int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, - UStringVector &errorPaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) @@ -210,8 +212,8 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); - const UString fullPath = phyPrefix + name; - NFind::CFileInfoW fi; + const FString fullPath = phyPrefix + us2fs(name); + NFind::CFileInfo fi; if (!fi.Find(fullPath)) { errorCodes.Add(::GetLastError()); @@ -227,7 +229,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, } { UStringVector pathParts; - pathParts.Add(fi.Name); + pathParts.Add(fs2us(fi.Name)); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } @@ -260,8 +262,8 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; - const UString fullPath = phyPrefix + nextNode.Name; - NFind::CFileInfoW fi; + const FString fullPath = phyPrefix + us2fs(nextNode.Name); + NFind::CFileInfo fi; if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) @@ -285,10 +287,10 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, } - NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); + NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (int ttt = 0; ; ttt++) { - NFind::CFileInfoW fi; + NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { @@ -300,8 +302,8 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, break; if (callback && (ttt & 0xFF) == 0xFF) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); - const UString &name = fi.Name; + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); + const UString &name = fs2us(fi.Name); bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); @@ -336,7 +338,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, addArchivePrefixNew.Add(name); } - RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, + RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; @@ -346,14 +348,14 @@ HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, - UStringVector &errorPaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); - RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, + RINOK(EnumerateDirItems(pair.Head, phyParent, -1, us2fs(pair.Prefix), UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h index d0ce950e..c96c7b9e 100755 --- a/CPP/7zip/UI/Common/EnumDirItems.h +++ b/CPP/7zip/UI/Common/EnumDirItems.h @@ -8,7 +8,7 @@ #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, - const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); + const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { @@ -19,7 +19,7 @@ HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, - UStringVector &errorPaths, + FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index ca2c8c73..81186772 100755 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -52,8 +52,8 @@ static HRESULT DecompressArchive( UStringVector removePathParts; - UString outDir = options.OutputDir; - outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); + FString outDir = options.OutputDir; + outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(arc.DefaultName))); #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". // outDir.TrimRight(); @@ -66,7 +66,7 @@ static HRESULT DecompressArchive( HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; - errorMessage = ((UString)L"Can not create output directory ") + outDir; + errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir); return res; } @@ -118,11 +118,11 @@ HRESULT DecompressArchives( for (i = 0; i < numArcs; i++) { - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; fi.Size = 0; if (!options.StdInMode) { - const UString &arcPath = arcPaths[i]; + const FString &arcPath = us2fs(arcPaths[i]); if (!fi.Find(arcPath)) throw "there is no such archive"; if (fi.IsDir()) @@ -142,7 +142,7 @@ HRESULT DecompressArchives( for (i = 0; i < numArcs; i++) { const UString &arcPath = arcPaths[i]; - NFile::NFind::CFileInfoW fi; + NFile::NFind::CFileInfo fi; if (options.StdInMode) { fi.Size = 0; @@ -150,7 +150,7 @@ HRESULT DecompressArchives( } else { - if (!fi.Find(arcPath) || fi.IsDir()) + if (!fi.Find(us2fs(arcPath)) || fi.IsDir()) throw "there is no such archive"; } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index 5a939ed2..2904a0ab 100755 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -23,7 +23,7 @@ struct CExtractOptions bool CalcCrc; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; - UString OutputDir; + FString OutputDir; // bool ShowDialog; // bool PasswordEnabled; diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 8f31708b..25494d0e 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -20,8 +20,8 @@ static UString ReplaceIncorrectChars(const UString &s) res += c; } res.TrimRight(); - while (!res.IsEmpty() && res[res.Length() - 1] == '.') - res.Delete(res.Length() - 1); + while (!res.IsEmpty() && res.Back() == '.') + res.DeleteBack(); return res; #else return s; @@ -132,8 +132,8 @@ UString GetCorrectFullFsPath(const UString &path) { UString &s = parts[i]; #ifdef _WIN32 - while (!s.IsEmpty() && s[s.Length() - 1] == '.') - s.Delete(s.Length() - 1); + while (!s.IsEmpty() && s.Back() == '.') + s.DeleteBack(); if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 856e47fb..cb4f83ee 100755 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -22,6 +22,7 @@ static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 +#include "Windows/FileName.h" #include "Windows/Registry.h" #endif @@ -32,53 +33,52 @@ using namespace NFile; extern HINSTANCE g_hInstance; #endif -static CSysString GetLibraryFolderPrefix() -{ - #ifdef _WIN32 - TCHAR fullPath[MAX_PATH + 1]; - ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); - CSysString path = fullPath; - int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - return path.Left(pos + 1); - #else - return CSysString(); // FIX IT - #endif -} - -#define kCodecsFolderName TEXT("Codecs") -#define kFormatsFolderName TEXT("Formats") -static const TCHAR *kMainDll = TEXT("7z.dll"); +#define kCodecsFolderName FTEXT("Codecs") +#define kFormatsFolderName FTEXT("Formats") +static CFSTR kMainDll = FTEXT("7z.dll"); #ifdef _WIN32 + static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); -static LPCTSTR kProgramPathValue = TEXT("Path"); -static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) +static LPCWSTR kProgramPathValue = L"Path"; +static LPCWSTR kProgramPath2Value = L"Path" + #ifdef _WIN64 + L"64"; + #else + L"32"; + #endif + +static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) { NRegistry::CKey key; - if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) - if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) + if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) + { + UString pathU; + if (key.QueryValue(value, pathU) == ERROR_SUCCESS) { + path = us2fs(pathU); NName::NormalizeDirPathPrefix(path); - return true; + return NFind::DoesFileExist(path + kMainDll); } + } return false; } #endif -CSysString GetBaseFolderPrefixFromRegistry() +static FString GetBaseFolderPrefixFromRegistry() { - CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); + FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); #ifdef _WIN32 if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) { - CSysString path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) - return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) - return path; + FString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; } #endif return moduleFolderPrefix; @@ -210,6 +210,14 @@ static void SplitString(const UString &srcString, UStringVector &destStrings) destStrings.Add(s); } +int CArcInfoEx::FindExtension(const UString &ext) const +{ + for (int i = 0; i < Exts.Size(); i++) + if (ext.CompareNoCase(Exts[i].Ext) == 0) + return i; + return -1; +} + void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt) { UStringVector exts, addExts; @@ -344,7 +352,7 @@ extern "C" } #endif -HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) +HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) { if (needCheckDll) { @@ -393,9 +401,9 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll) return res; } -HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) +HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) { - NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); + NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { @@ -443,10 +451,10 @@ HRESULT CCodecs::Load() Formats.Add(item); } #ifdef EXTERNAL_CODECS - const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); + const FString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll, false)); - RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); - RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); #endif return S_OK; } @@ -455,12 +463,11 @@ HRESULT CCodecs::Load() int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { - int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); - int slashPos2 = arcPath.ReverseFind(L'.'); + int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int dotPos = arcPath.ReverseFind(L'.'); - if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) + if (dotPos < 0 || dotPos < slashPos) return -1; - UString ext = arcPath.Mid(dotPos + 1); + const UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h index a633dd2e..f5963ed6 100755 --- a/CPP/7zip/UI/Common/LoadCodecs.h +++ b/CPP/7zip/UI/Common/LoadCodecs.h @@ -1,9 +1,8 @@ // LoadCodecs.h -#ifndef __LOADCODECS_H -#define __LOADCODECS_H +#ifndef __LOAD_CODECS_H +#define __LOAD_CODECS_H -#include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" @@ -58,19 +57,16 @@ struct CArcInfoEx #endif #endif bool KeepName; + UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } - int FindExtension(const UString &ext) const - { - for (int i = 0; i < Exts.Size(); i++) - if (ext.CompareNoCase(Exts[i].Ext) == 0) - return i; - return -1; - } + int FindExtension(const UString &ext) const; + + /* UString GetAllExtensions() const { UString s; @@ -82,6 +78,7 @@ struct CArcInfoEx } return s; } + */ void AddExts(const wchar_t* ext, const wchar_t* addExt); @@ -125,7 +122,7 @@ struct CCodecLib GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE - CSysString Path; + FString Path; void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } #endif CCodecLib(): GetMethodProperty(0) {} @@ -151,8 +148,8 @@ public: HRESULT LoadCodecs(); HRESULT LoadFormats(); - HRESULT LoadDll(const CSysString &path, bool needCheckDll); - HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); + HRESULT LoadDll(const FString &path, bool needCheckDll); + HRESULT LoadDllsFromFolder(const FString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 56a63046..60d2f6f5 100755 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -63,6 +63,25 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const return S_OK; } +HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(Archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const { NCOM::CPropVariant prop; @@ -339,7 +358,7 @@ HRESULT CArc::OpenStreamOrFile( { CInFileStream *fileStreamSpec = new CInFileStream; fileStream = fileStreamSpec; - if (!fileStreamSpec->Open(Path)) + if (!fileStreamSpec->Open(us2fs(Path))) return GetLastError(); stream = fileStream; } @@ -461,7 +480,7 @@ HRESULT CArchiveLink::Open( return S_OK; } -static void SetCallback(const UString &filePath, +static void SetCallback(const FString &filePath, IOpenCallbackUI *callbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &callback) @@ -471,12 +490,9 @@ static void SetCallback(const UString &filePath, openCallbackSpec->Callback = callbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; - UString fullName; - int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex); - openCallbackSpec->Init( - fullName.Left(fileNamePartStartIndex), - fullName.Mid(fileNamePartStartIndex)); + FString dirPrefix, fileName; + NFile::NDirectory::GetFullPathAndSplit(filePath, dirPrefix, fileName); + openCallbackSpec->Init(dirPrefix, fileName); } HRESULT CArchiveLink::Open2(CCodecs *codecs, @@ -491,14 +507,10 @@ HRESULT CArchiveLink::Open2(CCodecs *codecs, CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec; openCallbackSpec->Callback = callbackUI; - UString fullName, prefix, name; + FString prefix, name; if (!stream && !stdInMode) { - int fileNamePartStartIndex; - if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex)) - return GetLastError(); - prefix = fullName.Left(fileNamePartStartIndex); - name = fullName.Mid(fileNamePartStartIndex); + NFile::NDirectory::GetFullPathAndSplit(us2fs(filePath), prefix, name); openCallbackSpec->Init(prefix, name); } else @@ -507,9 +519,9 @@ HRESULT CArchiveLink::Open2(CCodecs *codecs, } RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); - VolumePaths.Add(prefix + name); + VolumePaths.Add(fs2us(prefix + name)); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) - VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]); + VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); VolumesSize = openCallbackSpec->TotalSize; return S_OK; } @@ -524,11 +536,11 @@ HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, return Open2(codecs, CIntVector(), false, NULL, filePath, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; - SetCallback(filePath, NULL, callback, openCallbackNew); + SetCallback(us2fs(filePath), NULL, callback, openCallbackNew); CInFileStream *fileStreamSpec = new CInFileStream; CMyComPtr<IInStream> stream(fileStreamSpec); - if (!fileStreamSpec->Open(filePath)) + if (!fileStreamSpec->Open(us2fs(filePath))) return GetLastError(); HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); IsOpen = (res == S_OK); diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index 4a003ee6..25f739e3 100755 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -29,6 +29,7 @@ struct CArc CArc(): MTimeDefined(false) {} HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; HRESULT IsItemAnti(UInt32 index, bool &result) const { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); } diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h index 9fd340cb..8b57a2a6 100755 --- a/CPP/7zip/UI/Common/Property.h +++ b/CPP/7zip/UI/Common/Property.h @@ -1,9 +1,9 @@ // Property.h -#ifndef __PROPERTY_H -#define __PROPERTY_H +#ifndef __7Z_PROPERTY_H +#define __7Z_PROPERTY_H -#include "Common/MyString.h" +#include "../../../Common/MyString.h" struct CProperty { diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp index 4827f2a7..ac9b59a3 100755 --- a/CPP/7zip/UI/Common/SetProperties.cpp +++ b/CPP/7zip/UI/Common/SetProperties.cpp @@ -49,13 +49,13 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert { if (!name.IsEmpty()) { - wchar_t c = name[name.Length() - 1]; + wchar_t c = name.Back(); if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) - name = name.Left(name.Length() - 1); + name.DeleteBack(); } } else diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp index eeaec180..c799c7bf 100755 --- a/CPP/7zip/UI/Common/TempFiles.cpp +++ b/CPP/7zip/UI/Common/TempFiles.cpp @@ -5,16 +5,15 @@ #include "TempFiles.h" #include "Windows/FileDir.h" -#include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { - while(!Paths.IsEmpty()) + while (!Paths.IsEmpty()) { - NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); + NDirectory::DeleteFileAlways(Paths.Back()); Paths.DeleteBack(); } } diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h index eb474a76..5dcda5b6 100755 --- a/CPP/7zip/UI/Common/TempFiles.h +++ b/CPP/7zip/UI/Common/TempFiles.h @@ -1,7 +1,7 @@ // TempFiles.h -#ifndef __TEMPFILES_H -#define __TEMPFILES_H +#ifndef __TEMP_FILES_H +#define __TEMP_FILES_H #include "Common/MyString.h" @@ -9,7 +9,7 @@ class CTempFiles { void Clear(); public: - UStringVector Paths; + FStringVector Paths; ~CTempFiles() { Clear(); } }; diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index a57ec2a6..e740e8a7 100755 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -7,10 +7,7 @@ #include "Common/IntToString.h" #include "Common/StringConvert.h" -#ifdef _WIN32 #include "Windows/DLL.h" -#endif - #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" @@ -40,7 +37,7 @@ using namespace NCOM; using namespace NFile; using namespace NName; -static const wchar_t *kTempFolderPrefix = L"7zE"; +static CFSTR kTempFolderPrefix = FTEXT("7zE"); using namespace NUpdateArchive; @@ -57,7 +54,7 @@ class COutMultiVolStream: { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; - UString Name; + FString Name; UInt64 Pos; UInt64 RealSize; }; @@ -65,7 +62,7 @@ class COutMultiVolStream: public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; - UString Prefix; + FString Prefix; CTempFiles *TempFiles; void Init() @@ -107,18 +104,18 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { if (processedSize != NULL) *processedSize = 0; - while(size > 0) + while (size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; - wchar_t temp[16]; + FChar temp[16]; ConvertUInt32ToString(_streamIndex + 1, temp); - UString res = temp; + FString res = temp; while (res.Length() < 3) - res = UString(L'0') + res; - UString name = Prefix + res; + res = FString(FTEXT('0')) + res; + FString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if (!subStream.StreamSpec->Create(name, false)) @@ -311,7 +308,7 @@ static HRESULT Compress( bool stdOutMode, const CDirItems &dirItems, bool sfxMode, - const UString &sfxModule, + const FString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, @@ -389,11 +386,10 @@ static HRESULT Compress( if (!stdOutMode) { - UString resultPath; - int pos; - if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos)) + FString dirPrefix; + if (!NFile::NDirectory::GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) throw 1417161; - NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); + NFile::NDirectory::CreateComplexDirectory(dirPrefix); } COutFileStream *outStreamSpec = NULL; @@ -408,21 +404,21 @@ static HRESULT Compress( outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; - UString realPath; + FString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { - wchar_t s[16]; + FChar s[16]; ConvertUInt32ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else - realPath = archivePath.GetFinalPath(); + realPath = us2fs(archivePath.GetFinalPath()); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); @@ -450,7 +446,7 @@ static HRESULT Compress( volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; - volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); + volStreamSpec->Prefix = us2fs(archivePath.GetFinalPath() + L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); @@ -484,7 +480,7 @@ static HRESULT Compress( { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; - UString realPath = archivePath.GetFinalPath(); + FString realPath = us2fs(archivePath.GetFinalPath()); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); @@ -527,14 +523,7 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); - - { - CPropVariant prop; - RINOK(archive->GetProperty(i, kpidSize, &prop)); - ai.SizeDefined = (prop.vt != VT_EMPTY); - if (ai.SizeDefined) - ai.Size = ConvertPropVariantToUInt64(prop); - } + RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); { CPropVariant prop; @@ -608,11 +597,11 @@ static HRESULT UpdateWithItemLists( #if defined(_WIN32) && !defined(UNDER_CE) class CCurrentDirRestorer { - UString _path; + FString _path; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); } ~CCurrentDirRestorer() { RestoreDirectory();} - bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); } + bool RestoreDirectory() const { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); } }; #endif @@ -661,17 +650,25 @@ HRESULT UpdateArchive( errorInfo.Message = L"SFX file is not specified"; return E_FAIL; } - UString name = options.SfxModule; - #ifdef UNDER_CE - if (!NFind::DoesFileExist(name)) - #else - if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) - #endif + bool found = false; + if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot find specified SFX module"; - errorInfo.FileName = name; - return E_FAIL; + const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule; + if (NFind::DoesFileExist(fullName)) + { + options.SfxModule = fullName; + found = true; + } + } + if (!found) + { + if (!NFind::DoesFileExist(options.SfxModule)) + { + errorInfo.SystemError = ::GetLastError(); + errorInfo.Message = L"7-Zip cannot find specified SFX module"; + errorInfo.FileName = options.SfxModule; + return E_FAIL; + } } } @@ -681,8 +678,8 @@ HRESULT UpdateArchive( if (!options.ArchivePath.OriginalPath.IsEmpty()) { - NFind::CFileInfoW fi; - if (fi.Find(arcPath)) + NFind::CFileInfo fi; + if (fi.Find(us2fs(arcPath))) { if (fi.IsDir()) throw "there is no such archive"; @@ -738,12 +735,12 @@ HRESULT UpdateArchive( CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); - UStringVector errorPaths; + FStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { - RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); + RINOK(callback->CanNotFindError(fs2us(errorPaths[i]), errorCodes[i])); } if (res != S_OK) { @@ -755,11 +752,11 @@ HRESULT UpdateArchive( } } - UString tempDirPrefix; + FString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 - NDirectory::CTempDirectoryW tempDirectory; + NDirectory::CTempDir tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); @@ -792,20 +789,20 @@ HRESULT UpdateArchive( } } - for(int i = 0; i < options.Commands.Size(); i++) + for (int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it - ap.Prefix = tempDirPrefix; + ap.Prefix = fs2us(tempDirPrefix); // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (!options.StdOutMode && (i > 0 || !createTempFile)) { - const UString &path = ap.GetFinalPath(); + const FString path = us2fs(ap.GetFinalPath()); if (NFind::DoesFileOrDirExist(path)) { errorInfo.SystemError = 0; @@ -839,21 +836,21 @@ HRESULT UpdateArchive( try { CArchivePath &ap = options.Commands[0].ArchivePath; - const UString &tempPath = ap.GetTempPath(); + const FString &tempPath = ap.GetTempPath(); if (thereIsInArchive) - if (!NDirectory::DeleteFileAlways(arcPath)) + if (!NDirectory::DeleteFileAlways(us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot delete the file"; - errorInfo.FileName = arcPath; + errorInfo.FileName = us2fs(arcPath); return E_FAIL; } - if (!NDirectory::MyMoveFile(tempPath, arcPath)) + if (!NDirectory::MyMoveFile(tempPath, us2fs(arcPath))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot move the file"; errorInfo.FileName = tempPath; - errorInfo.FileName2 = arcPath; + errorInfo.FileName2 = us2fs(arcPath); return E_FAIL; } } @@ -867,7 +864,7 @@ HRESULT UpdateArchive( if (options.EMailMode) { NDLL::CLibrary mapiLib; - if (!mapiLib.Load(TEXT("Mapi32.dll"))) + if (!mapiLib.Load(FTEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"7-Zip cannot load Mapi32.dll"; @@ -880,13 +877,13 @@ HRESULT UpdateArchive( errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function"; return E_FAIL; } - UStringVector fullPaths; + FStringVector fullPaths; int i; - for(i = 0; i < options.Commands.Size(); i++) + for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; - UString arcPath; - if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) + FString arcPath; + if (!NFile::NDirectory::MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"GetFullPathName error"; @@ -895,9 +892,9 @@ HRESULT UpdateArchive( fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; - for(i = 0; i < fullPaths.Size(); i++) + for (i = 0; i < fullPaths.Size(); i++) { - UString arcPath = fullPaths[i]; + UString arcPath = fs2us(fullPaths[i]); UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h index 49af0092..43a3c0fd 100755 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h @@ -21,8 +21,8 @@ struct CArchivePath UString VolExtension; // archive type extension for volumes bool Temp; - UString TempPrefix; // path(folder) for temp location - UString TempPostfix; + FString TempPrefix; // path(folder) for temp location + FString TempPostfix; CArchivePath(): Temp(false) {}; @@ -63,12 +63,12 @@ struct CArchivePath } - UString GetTempPath() const + FString GetTempPath() const { - UString path = TempPrefix + Name; + FString path = TempPrefix + us2fs(Name); if (!BaseExtension.IsEmpty()) - path += UString(L'.') + BaseExtension; - path += L".tmp"; + path += FString(FTEXT('.')) + us2fs(BaseExtension); + path += FTEXT(".tmp"); path += TempPostfix; return path; } @@ -97,7 +97,7 @@ struct CUpdateOptions CArchivePath ArchivePath; bool SfxMode; - UString SfxModule; + FString SfxModule; bool OpenShareForWrite; @@ -109,7 +109,7 @@ struct CUpdateOptions bool EMailRemoveAfter; UString EMailAddress; - UString WorkingDir; + FString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); @@ -137,8 +137,8 @@ struct CUpdateOptions struct CErrorInfo { DWORD SystemError; - UString FileName; - UString FileName2; + FString FileName; + FString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index 0f229058..21146bb0 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -22,7 +22,8 @@ CArchiveUpdateCallback::CArchiveUpdateCallback(): DirItems(0), ArcItems(0), UpdatePairs(0), - NewNames(0) + NewNames(0), + KeepOriginalItemNames(0) {} @@ -120,7 +121,22 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { - case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; + case kpidPath: + { + if (KeepOriginalItemNames) + { + if (up.ExistInArchive() && Archive) + { + UInt32 indexInArchive; + if (ArcItems == 0) + indexInArchive = up.ArcIndex; + else + indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; + return Archive->GetProperty(indexInArchive, propID, value); + } + } + prop = DirItems->GetLogPath(up.DirIndex); break; + } case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; @@ -186,7 +202,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); - if (!inStreamSpec->OpenShared(path, ShareForWrite)) + if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } @@ -216,12 +232,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN - wchar_t temp[16]; + FChar temp[16]; ConvertUInt32ToString(index + 1, temp); - UString res = temp; + FString res = temp; while (res.Length() < 2) - res = UString(L'0') + res; - UString fileName = VolName; + res = FString(FTEXT('0')) + res; + FString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 9a20c315..09f1c0d3 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -55,8 +55,8 @@ public: public: CRecordVector<UInt64> VolumesSizes; - UString VolName; - UString VolExt; + FString VolName; + FString VolExt; IUpdateCallbackUI *Callback; @@ -67,6 +67,7 @@ public: const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; + bool KeepOriginalItemNames; CArchiveUpdateCallback(); }; diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp index 164118e2..1ecb5b54 100755 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp @@ -5,23 +5,23 @@ #include "Common/StringConvert.h" #include "Common/Wildcard.h" -#include "Windows/FileDir.h" #include "Windows/FileName.h" #include "WorkDir.h" using namespace NWindows; using namespace NFile; +using namespace NDirectory; -UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) +FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; #ifndef UNDER_CE if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; - UString prefix = path.Left(3); - if (prefix[1] == L':' && prefix[2] == L'\\') + FString prefix = path.Left(3); + if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\')) { UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP)); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) @@ -36,24 +36,56 @@ UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) */ } #endif - switch(mode) + int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1; + fileName = path.Mid(pos); + switch (mode) { case NWorkDir::NMode::kCurrent: { - return ExtractDirPrefixFromPath(path); + return path.Left(pos);; } case NWorkDir::NMode::kSpecified: { - UString tempDir = workDirInfo.Path; + FString tempDir = workDirInfo.Path; NName::NormalizeDirPathPrefix(tempDir); return tempDir; } default: { - UString tempDir; - if (!NDirectory::MyGetTempPath(tempDir)) + FString tempDir; + if (!MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } + +HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) +{ + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + FString namePart; + FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); + CreateComplexDirectory(workDir); + CTempFile tempFile; + _outStreamSpec = new COutFileStream; + OutStream = _outStreamSpec; + if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) + { + DWORD error = GetLastError(); + return error ? error : E_FAIL; + } + _originalPath = originalPath; + return S_OK; +} + +HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) +{ + OutStream.Release(); + if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) + { + DWORD error = GetLastError(); + return error ? error : E_FAIL; + } + return S_OK; +} diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h index 0643d67a..79ea2b9d 100755 --- a/CPP/7zip/UI/Common/WorkDir.h +++ b/CPP/7zip/UI/Common/WorkDir.h @@ -1,10 +1,26 @@ // WorkDir.h -#ifndef __WORKDIR_H -#define __WORKDIR_H +#ifndef __WORK_DIR_H +#define __WORK_DIR_H + +#include "Windows/FileDir.h" #include "ZipRegistry.h" -UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); +#include "../../Common/FileStreams.h" + +FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); + +class CWorkDirTempFile +{ + FString _originalPath; + NWindows::NFile::NDirectory::CTempFile _tempFile; + COutFileStream *_outStreamSpec; +public: + CMyComPtr<IOutStream> OutStream; + + HRESULT CreateTempFile(const FString &originalPath); + HRESULT MoveToOriginal(bool deleteOriginal); +}; #endif diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index ac178078..d2aec4c6 100755 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -3,7 +3,6 @@ #include "StdAfx.h" #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/FileDir.h" #include "Windows/Registry.h" @@ -53,6 +52,13 @@ void CInfo::Save() const key.SetValue_Strings(kPathHistory, Paths); } +void Save_ShowPassword(bool showPassword) +{ + CS_LOCK + CKey key; + CreateMainKey(key, kKeyName); + key.SetValue(kShowPassword, showPassword); +} void CInfo::Load() { @@ -75,6 +81,17 @@ void CInfo::Load() key.GetValue_IfOk(kShowPassword, ShowPassword); } +bool Read_ShowPassword() +{ + CS_LOCK + CKey key; + bool showPassword = false; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return showPassword; + key.GetValue_IfOk(kShowPassword, showPassword); + return showPassword; +} + } namespace NCompression @@ -234,7 +251,7 @@ void CInfo::Save()const CKey key; CreateMainKey(key, kOptionsInfoKeyName); key.SetValue(kWorkDirType, (UInt32)Mode); - key.SetValue(kWorkDirPath, Path); + key.SetValue(kWorkDirPath, fs2us(Path)); key.SetValue(kTempRemovableOnly, ForRemovableOnly); } @@ -257,7 +274,10 @@ void CInfo::Load() case NMode::kSpecified: Mode = (NMode::EEnum)dirType; } - if (key.QueryValue(kWorkDirPath, Path) != ERROR_SUCCESS) + UString pathU; + if (key.QueryValue(kWorkDirPath, pathU) == ERROR_SUCCESS) + Path = us2fs(pathU); + else { Path.Empty(); if (Mode == NMode::kSpecified) diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index 37835386..6d8b7c13 100755 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -20,6 +20,8 @@ namespace NExtract void Save() const; void Load(); }; + void Save_ShowPassword(bool showPassword); + bool Read_ShowPassword(); } namespace NCompression @@ -76,7 +78,7 @@ namespace NWorkDir struct CInfo { NMode::EEnum Mode; - UString Path; + FString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp index 35e868c9..d0e43222 100755 --- a/CPP/7zip/UI/Console/BenchCon.cpp +++ b/CPP/7zip/UI/Console/BenchCon.cpp @@ -2,296 +2,41 @@ #include "StdAfx.h" -#include "../../../Common/IntToString.h" -#include "../../../Common/MyCom.h" - -#if !defined(_7ZIP_ST) || defined(_WIN32) -#include "../../../Windows/System.h" -#endif - #include "../Common/Bench.h" #include "BenchCon.h" #include "ConsoleClose.h" -struct CTotalBenchRes +struct CPrintBenchCallback: public IBenchPrintCallback { - UInt64 NumIterations; - UInt64 Rating; - UInt64 Usage; - UInt64 RPU; - void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } - void Normalize() - { - if (NumIterations == 0) - return; - Rating /= NumIterations; - Usage /= NumIterations; - RPU /= NumIterations; - NumIterations = 1; - } - void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) - { - Rating = (r1.Rating + r2.Rating) / 2; - Usage = (r1.Usage + r2.Usage) / 2; - RPU = (r1.RPU + r2.RPU) / 2; - NumIterations = (r1.NumIterations + r2.NumIterations) / 2; - } -}; + FILE *_file; -struct CBenchCallback: public IBenchCallback -{ - CTotalBenchRes EncodeRes; - CTotalBenchRes DecodeRes; - FILE *f; - void Init() { EncodeRes.Init(); DecodeRes.Init(); } - void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } - UInt32 dictionarySize; - HRESULT SetEncodeResult(const CBenchInfo &info, bool final); - HRESULT SetDecodeResult(const CBenchInfo &info, bool final); + void Print(const char *s); + void NewLine(); + HRESULT CheckBreak(); }; -static void NormalizeVals(UInt64 &v1, UInt64 &v2) -{ - while (v1 > 1000000) - { - v1 >>= 1; - v2 >>= 1; - } -} - -static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) -{ - UInt64 elTime = elapsedTime; - NormalizeVals(freq, elTime); - if (elTime == 0) - elTime = 1; - return value * freq / elTime; -} - -static void PrintNumber(FILE *f, UInt64 value, int size) -{ - char s[32]; - ConvertUInt64ToString(value, s); - fprintf(f, " "); - for (int len = (int)strlen(s); len < size; len++) - fprintf(f, " "); - fputs(s, f); -} - -static void PrintRating(FILE *f, UInt64 rating) -{ - PrintNumber(f, rating / 1000000, 6); -} - -static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) -{ - PrintNumber(f, (usage + 5000) / 10000, 5); - PrintRating(f, rpu); - PrintRating(f, rating); -} - - -static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) +void CPrintBenchCallback::Print(const char *s) { - UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); - PrintNumber(f, speed / 1024, 7); - UInt64 usage = GetUsage(info); - UInt64 rpu = GetRatingPerUsage(info, rating); - PrintResults(f, usage, rpu, rating); - res.NumIterations++; - res.RPU += rpu; - res.Rating += rating; - res.Usage += usage; + fputs(s, _file); } -static void PrintTotals(FILE *f, const CTotalBenchRes &res) +void CPrintBenchCallback::NewLine() { - fprintf(f, " "); - PrintResults(f, res.Usage, res.RPU, res.Rating); + Print("\n"); } - -HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - if (final) - { - UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); - PrintResults(f, info, rating, EncodeRes); - } - return S_OK; -} - -static const char *kSep = " | "; - - -HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) -{ - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - if (final) - { - UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); - fputs(kSep, f); - CBenchInfo info2 = info; - info2.UnpackSize *= info2.NumIterations; - info2.PackSize *= info2.NumIterations; - info2.NumIterations = 1; - PrintResults(f, info2, rating, DecodeRes); - } - return S_OK; -} - -static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) -{ - fprintf(f, "\nRAM %s ", sizeString); - PrintNumber(f, (size >> 20), 5); - fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); -} - -HRESULT LzmaBenchCon( - DECL_EXTERNAL_CODECS_LOC_VARS - FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) +HRESULT CPrintBenchCallback::CheckBreak() { - if (!CrcInternalTest()) - return S_FALSE; - #ifndef _7ZIP_ST - UInt64 ramSize = NWindows::NSystem::GetRamSize(); // - UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); - PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); - if (numThreads == (UInt32)-1) - numThreads = numCPUs; - if (numThreads > 1) - numThreads &= ~1; - if (dictionary == (UInt32)-1) - { - int dicSizeLog; - for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) - if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) - break; - dictionary = (1 << dicSizeLog); - } - #else - if (dictionary == (UInt32)-1) - dictionary = (1 << 22); - numThreads = 1; - #endif - - PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); - - CBenchCallback callback; - callback.Init(); - callback.f = f; - - fprintf(f, "\n\nDict Compressing | Decompressing\n "); - int j; - for (j = 0; j < 2; j++) - { - fprintf(f, " Speed Usage R/U Rating"); - if (j == 0) - fputs(kSep, f); - } - fprintf(f, "\n "); - for (j = 0; j < 2; j++) - { - fprintf(f, " KB/s %% MIPS MIPS"); - if (j == 0) - fputs(kSep, f); - } - fprintf(f, "\n\n"); - for (UInt32 i = 0; i < numIterations; i++) - { - const int kStartDicLog = 22; - int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; - while (((UInt32)1 << pow) > dictionary) - pow--; - for (; ((UInt32)1 << pow) <= dictionary; pow++) - { - fprintf(f, "%2d:", pow); - callback.dictionarySize = (UInt32)1 << pow; - HRESULT res = LzmaBench( - EXTERNAL_CODECS_LOC_VARS - numThreads, callback.dictionarySize, &callback); - fprintf(f, "\n"); - RINOK(res); - } - } - callback.Normalize(); - fprintf(f, "----------------------------------------------------------------\nAvr:"); - PrintTotals(f, callback.EncodeRes); - fprintf(f, " "); - PrintTotals(f, callback.DecodeRes); - fprintf(f, "\nTot:"); - CTotalBenchRes midRes; - midRes.SetMid(callback.EncodeRes, callback.DecodeRes); - PrintTotals(f, midRes); - fprintf(f, "\n"); - return S_OK; + return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK; } -struct CTempValues -{ - UInt64 *Values; - CTempValues(UInt32 num) { Values = new UInt64[num]; } - ~CTempValues() { delete []Values; } -}; - -HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) +HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector<CProperty> props, UInt32 numIterations, FILE *f) { - if (!CrcInternalTest()) - return S_FALSE; - - #ifndef _7ZIP_ST - UInt64 ramSize = NWindows::NSystem::GetRamSize(); - UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); - PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); - if (numThreads == (UInt32)-1) - numThreads = numCPUs; - #else - numThreads = 1; - #endif - if (dictionary == (UInt32)-1) - dictionary = (1 << 24); - - CTempValues speedTotals(numThreads); - fprintf(f, "\n\nSize"); - for (UInt32 ti = 0; ti < numThreads; ti++) - { - fprintf(f, " %5d", ti + 1); - speedTotals.Values[ti] = 0; - } - fprintf(f, "\n\n"); - - UInt64 numSteps = 0; - for (UInt32 i = 0; i < numIterations; i++) - { - for (int pow = 10; pow < 32; pow++) - { - UInt32 bufSize = (UInt32)1 << pow; - if (bufSize > dictionary) - break; - fprintf(f, "%2d: ", pow); - UInt64 speed; - for (UInt32 ti = 0; ti < numThreads; ti++) - { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - RINOK(CrcBench(ti + 1, bufSize, speed)); - PrintNumber(f, (speed >> 20), 5); - speedTotals.Values[ti] += speed; - } - fprintf(f, "\n"); - numSteps++; - } - } - if (numSteps != 0) - { - fprintf(f, "\nAvg:"); - for (UInt32 ti = 0; ti < numThreads; ti++) - PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); - fprintf(f, "\n"); - } - return S_OK; + CPrintBenchCallback callback; + callback._file = f; + callback.NewLine(); + return Bench(EXTERNAL_CODECS_LOC_VARS + &callback, NULL, props, numIterations, true); } diff --git a/CPP/7zip/UI/Console/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h index 966a83a6..73972186 100755 --- a/CPP/7zip/UI/Console/BenchCon.h +++ b/CPP/7zip/UI/Console/BenchCon.h @@ -6,11 +6,9 @@ #include <stdio.h> #include "../../Common/CreateCoder.h" +#include "../../UI/Common/Property.h" -HRESULT LzmaBenchCon( - DECL_EXTERNAL_CODECS_LOC_VARS - FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); - -HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); +HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector<CProperty> props, UInt32 numIterations, FILE *f); #endif diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index 09633ee5..7c1719da 100755 --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp @@ -628,14 +628,6 @@ SOURCE=..\Common\UpdateProduce.h # End Source File # Begin Source File -SOURCE=..\Common\WorkDir.cpp -# End Source File -# Begin Source File - -SOURCE=..\Common\WorkDir.h -# End Source File -# Begin Source File - SOURCE=..\Common\ZipRegistry.h # End Source File # End Group @@ -676,6 +668,14 @@ SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index af65739c..af379861 100755 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -182,7 +182,7 @@ HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else - (*OutStream) << NError::MyFormatMessage(result); + (*OutStream) << NError::MyFormatMessageW(result); } (*OutStream) << endl; NumArchiveErrors++; @@ -218,11 +218,7 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else - { - UString message; - NError::MyFormatMessage(result, message); - (*OutStream) << message; - } + (*OutStream) << NError::MyFormatMessageW(result); (*OutStream) << endl; return S_OK; } diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index f747cfda..7de2379a 100755 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -437,8 +437,8 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UInt64 arcPackSize = 0; if (!stdInMode) { - NFile::NFind::CFileInfoW fi; - if (!fi.Find(archiveName) || fi.IsDir()) + NFile::NFind::CFileInfo fi; + if (!fi.Find(us2fs(archiveName)) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; @@ -477,7 +477,7 @@ HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else - g_StdOut << NError::MyFormatMessage(result); + g_StdOut << NError::MyFormatMessageW(result); g_StdOut << endl; numErrors++; continue; diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 9bd451f8..722b09e2 100755 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -39,7 +39,9 @@ using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; +#ifdef _WIN32 HINSTANCE g_hInstance = 0; +#endif extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" @@ -111,7 +113,7 @@ static const char *kUserErrorMessage = "Incorrect command line"; static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; -static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; +static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { @@ -338,20 +340,6 @@ int Main2( } else if (options.Command.CommandType == NCommandType::kBenchmark) { - if (options.Method.CompareNoCase(L"CRC") == 0) - { - HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); - if (res != S_OK) - { - if (res == S_FALSE) - { - stdStream << "\nCRC Error\n"; - return NExitCode::kFatalError; - } - throw CSystemException(res); - } - } - else { HRESULT res; #ifdef EXTERNAL_CODECS @@ -360,11 +348,11 @@ int Main2( if (res != S_OK) throw CSystemException(res); #endif - res = LzmaBenchCon( + res = BenchCon( #ifdef EXTERNAL_CODECS compressCodecsInfo, &externalCodecs, #endif - (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); + options.Properties, options.NumIterations, (FILE *)stdStream); if (res != S_OK) { if (res == S_FALSE) @@ -410,7 +398,7 @@ int Main2( eo.YesToAll = options.YesToAll; eo.CalcCrc = options.CalcCrc; #if !defined(_7ZIP_ST) && !defined(_SFX) - eo.Properties = options.ExtractProperties; + eo.Properties = options.Properties; #endif UString errorMessage; CDecompressStat stat; @@ -480,7 +468,7 @@ int Main2( numErrors); if (numErrors > 0) { - g_StdOut << endl << "Errors: " << numErrors; + g_StdOut << endl << "Errors: " << numErrors << endl; return NExitCode::kFatalError; } if (result != S_OK) @@ -551,12 +539,12 @@ int Main2( } if (!errorInfo.FileName.IsEmpty()) { - message += errorInfo.FileName; + message += fs2us(errorInfo.FileName); message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { - message += errorInfo.FileName2; + message += fs2us(errorInfo.FileName2); message += L"\n"; } if (errorInfo.SystemError != 0) diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp index c54a3d09..25f4bd0d 100755 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -79,9 +79,8 @@ int MY_CDECL main (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } - UString message; - NError::MyFormatMessage(systemError.ErrorCode, message); - (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; + (*g_StdStream) << endl << endl << "System error:" << endl << + NError::MyFormatMessageW(systemError.ErrorCode) << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp index 28452b17..786db1bc 100755 --- a/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -7,13 +7,13 @@ #include "PercentPrinter.h" -const int kPaddingSize = 2; -const int kPercentsSize = 4; -const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; +static const unsigned kPaddingSize = 2; +static const unsigned kPercentsSize = 4; +static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; -static void ClearPrev(char *p, int num) +static void ClearPrev(char *p, unsigned num) { - int i; + unsigned i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; @@ -51,18 +51,30 @@ void CPercentPrinter::PrintNewLine() void CPercentPrinter::RePrintRatio() { char s[32]; - ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); - int size = (int)strlen(s); - s[size++] = '%'; - s[size] = '\0'; + unsigned size; + { + char c = '%'; + UInt64 value = 0; + if (m_Total == (UInt64)(Int64)-1) + { + value = m_CurValue >> 20; + c = 'M'; + } + else if (m_Total != 0) + value = m_CurValue * 100 / m_Total; + ConvertUInt64ToString(value, s); + size = (unsigned)strlen(s); + s[size++] = c; + s[size] = '\0'; + } - int extraSize = kPaddingSize + MyMax(size, kPercentsSize); + unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; - int i; + unsigned i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) @@ -73,7 +85,7 @@ void CPercentPrinter::RePrintRatio() for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; - for (; size < m_NumExtraChars; size++) + for (; size < extraSize; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h index 97f2e6ad..d970cc4b 100755 --- a/CPP/7zip/UI/Console/PercentPrinter.h +++ b/CPP/7zip/UI/Console/PercentPrinter.h @@ -1,9 +1,8 @@ // PercentPrinter.h -#ifndef __PERCENTPRINTER_H -#define __PERCENTPRINTER_H +#ifndef __PERCENT_PRINTER_H +#define __PERCENT_PRINTER_H -#include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter @@ -12,12 +11,12 @@ class CPercentPrinter UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; - int m_NumExtraChars; + unsigned m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), - m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} + m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile index 9b8fc37a..f100f635 100755 --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile @@ -54,6 +54,7 @@ WIN_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ + $O\MethodProps.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ @@ -77,7 +78,6 @@ UI_COMMON_OBJS = \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ - $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\OutStreamWithCRC.obj \ diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index ca5bf816..4bdc397a 100755 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -7,8 +7,10 @@ #include "Common/StringConvert.h" #include "Windows/COM.h" +#include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "Windows/Memory.h" #include "Windows/Menu.h" #include "Windows/Process.h" @@ -20,7 +22,6 @@ #include "../Common/ZipRegistry.h" #include "../FileManager/FormatUtils.h" -#include "../FileManager/ProgramLocation.h" #ifdef LANG #include "../FileManager/LangUtils.h" @@ -338,8 +339,9 @@ static const char *kExtractExludeExtensions = static const char *kNoOpenAsExtensions = " 7z arj bz2 cab chm cpio dmg flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip "; -static bool FindExt(const char *p, const UString &name) +static bool FindExt(const char *p, const FString &nameF) { + const UString name = fs2us(nameF); int extPos = name.ReverseFind('.'); if (extPos < 0) return false; @@ -357,7 +359,7 @@ static bool FindExt(const char *p, const UString &name) return false; } -static bool DoNeedExtract(const UString &name) +static bool DoNeedExtract(const FString &name) { return !FindExt(kExtractExludeExtensions, name); } @@ -408,11 +410,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast) { const UString &fileName = _fileNames.Front(); - UString folderPrefix; - NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); - - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(fileName)) + NFile::NFind::CFileInfo fileInfo; + if (!fileInfo.Find(us2fs(fileName))) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) { @@ -473,10 +472,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) { bool needExtract = false; - for(int i = 0; i < _fileNames.Size(); i++) + for (int i = 0; i < _fileNames.Size(); i++) { - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(_fileNames[i])) + NFile::NFind::CFileInfo fileInfo; + if (!fileInfo.Find(us2fs(_fileNames[i]))) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) needExtract = true; @@ -484,10 +483,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, const UString &fileName = _fileNames.Front(); if (needExtract) { - UString folderPrefix; - NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(fileName)) + FString folderPrefix; + NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileName), folderPrefix); + NFile::NFind::CFileInfo fileInfo; + if (!fileInfo.Find(us2fs(fileName))) return E_FAIL; // Extract if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) @@ -497,8 +496,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = folderPrefix; - commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR); + commandMapItem.Folder = fs2us(folderPrefix); + commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fileInfo.Name)) + UString(WCHAR_PATH_SEPARATOR); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } @@ -512,7 +511,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = folderPrefix; + commandMapItem.Folder = fs2us(folderPrefix); _commandMap.Add(commandMapItem); } @@ -524,13 +523,13 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, FillCommand(kExtractTo, s, commandMapItem); UString folder; if (_fileNames.Size() == 1) - folder = GetSubFolderNameForExtract(fileInfo.Name); + folder = GetSubFolderNameForExtract(fs2us(fileInfo.Name)); else folder = L'*'; if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = folderPrefix; + commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.Folder += folder; s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR))); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); @@ -548,8 +547,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); UString archiveName7z = archiveName + L".7z"; UString archiveNameZip = archiveName + L".zip"; - UString archivePathPrefix; - NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix); + FString archivePathPrefix; + NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileName), archivePathPrefix); // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) @@ -558,7 +557,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = archivePathPrefix; + commandMapItem.Folder = fs2us(archivePathPrefix); commandMapItem.ArcName = archiveName; FillCommand(kCompress, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); @@ -586,7 +585,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = archivePathPrefix; + commandMapItem.Folder = fs2us(archivePathPrefix); commandMapItem.ArcName = archiveName7z; commandMapItem.ArcType = L"7z"; s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); @@ -618,7 +617,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) commandMapItem.Folder = _dropPath; else - commandMapItem.Folder = archivePathPrefix; + commandMapItem.Folder = fs2us(archivePathPrefix); commandMapItem.ArcName = archiveNameZip; commandMapItem.ArcType = L"zip"; s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); @@ -675,9 +674,7 @@ int CZipContextMenu::FindVerb(const UString &verb) static UString Get7zFmPath() { - UString path; - GetProgramFolderPath(path); - return path + L"7zFM.exe"; + return fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zFM.exe"; } STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) diff --git a/CPP/7zip/UI/Explorer/DllExports.cpp b/CPP/7zip/UI/Explorer/DllExports.cpp index bc8ae177..4f649f59 100755 --- a/CPP/7zip/UI/Explorer/DllExports.cpp +++ b/CPP/7zip/UI/Explorer/DllExports.cpp @@ -35,16 +35,6 @@ using namespace NWindows; HINSTANCE g_hInstance = 0; HWND g_HWND = 0; -UString HResultToMessage(HRESULT errorCode) -{ - UString message; - if (!NError::MyFormatMessage(errorCode, message)) - message.Empty(); - if (message.IsEmpty()) - message = L"Error"; - return message; -} - LONG g_DllRefCount = 0; // Reference count of this DLL. static LPCWSTR kShellExtName = L"7-Zip Shell Extension"; @@ -191,14 +181,15 @@ static BOOL RegisterServer(CLSID clsid, LPCWSTR title) if (!GetStringFromIID(clsid, clsidString, MAX_PATH)) return FALSE; - UString modulePath; - if (!NDLL::MyGetModuleFileName(g_hInstance, modulePath)) + FString modulePath; + if (!NDLL::MyGetModuleFileName(modulePath)) return FALSE; + UString modulePathU = fs2us(modulePath); CRegItem clsidEntries[] = { HKEY_CLASSES_ROOT, kClsidMask, NULL, title, - HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePath, + HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePathU, HKEY_CLASSES_ROOT, kClsidInprocMask, L"ThreadingModel", L"Apartment", NULL, NULL, NULL, NULL }; diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index b980d846..9f55e8e5 100755 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -449,8 +449,7 @@ bool WasEscPressed() void ShowErrorMessage(DWORD errorCode) { - UString message; - NError::MyFormatMessage(errorCode, message); + UString message = NError::MyFormatMessageW(errorCode); message.Replace(L"\x0D", L""); message.Replace(L"\x0A", L" "); g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)); diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp index 5e017b80..7b58d0ca 100755 --- a/CPP/7zip/UI/Far/Main.cpp +++ b/CPP/7zip/UI/Far/Main.cpp @@ -87,12 +87,12 @@ class COpenArchiveCallback: DWORD m_PrevTickCount; - NWindows::NFile::NFind::CFileInfoW _fileInfo; + NWindows::NFile::NFind::CFileInfo _fileInfo; public: bool PasswordIsDefined; UString Password; - UString _folderPrefix; + FString _folderPrefix; public: MY_UNKNOWN_IMP3( @@ -130,7 +130,7 @@ public: } void ShowMessage(); - void LoadFileInfo(const UString &folderPrefix, const UString &fileName) + void LoadFileInfo(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; if (!_fileInfo.Find(_folderPrefix + fileName)) @@ -251,7 +251,7 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in if (WasEscPressed()) return E_ABORT; *inStream = NULL; - UString fullPath = _folderPrefix + name; + FString fullPath = _folderPrefix + us2fs(name); if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) @@ -333,16 +333,15 @@ HRESULT OpenArchive(const CSysString &fileName, static HANDLE MyOpenFilePluginW(const wchar_t *name) { - UString normalizedName = name; + FString normalizedName = us2fs(name); normalizedName.Trim(); - UString fullName; - int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(normalizedName, fullName, fileNamePartStartIndex); - NFile::NFind::CFileInfoW fileInfo; + FString fullName; + NFile::NDirectory::MyGetFullPathName(normalizedName, fullName); + NFile::NFind::CFileInfo fileInfo; if (!fileInfo.Find(fullName)) return INVALID_HANDLE_VALUE; if (fileInfo.IsDir()) - return INVALID_HANDLE_VALUE; + return INVALID_HANDLE_VALUE; CMyComPtr<IInFolderArchive> archiveHandler; @@ -360,9 +359,11 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name) // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) openArchiveCallbackSpec->Init(); - openArchiveCallbackSpec->LoadFileInfo( - fullName.Left(fileNamePartStartIndex), - fullName.Mid(fileNamePartStartIndex)); + { + FString dirPrefix, fileName; + NFile::NDirectory::GetFullPathAndSplit(fullName, dirPrefix, fileName); + openArchiveCallbackSpec->LoadFileInfo(dirPrefix, fileName); + } // ::OutputDebugStringA("before OpenArchive\n"); @@ -449,7 +450,7 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item) if(fileName.IsEmpty()) return INVALID_HANDLE_VALUE; if (fileName.Length() >= 2 && - fileName[0] == '\"' && fileName[fileName.Length() - 1] == '\"') + fileName[0] == '\"' && fileName.Back() == '\"') fileName = fileName.Mid(1, fileName.Length() - 2); return MyOpenFilePlugin(fileName); diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index a19b037c..8bdfb10d 100755 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -18,7 +18,7 @@ using namespace NWindows; using namespace NFar; -CPlugin::CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName): +CPlugin::CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName): m_ArchiveHandler(archiveHandler), m_FileName(fileName), _archiveTypeName(archiveTypeName) @@ -532,10 +532,10 @@ static void InsertSeparator(InfoPanelLine *lines, int &numItems) void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) { info->StructSize = sizeof(*info); - info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS| OPIF_USEHIGHLIGHTING| + info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS | OPIF_USEHIGHLIGHTING | OPIF_ADDDOTS | OPIF_COMPAREFATTIME; - COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(m_FileName, CP_OEMCP)); + COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(fs2us(m_FileName), CP_OEMCP)); info->HostFile = m_FileNameBuffer; // test it it is not static COPY_STR_LIMITED(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP)); @@ -545,10 +545,9 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) UString name; { - UString fullName; - int index; - NFile::NDirectory::MyGetFullPathName(m_FileName, fullName, index); - name = fullName.Mid(index); + FString dirPrefix, fileName; + NFile::NDirectory::GetFullPathAndSplit(m_FileName, dirPrefix, fileName); + name = fs2us(fileName); } m_PannelTitle = @@ -852,14 +851,14 @@ int CPlugin::ProcessKey(int key, unsigned int controlState) } if ((controlState & PKF_ALT) != 0 && key == VK_F6) { - UString folderPath; + FString folderPath; if (!NFile::NDirectory::GetOnlyDirPrefix(m_FileName, folderPath)) return FALSE; PanelInfo panelInfo; g_StartupInfo.ControlGetActivePanelInfo(panelInfo); GetFilesReal(panelInfo.SelectedItems, panelInfo.SelectedItemsNumber, FALSE, - UnicodeStringToMultiByte(folderPath, CP_OEMCP), OPM_SILENT, true); + UnicodeStringToMultiByte(fs2us(folderPath), CP_OEMCP), OPM_SILENT, true); g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL); g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL); g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL); diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h index ab534e21..c4122c45 100755 --- a/CPP/7zip/UI/Far/Plugin.h +++ b/CPP/7zip/UI/Far/Plugin.h @@ -9,6 +9,8 @@ #include "Windows/FileFind.h" #include "Windows/PropVariant.h" +#include "../Common/WorkDir.h" + #include "../Agent/IFolderArchive.h" #include "FarUtils.h" @@ -36,9 +38,10 @@ class CPlugin void EnterToDirectory(const UString &dirName); void GetPathParts(UStringVector &pathParts); void GetCurrentDir(); + HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector); public: - UString m_FileName; - NWindows::NFile::NFind::CFileInfoW m_FileInfo; + FString m_FileName; + NWindows::NFile::NFind::CFileInfo m_FileInfo; CMyComPtr<IInFolderArchive> m_ArchiveHandler; CMyComPtr<IFolderFolder> _folder; @@ -48,7 +51,7 @@ public: bool PasswordIsDefined; UString Password; - CPlugin(const UString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName); + CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName); ~CPlugin(); void ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex); diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp index c8d784c3..3a3df300 100755 --- a/CPP/7zip/UI/Far/PluginDelete.cpp +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -2,20 +2,11 @@ #include "StdAfx.h" -#include "Windows/FileDir.h" - -#include "../Common/WorkDir.h" - #include "Messages.h" #include "Plugin.h" #include "UpdateCallback100.h" using namespace NFar; -using namespace NWindows; -using namespace NFile; -using namespace NDirectory; - -static LPCWSTR kTempArchivePrefix = L"7zA"; int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) { @@ -67,18 +58,10 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) g_StartupInfo.GetMsgString(NMessageID::kDeleting), 48); } - NWorkDir::CInfo workDirInfo; - workDirInfo.Load(); - - UString workDir = GetWorkDir(workDirInfo, m_FileName); - CreateComplexDirectory(workDir); - - CTempFileW tempFile; - UString tempFileName; - if (tempFile.Create(workDir, kTempArchivePrefix, tempFileName) == 0) + CWorkDirTempFile tempFile; + if (tempFile.CreateTempFile(m_FileName) != S_OK) return FALSE; - CRecordVector<UINT32> indices; indices.Reserve(numItems); int i; @@ -101,61 +84,23 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) outArchive->SetFolder(_folder); CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); + CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); - - result = outArchive->DeleteItems( - tempFileName, - &indices.Front(), indices.Size(), - updateCallback); + result = outArchive->DeleteItems(tempFile.OutStream, &indices.Front(), indices.Size(), updateCallback); updateCallback.Release(); outArchive.Release(); - if (result != S_OK) - { - ShowErrorMessage(result); - return FALSE; - } - - _folder.Release(); - m_ArchiveHandler->Close(); - - if (!DeleteFileAlways(m_FileName)) + if (result == S_OK) { - ShowLastErrorMessage(); - return FALSE; + result = AfterUpdate(tempFile, pathVector); } - - tempFile.DisableDeleting(); - if (!MyMoveFile(tempFileName, m_FileName)) - { - ShowLastErrorMessage(); - return FALSE; - } - - result = m_ArchiveHandler->ReOpen(NULL); if (result != S_OK) { ShowErrorMessage(result); return FALSE; } - - - //////////////////////////// - // Restore _folder; - - m_ArchiveHandler->BindToRootFolder(&_folder); - for (i = 0; i < pathVector.Size(); i++) - { - CMyComPtr<IFolderFolder> newFolder; - _folder->BindToFolder(pathVector[i], &newFolder); - if (!newFolder) - break; - _folder = newFolder; - } GetCurrentDir(); - return TRUE; } diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp index 965030ea..a4450064 100755 --- a/CPP/7zip/UI/Far/PluginRead.cpp +++ b/CPP/7zip/UI/Far/PluginRead.cpp @@ -194,9 +194,11 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa #ifdef UNDER_CE destPathU = L"\\"; #else - if (!NFile::NDirectory::MyGetCurrentDirectory(destPathU)) + FString destPathF = us2fs(destPathU); + if (!NFile::NDirectory::MyGetCurrentDirectory(destPathF)) throw 318016; - NFile::NName::NormalizeDirPathPrefix(destPathU); + NFile::NName::NormalizeDirPathPrefix(destPathF); + destPathU = fs2us(destPathF); #endif break; } @@ -251,7 +253,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa passwordIsDefined = !password.IsEmpty(); } - NFile::NDirectory::CreateComplexDirectory(destPathU); + NFile::NDirectory::CreateComplexDirectory(us2fs(destPathU)); /* vector<int> realIndices; diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp index be9616a4..e02f4d80 100755 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -7,15 +7,10 @@ #include "Common/Wildcard.h" #include "Common/StringConvert.h" -#include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" -#include "Windows/Defs.h" -#include "Windows/PropVariant.h" #include "../Common/ZipRegistry.h" -#include "../Common/WorkDir.h" -#include "../Common/OpenArchive.h" #include "../Agent/Agent.h" @@ -30,13 +25,11 @@ using namespace NFar; using namespace NUpdateArchive; -static const char *kHelpTopic = "Update"; - -static LPCWSTR kTempArcivePrefix = L"7zA"; +static const char *kHelpTopic = "Update"; static const char *kArchiveHistoryKeyName = "7-ZipArcName"; -static UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; +static const UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method) { @@ -47,18 +40,39 @@ static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method) realNames.Add(UString(L"x")); NCOM::CPropVariant value = (UInt32)method; CRecordVector<const wchar_t *> names; - for(int i = 0; i < realNames.Size(); i++) + for (int i = 0; i < realNames.Size(); i++) names.Add(realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size())); } return S_OK; } +HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector) +{ + _folder.Release(); + m_ArchiveHandler->Close(); + + RINOK(tempFile.MoveToOriginal(true)); + + RINOK(m_ArchiveHandler->ReOpen(NULL)); // check it + + m_ArchiveHandler->BindToRootFolder(&_folder); + for (int i = 0; i < pathVector.Size(); i++) + { + CMyComPtr<IFolderFolder> newFolder; + _folder->BindToFolder(pathVector[i], &newFolder); + if (!newFolder) + break; + _folder = newFolder; + } + return S_OK; +} + NFileOperationReturnCode::EEnum CPlugin::PutFiles( struct PluginPanelItem *panelItems, int numItems, int moveMode, int opMode) { - if(moveMode != 0) + if (moveMode != 0) { g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported); return NFileOperationReturnCode::kError; @@ -153,20 +167,14 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( compressionInfo.Save(); - NWorkDir::CInfo workDirInfo; - workDirInfo.Load(); - UString workDir = GetWorkDir(workDirInfo, m_FileName); - CreateComplexDirectory(workDir); - - CTempFileW tempFile; - UString tempFileName; - if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) + CWorkDirTempFile tempFile;; + if (tempFile.CreateTempFile(m_FileName) != S_OK) return NFileOperationReturnCode::kError; /* CSysStringVector fileNames; - for(int i = 0; i < numItems; i++) + for (int i = 0; i < numItems; i++) { const PluginPanelItem &panelItem = panelItems[i]; CSysString fullName; @@ -189,44 +197,28 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); } - //////////////////////////// - // Save FolderItem; - UStringVector aPathVector; - GetPathParts(aPathVector); + UStringVector pathVector; + GetPathParts(pathVector); - /* - UString anArchivePrefix; - for(i = aPathVector.Size() - 1; i >= 0; i--) - { - anArchivePrefix += aPathVector[i]; - anArchivePrefix += wchar_t(NName::kDirDelimiter); - } - ///////////////////////////////// - */ - UStringVector fileNames; fileNames.Reserve(numItems); - for(i = 0; i < numItems; i++) + for (i = 0; i < numItems; i++) fileNames.Add(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP)); CRecordVector<const wchar_t *> fileNamePointers; fileNamePointers.Reserve(numItems); - for(i = 0; i < numItems; i++) + for (i = 0; i < numItems; i++) fileNamePointers.Add(fileNames[i]); CMyComPtr<IOutFolderArchive> outArchive; HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive); - if(result != S_OK) + if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return NFileOperationReturnCode::kError; } outArchive->SetFolder(_folder); - // CSysString aCurrentFolder; - // MyGetCurrentDirectory(aCurrentFolder); - // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP), - outArchive->SetFiles(L"", - &fileNamePointers.Front(), fileNamePointers.Size()); + outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; @@ -239,42 +231,14 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) return NFileOperationReturnCode::kError; - result = outArchive->DoOperation2(tempFileName, actionSetByte, NULL, updateCallback); + result = outArchive->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback); updateCallback.Release(); outArchive.Release(); - /* - HRESULT result = Compress(fileNames, anArchivePrefix, *actionSet, - m_ProxyHandler.get(), - m_ArchiverInfo.ClassID, compressionInfo.Method == 0, - compressionInfo.Method == 2, tempFileName, progressBoxPointer); - */ - - if (result != S_OK) + if (result == S_OK) { - ShowErrorMessage(result); - return NFileOperationReturnCode::kError; + result = AfterUpdate(tempFile, pathVector); } - - _folder.Release(); - m_ArchiveHandler->Close(); - - // m_FolderItem = NULL; - - if (!DeleteFileAlways(m_FileName)) - { - ShowLastErrorMessage(); - return NFileOperationReturnCode::kError; - } - - tempFile.DisableDeleting(); - if (!MyMoveFile(tempFileName, m_FileName)) - { - ShowLastErrorMessage(); - return NFileOperationReturnCode::kError; - } - - m_ArchiveHandler->ReOpen(NULL); if (result != S_OK) { ShowErrorMessage(result); @@ -282,37 +246,17 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( } /* - if(m_ProxyHandler->ReInit(NULL) != S_OK) - return NFileOperationReturnCode::kError; - */ - - //////////////////////////// - // Restore FolderItem; - - m_ArchiveHandler->BindToRootFolder(&_folder); - for (i = 0; i < aPathVector.Size(); i++) + if (moveMode != 0) { - CMyComPtr<IFolderFolder> newFolder; - _folder->BindToFolder(aPathVector[i], &newFolder); - if(!newFolder ) - break; - _folder = newFolder; - } - - /* - if(moveMode != 0) - { - for(int i = 0; i < numItems; i++) + for (int i = 0; i < numItems; i++) { - const PluginPanelItem &aPluginPanelItem = panelItems[i]; + const PluginPanelItem &pluginPanelItem = panelItems[i]; bool result; - if(NFile::NFind::NAttributes::IsDir(aPluginPanelItem.FindData.dwFileAttributes)) - result = NFile::NDirectory::RemoveDirectoryWithSubItems( - aPluginPanelItem.FindData.cFileName); + if (NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes)) + result = NFile::NDirectory::RemoveDirectoryWithSubItems(pluginPanelItem.FindData.cFileName); else - result = NFile::NDirectory::DeleteFileAlways( - aPluginPanelItem.FindData.cFileName); - if(!result) + result = NFile::NDirectory::DeleteFileAlways(pluginPanelItem.FindData.cFileName); + if (!result) return NFileOperationReturnCode::kError; } } @@ -361,11 +305,11 @@ void CParsedPath::ParsePath(const UString &path) case NPathType::kLocal: { int posDiskDelimiter = path.Find(kDiskDelimiter); - if(posDiskDelimiter >= 0) + if (posDiskDelimiter >= 0) { curPos = posDiskDelimiter + 1; if (path.Length() > curPos) - if(path[curPos] == kDirDelimiter) + if (path[curPos] == kDirDelimiter) curPos++; } break; @@ -373,7 +317,7 @@ void CParsedPath::ParsePath(const UString &path) case NPathType::kUNC: { int curPos = path.Find(kDirDelimiter, 2); - if(curPos < 0) + if (curPos < 0) curPos = path.Length(); else curPos++; @@ -386,7 +330,7 @@ void CParsedPath::ParsePath(const UString &path) UString CParsedPath::MergePath() const { UString result = Prefix; - for(int i = 0; i < PathParts.Size(); i++) + for (int i = 0; i < PathParts.Size(); i++) { if (i != 0) result += kDirDelimiter; @@ -409,20 +353,20 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) UStringVector fileNames; int i; - for(i = 0; i < pluginPanelItems.Size(); i++) + for (i = 0; i < pluginPanelItems.Size(); i++) { const PluginPanelItem &panelItem = pluginPanelItems[i]; - UString fullName; if (strcmp(panelItem.FindData.cFileName, "..") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; if (strcmp(panelItem.FindData.cFileName, ".") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; - UString fileNameUnicode = MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP); - if (!MyGetFullPathName(fileNameUnicode, fullName)) + FString fullPath; + FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP)); + if (!MyGetFullPathName(fileNameUnicode, fullPath)) return E_FAIL; - fileNames.Add(fullName); + fileNames.Add(fs2us(fullPath)); } NCompression::CInfo compressionInfo; @@ -453,7 +397,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { CParsedPath parsedPath; parsedPath.ParsePath(fileNames.Front()); - if(parsedPath.PathParts.Size() == 0) + if (parsedPath.PathParts.Size() == 0) return E_FAIL; if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1) { @@ -589,7 +533,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { CIntVector indices; CSysStringVector archiverNames; - for(int i = 0; i < codecs->Formats.Size(); i++) + for (int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; if (arc.UpdateEnabled) @@ -602,7 +546,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT, g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle), NULL, archiverNames, archiverIndex); - if(index >= 0) + if (index >= 0) { const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat]; if (prevArchiverInfo.KeepName) @@ -653,18 +597,12 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) NWorkDir::CInfo workDirInfo; workDirInfo.Load(); - UString fullArchiveName; - if (!MyGetFullPathName(archiveName, fullArchiveName)) + FString fullArchiveName; + if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName)) return E_FAIL; - UString workDir = GetWorkDir(workDirInfo, fullArchiveName); - CreateComplexDirectory(workDir); - - CTempFileW tempFile; - UString tempFileName; - if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0) - return E_FAIL; - + CWorkDirTempFile tempFile; + RINOK(tempFile.CreateTempFile(fullArchiveName)); CScreenRestorer screenRestorer; CProgressBox progressBox; @@ -678,12 +616,12 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; CMyComPtr<IOutFolderArchive> outArchive; CMyComPtr<IInFolderArchive> archiveHandler; - if(fileInfo.Find(fullArchiveName)) + if (fileInfo.Find(fullArchiveName)) { if (fileInfo.IsDir()) throw "There is Directory with such name"; @@ -702,7 +640,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) throw "Type of existing archive differs from specified type"; HRESULT result = archiveHandler.QueryInterface( IID_IOutFolderArchive, &outArchive); - if(result != S_OK) + if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return E_FAIL; @@ -726,15 +664,11 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) CRecordVector<const wchar_t *> fileNamePointers; fileNamePointers.Reserve(fileNames.Size()); - for(i = 0; i < fileNames.Size(); i++) + for (i = 0; i < fileNames.Size(); i++) fileNamePointers.Add(fileNames[i]); outArchive->SetFolder(NULL); - // CSysString aCurrentFolder; - // MyGetCurrentDirectory(aCurrentFolder); - // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP), - outArchive->SetFiles(L"", - &fileNamePointers.Front(), fileNamePointers.Size()); + outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; @@ -749,7 +683,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) HRESULT result = outArchive->DoOperation( codecs, archiverIndex, - tempFileName, actionSetByte, + tempFile.OutStream, actionSetByte, NULL, updateCallback); updateCallback.Release(); outArchive.Release(); @@ -760,21 +694,14 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) return result; } - if(archiveHandler) + if (archiveHandler) { archiveHandler->Close(); - if (!DeleteFileAlways(fullArchiveName)) - { - ShowLastErrorMessage(); - return NFileOperationReturnCode::kError; - } } - tempFile.DisableDeleting(); - if (!MyMoveFile(tempFileName, fullArchiveName)) + if (!tempFile.MoveToOriginal(archiveHandler != NULL)) { ShowLastErrorMessage(); return E_FAIL; } - return S_OK; } diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index c195a79d..5f31f607 100755 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -11,6 +11,8 @@ #include "Windows/COM.h" #include "Windows/Error.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" + #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Thread.h" @@ -31,7 +33,7 @@ using namespace NFind; extern DWORD g_ComCtl32Version; extern HINSTANCE g_hInstance; -static LPCWSTR kTempDirPrefix = L"7zE"; +static CFSTR kTempDirPrefix = FTEXT("7zE"); void CPanelCallbackImp::OnTab() { @@ -374,7 +376,7 @@ static void ReducePathToRealFileSystemPath(UString &path) { while (!path.IsEmpty()) { - if (NFind::DoesDirExist(path)) + if (NFind::DoesDirExist(us2fs(path))) { NName::NormalizeDirPathPrefix(path); break; @@ -510,6 +512,8 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) return info; } +bool IsCorrectFsName(const UString name); + void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); @@ -599,10 +603,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (indices.Size() > 1 || (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) || - NFind::DoesDirExist(destPath) || + NFind::DoesDirExist(us2fs(destPath)) || srcPanel.IsArcFolder()) { - NDirectory::CreateComplexDirectory(destPath); + NDirectory::CreateComplexDirectory(us2fs(destPath)); NName::NormalizeDirPathPrefix(destPath); if (!CheckFolderPath(destPath)) { @@ -616,11 +620,16 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) } else { + if (!IsCorrectFsName(destPath)) + { + srcPanel.MessageBoxError(E_INVALIDARG); + return; + } int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos >= 0) { UString prefix = destPath.Left(pos + 1); - NDirectory::CreateComplexDirectory(prefix); + NDirectory::CreateComplexDirectory(us2fs(prefix)); if (!CheckFolderPath(prefix)) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); @@ -645,8 +654,8 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); bool useTemp = useSrcPanel && useDestPanel; - NFile::NDirectory::CTempDirectoryW tempDirectory; - UString tempDirPrefix; + NFile::NDirectory::CTempDir tempDirectory; + FString tempDirPrefix; if (useTemp) { tempDirectory.Create(kTempDirPrefix); @@ -662,7 +671,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) HRESULT result; if (useSrcPanel) { - UString folder = useTemp ? tempDirPrefix : destPath; + UString folder = useTemp ? fs2us(tempDirPrefix) : destPath; result = srcPanel.CopyTo(indices, folder, move, true, 0); if (result != S_OK) { @@ -681,7 +690,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) UStringVector filePaths; UString folderPrefix; if (useTemp) - folderPrefix = tempDirPrefix; + folderPrefix = fs2us(tempDirPrefix); else folderPrefix = srcPanel._currentFolderPrefix; filePaths.Reserve(indices.Size()); diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index a057c34e..2af63b47 100755 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -202,7 +202,7 @@ public: void SelectSpec(bool selectMode) { GetFocusedPanel().SelectSpec(selectMode); } void SelectByType(bool selectMode) { GetFocusedPanel().SelectByType(selectMode); } - void RefreshStatusBar() { GetFocusedPanel().RefreshStatusBar(); } + void Refresh_StatusBar() { GetFocusedPanel().Refresh_StatusBar(); } void SetListViewMode(UInt32 index) { GetFocusedPanel().SetListViewMode(index); } UInt32 GetListViewMode() { return GetFocusedPanel().GetListViewMode(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 602b12f3..1c350064 100755 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -2,13 +2,14 @@ #include "StdAfx.h" -#ifdef UNDER_CE +#include "BrowseDialog.h" + +#ifdef USE_MY_BROWSE_DIALOG #include "Common/IntToString.h" #include "Windows/PropVariantConversions.h" -#include "BrowseDialog.h" #include "LangUtils.h" #include "PropertyNameRes.h" @@ -60,7 +61,7 @@ bool CBrowseDialog::OnInit() _list.Attach(GetItem(IDC_BROWSE_LIST)); #ifndef UNDER_CE - _list.SetUnicodeFormat(true); + _list.SetUnicodeFormat(); #endif #ifndef _SFX @@ -191,8 +192,8 @@ int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) { if (lParam1 == kParentIndex) return -1; if (lParam2 == kParentIndex) return 1; - const CFileInfoW &f1 = _files[(int)lParam1]; - const CFileInfoW &f2 = _files[(int)lParam2]; + const CFileInfo &f1 = _files[(int)lParam1]; + const CFileInfo &f2 = _files[(int)lParam2]; bool isDir1 = f1.IsDir(); bool isDir2 = f2.IsDir(); @@ -225,12 +226,12 @@ static HRESULT GetNormalizedError() HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) { - CEnumeratorW enumerator(pathPrefix + L'*'); - CObjectVector<CFileInfoW> files; + CEnumerator enumerator(us2fs(pathPrefix + L'*')); + CObjectVector<CFileInfo> files; for (;;) { bool found; - CFileInfoW fi; + CFileInfo fi; if (!enumerator.Next(fi, found)) return GetNormalizedError(); if (!found) @@ -278,16 +279,17 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected for (int i = 0; i < _files.Size(); i++) { - const CFileInfoW &fi = _files[i]; + const CFileInfo &fi = _files[i]; item.iItem = index; - if (fi.Name.CompareNoCase(selectedName) == 0) + const UString name = fs2us(fi.Name); + if (name.CompareNoCase(selectedName) == 0) cursorIndex = item.iItem; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; int subItem = 0; item.iSubItem = subItem++; item.lParam = i; - item.pszText = (wchar_t *)(const wchar_t *)fi.Name; - item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + fi.Name); + item.pszText = (wchar_t *)(const wchar_t *)name; + item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, Path + name); if (item.iImage < 0) item.iImage = 0; _list.InsertItem(&item); @@ -325,7 +327,7 @@ HRESULT CBrowseDialog::Reload() { int fileIndex = GetRealItemIndex(index); if (fileIndex != kParentIndex) - selectedCur = _files[fileIndex].Name; + selectedCur = fs2us(_files[fileIndex].Name); } return Reload(Path, selectedCur); } @@ -443,13 +445,13 @@ void CBrowseDialog::FinishOnOK() OpenParentFolder(); return; } - const CFileInfoW &file = _files[fileIndex]; + const CFileInfo &file = _files[fileIndex]; if (file.IsDir() != FolderMode) { ShowSelectError(); return; } - Path += file.Name; + Path += fs2us(file.Name); } End(IDOK); } @@ -464,7 +466,7 @@ void CBrowseDialog::OnItemEnter() OpenParentFolder(); else { - const CFileInfoW &file = _files[fileIndex]; + const CFileInfo &file = _files[fileIndex]; if (!file.IsDir()) { if (!FolderMode) @@ -473,7 +475,7 @@ void CBrowseDialog::OnItemEnter() ShowSelectError(); return; } - HRESULT res = Reload(Path + file.Name + WCHAR_PATH_SEPARATOR, L""); + HRESULT res = Reload(Path + fs2us(file.Name) + WCHAR_PATH_SEPARATOR, L""); if (res != S_OK) ShowError(HResultToMessage(res)); } @@ -481,6 +483,8 @@ void CBrowseDialog::OnItemEnter() void CBrowseDialog::OnOK() { + // When we press "Enter" in listview, windows sends message to first Button. + // We check that message was from listview; if (GetFocus() == _list) { OnItemEnter(); diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h index 41eb6b50..f597d1c3 100755 --- a/CPP/7zip/UI/FileManager/BrowseDialog.h +++ b/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -4,6 +4,10 @@ #define __BROWSE_DIALOG_H #ifdef UNDER_CE +#define USE_MY_BROWSE_DIALOG +#endif + +#ifdef USE_MY_BROWSE_DIALOG #include "Windows/FileFind.h" @@ -16,7 +20,7 @@ class CBrowseDialog: public NWindows::NControl::CModalDialog { NWindows::NControl::CListView _list; - CObjectVector<NWindows::NFile::NFind::CFileInfoW> _files; + CObjectVector<NWindows::NFile::NFind::CFileInfo> _files; CExtToIconMap _extToIconMap; int _sortIndex; bool _ascending; diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index d27db23f..90076ebb 100755 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -2,12 +2,18 @@ #include "StdAfx.h" +#include "Common/StringConvert.h" + #include "Windows/Error.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "../../Common/FilePathAutoRename.h" +#ifndef _SFX +#include "../Common/ZipRegistry.h" +#endif + #include "../GUI/ExtractRes.h" #include "ExtractCallback.h" @@ -177,6 +183,11 @@ STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) return S_OK; } +HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path) +{ + return MessageError(GetUnicodeString(message) + fs2us(path)); +} + STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *message) { AddErrorMessage(message); @@ -296,7 +307,7 @@ HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, boo MyLoadStringW(IDS_MEM_ERROR); #endif else - NError::MyFormatMessage(result, message2); + message2 = NError::MyFormatMessageW(result); message += message2; } MessageError(message); @@ -339,11 +350,19 @@ STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { CPasswordDialog dialog; + #ifndef _SFX + bool showPassword = NExtract::Read_ShowPassword(); + dialog.ShowPassword = showPassword; + #endif ProgressDialog->WaitCreating(); if (dialog.Create(*ProgressDialog) == IDCANCEL) return E_ABORT; Password = dialog.Password; PasswordIsDefined = true; + #ifndef _SFX + if (dialog.ShowPassword != showPassword) + NExtract::Save_ShowPassword(dialog.ShowPassword); + #endif } return StringToBstr(Password, password); } @@ -366,19 +385,16 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( *writeAnswer = BoolToInt(false); UString destPathSpec = destPath; - UString destPathSys = destPathSpec; + FString destPathSys = us2fs(destPath); bool srcIsFolderSpec = IntToBool(srcIsFolder); - CFileInfoW destFileInfo; + CFileInfo destFileInfo; if (destFileInfo.Find(destPathSys)) { if (srcIsFolderSpec) { if (!destFileInfo.IsDir()) { - UString message = UString(L"can not replace file \'") - + destPathSpec + - UString(L"\' with folder with same name"); - RINOK(MessageError(message)); + RINOK(MessageError("can not replace file with folder with same name: ", destPathSys)); return E_ABORT; } *writeAnswer = BoolToInt(false); @@ -386,10 +402,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( } if (destFileInfo.IsDir()) { - UString message = UString(L"can not replace folder \'") - + destPathSpec + - UString(L"\' with file with same name"); - RINOK(MessageError(message)); + RINOK(MessageError("can not replace folder with file with same name: ", destPathSys)); return E_FAIL; } @@ -432,19 +445,15 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( { if (!AutoRenamePath(destPathSys)) { - UString message = UString(L"can not create name of file ") - + destPathSys; - RINOK(MessageError(message)); + RINOK(MessageError("can not create name for file: ", destPathSys)); return E_ABORT; } - destPathResultTemp = destPathSys; + destPathResultTemp = fs2us(destPathSys); } else if (!NFile::NDirectory::DeleteFileAlways(destPathSys)) { - UString message = UString(L"can not delete output file ") - + destPathSys; - RINOK(MessageError(message)); + RINOK(MessageError("can not delete output file: ", destPathSys)); return E_ABORT; } } diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h index b4e88fd5..19c29e77 100755 --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -35,6 +35,7 @@ class CExtractCallbackImp: #endif public CMyUnknownImp { + HRESULT MessageError(const char *message, const FString &path); public: MY_QUERYINTERFACE_BEGIN2(IFolderOperationsExtractCallback) MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback) diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index f3b48704..147a1fb7 100755 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -33,7 +33,9 @@ using namespace NFind; #define MENU_HEIGHT 26 +#ifdef _WIN32 HINSTANCE g_hInstance; +#endif HWND g_HWND; bool g_OpenArchive = false; static UString g_MainPath; @@ -114,7 +116,7 @@ public: }; static bool g_CanChangeSplitter = false; -static UINT32 g_SplitterPos = 0; +static UInt32 g_SplitterPos = 0; static CSplitterPos g_Splitter; static bool g_PanelsInfoDefined = false; @@ -208,7 +210,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) ySize = rect.bottom - rect.top; } - UINT32 numPanels, currentPanel; + UInt32 numPanels, currentPanel; g_PanelsInfoDefined = ReadPanelsInfo(numPanels, currentPanel, g_SplitterPos); if (g_PanelsInfoDefined) { @@ -409,6 +411,30 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, { #ifdef _WIN32 + /* + #ifndef _WIN64 + #ifndef UNDER_CE + { + HMODULE hMod = GetModuleHandle("Kernel32.dll"); + if (hMod) + { + typedef BOOL (WINAPI *PSETDEP)(DWORD); + #define MY_PROCESS_DEP_ENABLE 1 + PSETDEP procSet = (PSETDEP)GetProcAddress(hMod,"SetProcessDEPPolicy"); + if (procSet) + procSet(MY_PROCESS_DEP_ENABLE); + + typedef BOOL (WINAPI *HSI)(HANDLE, HEAP_INFORMATION_CLASS ,PVOID, SIZE_T); + HSI hsi = (HSI)GetProcAddress(hMod, "HeapSetInformation"); + #define MY_HeapEnableTerminationOnCorruption ((HEAP_INFORMATION_CLASS)1) + if (hsi) + hsi(NULL, MY_HeapEnableTerminationOnCorruption, NULL, 0); + } + } + #endif + #endif + */ + NT_CHECK SetLargePageSize(); @@ -639,7 +665,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) bool needOpenFile = false; if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) { - if (NFile::NFind::DoesFileExist(g_MainPath)) + if (NFile::NFind::DoesFileExist(us2fs(g_MainPath))) needOpenFile = true; } HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted); @@ -665,8 +691,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (res == E_OUTOFMEMORY) message = LangString(IDS_MEM_ERROR, 0x0200060B); else - if (!NError::MyFormatMessage(res, message)) - message = L"Error"; + message = NError::MyFormatMessageW(res); } } MessageBoxW(0, message, L"7-zip", MB_ICONERROR); diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp index 87ee3fc9..823b0826 100755 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -26,9 +26,9 @@ using namespace NWindows; using namespace NFile; using namespace NFind; -static const wchar_t *kVolPrefix = L"\\\\.\\"; +static CFSTR kVolPrefix = FTEXT("\\\\.\\"); -UString CDriveInfo::GetDeviceFileIoName() const +FString CDriveInfo::GetDeviceFileIoName() const { return kVolPrefix + Name; } @@ -40,7 +40,7 @@ struct CPhysTempBuffer ~CPhysTempBuffer() { MidFree(buffer); } }; -static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, +static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize, UInt32 bufferSize, UInt64 progressStart, IProgress *progress) { NFile::NIO::CInFile inFile; @@ -120,17 +120,17 @@ STDMETHODIMP CFSDrives::LoadItems() { _drives.Clear(); - UStringVector driveStrings; + FStringVector driveStrings; MyGetLogicalDriveStrings(driveStrings); for (int i = 0; i < driveStrings.Size(); i++) { CDriveInfo di; - const UString &driveName = driveStrings[i]; + const FString &driveName = driveStrings[i]; di.FullSystemName = driveName; - - di.Name = di.FullSystemName.Left(di.FullSystemName.Length() - 1); + if (!driveName.IsEmpty()) + di.Name = driveName.Left(driveName.Length() - 1); di.ClusterSize = 0; di.DriveSize = 0; di.FreeSpace = 0; @@ -150,14 +150,11 @@ STDMETHODIMP CFSDrives::LoadItems() } if (needRead) { - UString volumeName, fileSystemName; DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags; NFile::NSystem::MyGetVolumeInformation(driveName, - volumeName, + di.VolumeName, &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags, - fileSystemName); - di.VolumeName = volumeName; - di.FileSystemName = fileSystemName; + di.FileSystemName); NFile::NSystem::MyGetDiskFreeSpace(driveName, di.ClusterSize, di.DriveSize, di.FreeSpace); @@ -198,7 +195,7 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT return S_OK; } -HRESULT CFSDrives::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder) +HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) { *resultFolder = 0; if (_volumeMode) @@ -232,7 +229,7 @@ STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder) STDMETHODIMP CFSDrives::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) { - return BindToFolderSpec(name, resultFolder); + return BindToFolderSpec(us2fs(name), resultFolder); } STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder) @@ -252,7 +249,7 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) case kpidType: prop = L"FSDrives"; break; case kpidPath: if (_volumeMode) - prop = kVolPrefix; + prop = fs2us(kVolPrefix); else prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); break; @@ -325,7 +322,7 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, UString destPath = path; if (destPath.IsEmpty()) return E_INVALIDARG; - bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR); if (directName) { if (numItems > 1) @@ -339,18 +336,18 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, int index = indices[i]; const CDriveInfo &di = _drives[index]; UString destPath2 = destPath; - UString name = di.Name; + UString name = fs2us(di.Name); if (!directName) { UString destName = name; - if (!destName.IsEmpty() && destName[destName.Length() - 1] == L':') + if (!destName.IsEmpty() && destName.Back() == L':') { - destName.Delete(destName.Length() - 1); + destName.DeleteBack(); destName += GetExt(index); } destPath2 += destName; } - UString srcPath = di.GetDeviceFileIoName(); + FString srcPath = di.GetDeviceFileIoName(); UInt64 fileSize = 0; if (GetLength(index, fileSize) != S_OK) @@ -363,16 +360,16 @@ STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, Int32 writeAskResult; CMyComBSTR destPathResult; - RINOK(callback->AskWrite(srcPath, BoolToInt(false), NULL, &fileSize, + RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize, destPath2, &destPathResult, &writeAskResult)); if (!IntToBool(writeAskResult)) continue; - RINOK(callback->SetCurrentFilePath(srcPath)); + RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); static const UInt32 kBufferSize = (4 << 20); UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; - RINOK(CopyFileSpec(srcPath, destPathResult, false, fileSize, bufferSize, completedSize, callback)); + RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback)); completedSize += fileSize; } return S_OK; @@ -393,6 +390,11 @@ STDMETHODIMP CFSDrives::CopyFrom(const wchar_t * /* fromFolderPath */, return E_NOTIMPL; } +STDMETHODIMP CFSDrives::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */) { return E_NOTIMPL; diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h index fc99bce7..a0cfd9be 100755 --- a/CPP/7zip/UI/FileManager/FSDrives.h +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -10,8 +10,8 @@ struct CDriveInfo { - UString Name; - UString FullSystemName; + FString Name; + FString FullSystemName; bool KnownSizes; UInt64 DriveSize; UInt64 FreeSpace; @@ -21,7 +21,7 @@ struct CDriveInfo UString FileSystemName; UINT DriveType; - UString GetDeviceFileIoName() const; + FString GetDeviceFileIoName() const; }; class CFSDrives: @@ -33,7 +33,7 @@ class CFSDrives: CObjectVector<CDriveInfo> _drives; bool _volumeMode; - HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); + HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder); UString GetExt(int index) const; HRESULT GetLength(int index, UInt64 &length) const; public: diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 1b3837cf..e4cb9f27 100755 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -24,7 +24,7 @@ namespace NWindows { namespace NFile { -bool GetLongPath(LPCWSTR path, UString &longPath); +bool GetLongPath(CFSTR path, UString &longPath); }} @@ -47,7 +47,7 @@ static STATPROPSTG kProps[] = { NULL, kpidPrefix, VT_BSTR} }; -HRESULT CFSFolder::Init(const UString &path, IFolderFolder *parentFolder) +HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder) { _parentFolder = parentFolder; _path = path; @@ -65,25 +65,25 @@ HRESULT CFSFolder::Init(const UString &path, IFolderFolder *parentFolder) { DWORD lastError = GetLastError(); CFindFile findFile; - CFileInfoW fi; - if (!findFile.FindFirst(_path + UString(L"*"), fi)) + CFileInfo fi; + if (!findFile.FindFirst(_path + FCHAR_ANY_MASK, fi)) return lastError; } return S_OK; } -HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) +static HRESULT GetFolderSize(const FString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress) { RINOK(progress->SetCompleted(NULL)); numFiles = numFolders = size = 0; - CEnumeratorW enumerator(path + UString(WSTRING_PATH_SEPARATOR L"*")); - CFileInfoW fi; + CEnumerator enumerator(path + FSTRING_PATH_SEPARATOR FSTRING_ANY_MASK); + CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) { UInt64 subFolders, subFiles, subSize; - RINOK(GetFolderSize(path + UString(WCHAR_PATH_SEPARATOR) + fi.Name, subFolders, subFiles, subSize, progress)); + RINOK(GetFolderSize(path + FCHAR_PATH_SEPARATOR + fi.Name, subFolders, subFiles, subSize, progress)); numFolders += subFolders; numFolders++; numFiles += subFiles; @@ -98,10 +98,10 @@ HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, return S_OK; } -HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const UString &path) +HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const FString &path) { { - CEnumeratorW enumerator(path + L"*"); + CEnumerator enumerator(path + FCHAR_ANY_MASK); CDirItem fi; while (enumerator.Next(fi)) { @@ -128,7 +128,7 @@ HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const UString &path) { CDirItem &item = dirItem.Files[i]; if (item.IsDir()) - LoadSubItems(item, path + item.Name + WCHAR_PATH_SEPARATOR); + LoadSubItems(item, path + item.Name + FCHAR_PATH_SEPARATOR); } return S_OK; } @@ -166,7 +166,7 @@ STDMETHODIMP CFSFolder::LoadItems() return S_OK; } -static const wchar_t *kDescriptionFileName = L"descript.ion"; +static CFSTR kDescriptionFileName = FTEXT("descript.ion"); bool CFSFolder::LoadComments() { @@ -244,10 +244,10 @@ STDMETHODIMP CFSFolder::GetNumberOfSubFolders(UInt32 *numSubFolders) */ #ifndef UNDER_CE -static bool MyGetCompressedFileSizeW(LPCWSTR fileName, UInt64 &size) +static bool MyGetCompressedFileSizeW(CFSTR fileName, UInt64 &size) { DWORD highPart; - DWORD lowPart = ::GetCompressedFileSizeW(fileName, &highPart); + DWORD lowPart = ::GetCompressedFileSizeW(fs2us(fileName), &highPart); if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR) { #ifdef WIN_LONG_PATH @@ -274,7 +274,7 @@ STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT switch(propID) { case kpidIsDir: prop = fi.IsDir(); break; - case kpidName: prop = fi.Name; break; + case kpidName: prop = fs2us(fi.Name); break; case kpidSize: if (!fi.IsDir()) prop = fi.Size; break; case kpidPackSize: #ifdef UNDER_CE @@ -298,7 +298,7 @@ STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT { LoadComments(); UString comment; - if (_comments.GetValue(GetRelPath(fi), comment)) + if (_comments.GetValue(fs2us(GetRelPath(fi)), comment)) prop = comment; break; } @@ -313,29 +313,29 @@ STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT return S_OK; } -HRESULT CFSFolder::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder) +HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) { *resultFolder = 0; CFSFolder *folderSpec = new CFSFolder; CMyComPtr<IFolderFolder> subFolder = folderSpec; - RINOK(folderSpec->Init(_path + name + UString(WCHAR_PATH_SEPARATOR), 0)); + RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR, 0)); *resultFolder = subFolder.Detach(); return S_OK; } -UString CFSFolder::GetPrefix(const CDirItem &item) const +FString CFSFolder::GetPrefix(const CDirItem &item) const { - UString path; + FString path; CDirItem *cur = item.Parent; while (cur->Parent != 0) { - path = cur->Name + UString(WCHAR_PATH_SEPARATOR) + path; + path = cur->Name + FCHAR_PATH_SEPARATOR + path; cur = cur->Parent; } return path; } -UString CFSFolder::GetRelPath(const CDirItem &item) const +FString CFSFolder::GetRelPath(const CDirItem &item) const { return GetPrefix(item) + item.Name; } @@ -351,7 +351,7 @@ STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) { - return BindToFolderSpec(name, resultFolder); + return BindToFolderSpec(us2fs(name), resultFolder); } STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) @@ -365,11 +365,11 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) } if (_path.IsEmpty()) return E_INVALIDARG; - int pos = _path.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = _path.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0 || pos != _path.Length() - 1) return E_FAIL; - UString parentPath = _path.Left(pos); - pos = parentPath.ReverseFind(WCHAR_PATH_SEPARATOR); + FString parentPath = _path.Left(pos); + pos = parentPath.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0) { #ifdef UNDER_CE @@ -382,17 +382,17 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) #endif return S_OK; } - UString parentPathReduced = parentPath.Left(pos); + FString parentPathReduced = parentPath.Left(pos); parentPath = parentPath.Left(pos + 1); #ifndef UNDER_CE - pos = parentPathReduced.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = parentPathReduced.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos == 1) { - if (parentPath[0] != WCHAR_PATH_SEPARATOR) + if (parentPath[0] != FCHAR_PATH_SEPARATOR) return E_FAIL; CNetFolder *netFolderSpec = new CNetFolder; CMyComPtr<IFolderFolder> netFolder = netFolderSpec; - netFolderSpec->Init(parentPath); + netFolderSpec->Init(fs2us(parentPath)); *resultFolder = netFolder.Detach(); return S_OK; } @@ -421,7 +421,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) switch(propID) { case kpidType: prop = L"FSFolder"; break; - case kpidPath: prop = _path; break; + case kpidPath: prop = fs2us(_path); break; } prop.Detach(value); return S_OK; @@ -532,13 +532,13 @@ STDMETHODIMP CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgr return result; } -HRESULT CFSFolder::GetComplexName(const wchar_t *name, UString &resultPath) +HRESULT CFSFolder::GetComplexName(CFSTR name, FString &resultPath) { - UString newName = name; + FString newName = name; resultPath = _path + newName; if (newName.Length() < 1) return S_OK; - if (newName[0] == WCHAR_PATH_SEPARATOR) + if (newName[0] == FCHAR_PATH_SEPARATOR) { resultPath = newName; return S_OK; @@ -552,11 +552,11 @@ HRESULT CFSFolder::GetComplexName(const wchar_t *name, UString &resultPath) STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */) { - UString processedName; - RINOK(GetComplexName(name, processedName)); - if(NDirectory::MyCreateDirectory(processedName)) + FString processedName; + RINOK(GetComplexName(us2fs(name), processedName)); + if (NDirectory::MyCreateDirectory(processedName)) return S_OK; - if(::GetLastError() == ERROR_ALREADY_EXISTS) + if (::GetLastError() == ERROR_ALREADY_EXISTS) return ::GetLastError(); if (!NDirectory::CreateComplexDirectory(processedName)) return ::GetLastError(); @@ -565,8 +565,8 @@ STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progres STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */) { - UString processedName; - RINOK(GetComplexName(name, processedName)); + FString processedName; + RINOK(GetComplexName(us2fs(name), processedName)); NIO::COutFile outFile; if (!outFile.Create(processedName, false)) return ::GetLastError(); @@ -576,8 +576,8 @@ STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */) { const CDirItem &fi = *_refs[index]; - const UString fullPrefix = _path + GetPrefix(fi); - if (!NDirectory::MyMoveFile(fullPrefix + fi.Name, fullPrefix + newName)) + const FString fullPrefix = _path + GetPrefix(fi); + if (!NDirectory::MyMoveFile(fullPrefix + fi.Name, fullPrefix + us2fs(newName))) return GetLastError(); return S_OK; } @@ -588,7 +588,7 @@ STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress for (UInt32 i = 0; i < numItems; i++) { const CDirItem &fi = *_refs[indices[i]]; - const UString fullPath = _path + GetRelPath(fi); + const FString fullPath = _path + GetRelPath(fi); bool result; if (fi.IsDir()) result = NDirectory::RemoveDirectoryWithSubItems(fullPath); @@ -614,7 +614,7 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, { case kpidComment: { - UString filename = fi.Name; + UString filename = fs2us(fi.Name); filename.Trim(); if (value->vt == VT_EMPTY) _comments.DeletePair(filename); diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index e39004ad..13e9e018 100755 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -1,7 +1,7 @@ // FSFolder.h -#ifndef __FSFOLDER_H -#define __FSFOLDER_H +#ifndef __FS_FOLDER_H +#define __FS_FOLDER_H #include "Common/MyCom.h" @@ -14,7 +14,7 @@ namespace NFsFolder { class CFSFolder; -struct CFileInfoEx: public NWindows::NFile::NFind::CFileInfoW +struct CFileInfoEx: public NWindows::NFile::NFind::CFileInfo { #ifndef UNDER_CE bool CompressedSizeIsDefined; @@ -74,7 +74,7 @@ public: STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); private: - UString _path; + FString _path; CDirItem _root; CRecordVector<CDirItem *> _refs; @@ -90,24 +90,24 @@ private: HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress); HRESULT GetItemFullSize(int index, UInt64 &size, IProgress *progress); - HRESULT GetComplexName(const wchar_t *name, UString &resultPath); - HRESULT BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder); + HRESULT GetComplexName(CFSTR name, FString &resultPath); + HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder); bool LoadComments(); bool SaveComments(); - HRESULT LoadSubItems(CDirItem &dirItem, const UString &path); + HRESULT LoadSubItems(CDirItem &dirItem, const FString &path); void AddRefs(CDirItem &dirItem); public: - HRESULT Init(const UString &path, IFolderFolder *parentFolder); + HRESULT Init(const FString &path, IFolderFolder *parentFolder); #ifdef UNDER_CE - HRESULT InitToRoot() { return Init(L"\\", NULL); } + HRESULT InitToRoot() { return Init(FTEXT("\\"), NULL); } #endif CFSFolder() : _flatMode(false) {} - UString GetPrefix(const CDirItem &item) const; - UString GetRelPath(const CDirItem &item) const; - UString GetRelPath(UInt32 index) const { return GetRelPath(*_refs[index]); } + FString GetPrefix(const CDirItem &item) const; + FString GetRelPath(const CDirItem &item) const; + FString GetRelPath(UInt32 index) const { return GetRelPath(*_refs[index]); } void Clear() { @@ -116,8 +116,6 @@ public: } }; -HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress); - } #endif diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index b6ffd574..c31498c7 100755 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -102,13 +102,7 @@ typedef BOOL (WINAPI * CopyFileExPointerW)( IN DWORD dwCopyFlags ); -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -static CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } -#endif - -static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +static bool MyCopyFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) { CProgressInfo progressInfo; progressInfo.Progress = progress; @@ -128,8 +122,8 @@ static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progres CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW"); if (copyFunctionW == 0) - return BOOLToBool(::CopyFileW(existingFile, newFile, TRUE)); - if (copyFunctionW(existingFile, newFile, CopyProgressRoutine, + return BOOLToBool(::CopyFileW(fs2us(existingFile), fs2us(newFile), TRUE)); + if (copyFunctionW(fs2us(existingFile), fs2us(newFile), CopyProgressRoutine, &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) return true; #ifdef WIN_LONG_PATH @@ -150,13 +144,13 @@ static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progres "CopyFileExA"); if (copyFunction != 0) { - if (copyFunction(GetSysPath(existingFile), GetSysPath(newFile), + if (copyFunction(fs2fas(existingFile), fs2fas(newFile), CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) return true; if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return false; } - return BOOLToBool(::CopyFile(GetSysPath(existingFile), GetSysPath(newFile), TRUE)); + return BOOLToBool(::CopyFile(fs2fas(existingFile), fs2fas(newFile), TRUE)); } #endif } @@ -169,7 +163,7 @@ typedef BOOL (WINAPI * MoveFileWithProgressPointer)( IN DWORD dwFlags ); -static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +static bool MyMoveFile(CFSTR existingFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) { #ifndef UNDER_CE // if (IsItWindows2000orHigher()) @@ -184,7 +178,7 @@ static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progres if (moveFunction != 0) { if (moveFunction( - existingFile, newFile, CopyProgressRoutine, + fs2us(existingFile), fs2us(newFile), CopyProgressRoutine, &progressInfo, MOVEFILE_COPY_ALLOWED)) return true; if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) @@ -207,41 +201,48 @@ static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progres return NDirectory::MyMoveFile(existingFile, newFile); } +static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, + const wchar_t *message, const FString &fileName) +{ + return callback->ShowMessage(message + fs2us(fileName)); +} + +static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, + const char *message, const FString &fileName) +{ + return SendMessageError(callback, MultiByteToUnicodeString(message), fileName); +} + static HRESULT MyCopyFile( - const UString &srcPath, - const CFileInfoW &srcFileInfo, - const UString &destPathSpec, + const FString &srcPath, + const CFileInfo &srcFileInfo, + const FString &destPathSpec, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { - UString destPath = destPathSpec; + FString destPath = destPathSpec; if (destPath.CompareNoCase(srcPath) == 0) { - UString message = UString(L"can not move file \'") + destPath + UString(L"\' onto itself"); - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not copy file onto itself: ", destPath)); return E_ABORT; } Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite( - srcPath, + fs2us(srcPath), BoolToInt(false), &srcFileInfo.MTime, &srcFileInfo.Size, - destPath, + fs2us(destPath), &destPathResult, &writeAskResult)); if (IntToBool(writeAskResult)) { - UString destPathNew = UString(destPathResult); - RINOK(callback->SetCurrentFilePath(srcPath)); + FString destPathNew = us2fs(destPathResult); + RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); if (!MyCopyFile(srcPath, destPathNew, callback, completedSize)) { - UString message = NError::MyFormatMessageW(GetLastError()) + - UString(L" \'") + - UString(destPathNew) + - UString(L"\'"); - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, NError::MyFormatMessageW(GetLastError()) + L" : ", destPathNew)); return E_ABORT; } } @@ -249,44 +250,41 @@ static HRESULT MyCopyFile( return callback->SetCompleted(&completedSize); } -static UString CombinePath(const UString &folderPath, const UString &fileName) +static FString CombinePath(const FString &folderPath, const FString &fileName) { - return folderPath + UString(WCHAR_PATH_SEPARATOR) + fileName; + return folderPath + FCHAR_PATH_SEPARATOR + fileName; } static HRESULT CopyFolder( - const UString &srcPath, - const UString &destPathSpec, + const FString &srcPath, + const FString &destPathSpec, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { RINOK(callback->SetCompleted(&completedSize)); - const UString destPath = destPathSpec; + const FString destPath = destPathSpec; int len = srcPath.Length(); if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) { - if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + if (destPath.Length() == len || destPath[len] == FCHAR_PATH_SEPARATOR) { - UString message = UString(L"can not copy folder \'") + - destPath + UString(L"\' onto itself"); - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath)); return E_ABORT; } } if (!NDirectory::CreateComplexDirectory(destPath)) { - UString message = UString(L"can not create folder ") + destPath; - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } - CEnumeratorW enumerator(CombinePath(srcPath, L"*")); + CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); CFileInfoEx fi; while (enumerator.Next(fi)) { - const UString srcPath2 = CombinePath(srcPath, fi.Name); - const UString destPath2 = CombinePath(destPath, fi.Name); + const FString srcPath2 = CombinePath(srcPath, fi.Name); + const FString destPath2 = CombinePath(destPath, fi.Name); if (fi.IsDir()) { RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize)) @@ -313,7 +311,7 @@ STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, UString destPath = path; if (destPath.IsEmpty()) return E_INVALIDARG; - bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR); if (directName) { if (numItems > 1) @@ -337,10 +335,10 @@ STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, for (UInt32 i = 0; i < numItems; i++) { const CDirItem &fi = *_refs[indices[i]]; - UString destPath2 = destPath; + FString destPath2 = us2fs(destPath); if (!directName) destPath2 += fi.Name; - UString srcPath = _path + GetPrefix(fi) + fi.Name; + FString srcPath = _path + GetPrefix(fi) + fi.Name; if (fi.IsDir()) { RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); @@ -356,40 +354,35 @@ STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, ///////////////////////////////////////////////// // Move Operations -HRESULT MyMoveFile( - const UString &srcPath, - const CFileInfoW &srcFileInfo, - const UString &destPathSpec, +static HRESULT MyMoveFile( + const FString &srcPath, + const CFileInfo &srcFileInfo, + const FString &destPath, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { - UString destPath = destPathSpec; if (destPath.CompareNoCase(srcPath) == 0) { - UString message = UString(L"can not move file \'") - + destPath + - UString(L"\' onto itself"); - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not move file onto itself: ", srcPath)); return E_ABORT; } Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite( - srcPath, + fs2us(srcPath), BoolToInt(false), &srcFileInfo.MTime, &srcFileInfo.Size, - destPath, + fs2us(destPath), &destPathResult, &writeAskResult)); if (IntToBool(writeAskResult)) { - UString destPathNew = UString(destPathResult); - RINOK(callback->SetCurrentFilePath(srcPath)); + FString destPathNew = us2fs(destPathResult); + RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); if (!MyMoveFile(srcPath, destPathNew, callback, completedSize)) { - UString message = UString(L"can not move to file ") + destPathNew; - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not move to file: ", destPathNew)); } } completedSize += srcFileInfo.Size; @@ -397,21 +390,18 @@ HRESULT MyMoveFile( return S_OK; } -HRESULT MyMoveFolder( - const UString &srcPath, - const UString &destPathSpec, +static HRESULT MyMoveFolder( + const FString &srcPath, + const FString &destPath, IFolderOperationsExtractCallback *callback, UInt64 &completedSize) { - UString destPath = destPathSpec; int len = srcPath.Length(); if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) { - if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + if (destPath.Length() == len || destPath[len] == FCHAR_PATH_SEPARATOR) { - UString message = UString(L"can not move folder \'") + - destPath + UString(L"\' onto itself"); - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath)); return E_ABORT; } } @@ -421,17 +411,16 @@ HRESULT MyMoveFolder( if (!NDirectory::CreateComplexDirectory(destPath)) { - UString message = UString(L"can not create folder ") + destPath; - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } { - CEnumeratorW enumerator(CombinePath(srcPath, L"*")); + CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); CFileInfoEx fi; while (enumerator.Next(fi)) { - const UString srcPath2 = CombinePath(srcPath, fi.Name); - const UString destPath2 = CombinePath(destPath, fi.Name); + const FString srcPath2 = CombinePath(srcPath, fi.Name); + const FString destPath2 = CombinePath(destPath, fi.Name); if (fi.IsDir()) { RINOK(MyMoveFolder(srcPath2, destPath2, callback, completedSize)); @@ -444,8 +433,7 @@ HRESULT MyMoveFolder( } if (!NDirectory::MyRemoveDirectory(srcPath)) { - UString message = UString(L"can not remove folder") + srcPath; - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not remove folder: ", srcPath)); return E_ABORT; } return S_OK; @@ -465,10 +453,10 @@ STDMETHODIMP CFSFolder::MoveTo( RINOK(callback->SetTotal(totalSize)); RINOK(callback->SetNumFiles(numFiles)); - UString destPath = path; + FString destPath = us2fs(path); if (destPath.IsEmpty()) return E_INVALIDARG; - bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + bool directName = (destPath.Back() != FCHAR_PATH_SEPARATOR); if (directName) { if (numItems > 1) @@ -477,9 +465,7 @@ STDMETHODIMP CFSFolder::MoveTo( else if (!NDirectory::CreateComplexDirectory(destPath)) { - UString message = UString(L"can not create folder ") + - destPath; - RINOK(callback->ShowMessage(message)); + RINOK(SendMessageError(callback, "can not create folder: ", destPath)); return E_ABORT; } @@ -488,10 +474,10 @@ STDMETHODIMP CFSFolder::MoveTo( for (UInt32 i = 0; i < numItems; i++) { const CDirItem &fi = *_refs[indices[i]]; - UString destPath2 = destPath; + FString destPath2 = destPath; if (!directName) destPath2 += fi.Name; - UString srcPath = _path + GetPrefix(fi) + fi.Name; + FString srcPath = _path + GetPrefix(fi) + fi.Name; if (fi.IsDir()) { RINOK(MyMoveFolder(srcPath, destPath2, callback, completedSize)); @@ -515,7 +501,7 @@ STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, { UString path = (UString)fromFolderPath + itemsPaths[i]; - CFileInfoW fi; + CFileInfo fi; if (!FindFile(path, fi)) return ::GetLastError(); if (fi.IsDir()) @@ -544,4 +530,9 @@ STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, return E_NOTIMPL; } +STDMETHODIMP CFSFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + } diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 08f15c18..d29ac44c 100755 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -4,6 +4,7 @@ #include "resource.h" +#include "Windows/FileName.h" #include "Windows/Thread.h" #include "../Agent/Agent.h" @@ -11,11 +12,9 @@ #include "LangUtils.h" #include "OpenCallback.h" #include "PluginLoader.h" -#include "RegistryAssociations.h" #include "RegistryPlugins.h" using namespace NWindows; -using namespace NRegistryAssociations; struct CThreadArchiveOpen { @@ -56,9 +55,29 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString & } */ +static const FChar kExtensionDelimiter = FTEXT('.'); + +static void SplitNameToPureNameAndExtension(const FString &fullName, + FString &pureName, FString &extensionDelimiter, FString &extension) +{ + int index = fullName.ReverseFind(kExtensionDelimiter); + if (index < 0) + { + pureName = fullName; + extensionDelimiter.Empty(); + extension.Empty(); + } + else + { + pureName = fullName.Left(index); + extensionDelimiter = kExtensionDelimiter; + extension = fullName.Mid(index + 1); + } +} + HRESULT OpenFileFolderPlugin( IInStream *inStream, - const UString &path, + const FString &path, const UString &arcFormat, HMODULE *module, IFolderFolder **resultFolder, @@ -68,11 +87,11 @@ HRESULT OpenFileFolderPlugin( CObjectVector<CPluginInfo> plugins; ReadFileFolderPluginInfoList(plugins); - UString extension, name, pureName, dot; + FString extension, name, pureName, dot; - int slashPos = path.ReverseFind(WCHAR_PATH_SEPARATOR); - UString dirPrefix; - UString fileName; + int slashPos = path.ReverseFind(FCHAR_PATH_SEPARATOR); + FString dirPrefix; + FString fileName; if (slashPos >= 0) { dirPrefix = path.Left(slashPos + 1); @@ -81,7 +100,7 @@ HRESULT OpenFileFolderPlugin( else fileName = path; - NFile::NName::SplitNameToPureNameAndExtension(fileName, pureName, dot, extension); + SplitNameToPureNameAndExtension(fileName, pureName, dot, extension); /* if (!extension.IsEmpty()) @@ -124,12 +143,12 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec->ParentWindow = parentWindow; if (inStream) - t.OpenCallbackSpec->SetSubArchiveName(fileName); + t.OpenCallbackSpec->SetSubArchiveName(fs2us(fileName)); else t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); t.InStream = inStream; - t.Path = path; + t.Path = fs2us(path); t.ArcFormat = arcFormat; UString progressTitle = LangString(IDS_OPENNING, 0x03020283); diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h index 85717efd..593880e9 100755 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h @@ -3,7 +3,7 @@ #ifndef __FILE_FOLDER_PLUGIN_OPEN_H #define __FILE_FOLDER_PLUGIN_OPEN_H -HRESULT OpenFileFolderPlugin(IInStream *inStream, const UString &path, const UString &arcFormat, +HRESULT OpenFileFolderPlugin(IInStream *inStream, const FString &path, const UString &arcFormat, HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password); #endif diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp index 22993383..b81850fd 100755 --- a/CPP/7zip/UI/FileManager/FilePlugins.cpp +++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp @@ -2,73 +2,39 @@ #include "StdAfx.h" -#include "Common/MyCom.h" - #include "../Agent/Agent.h" #include "FilePlugins.h" #include "PluginLoader.h" #include "StringUtils.h" -using namespace NRegistryAssociations; - -int CExtDatabase::FindExtInfoBig(const UString &ext) -{ - for (int i = 0; i < ExtBigItems.Size(); i++) - if (ExtBigItems[i].Ext.CompareNoCase(ext) == 0) - return i; - return -1; -} - -int CExtDatabase::FindPlugin(const UString &plugin) +int CExtDatabase::FindExt(const UString &ext) { - for (int i = 0; i < Plugins.Size(); i++) - if (Plugins[i].Name.CompareNoCase(plugin) == 0) + for (int i = 0; i < Exts.Size(); i++) + if (Exts[i].Ext.CompareNoCase(ext) == 0) return i; return -1; } void CExtDatabase::Read() { - /* - CObjectVector<CExtInfo> extItems; - ReadInternalAssociations(extItems); - */ ReadFileFolderPluginInfoList(Plugins); - /* - for (int i = 0; i < extItems.Size(); i++) - { - const CExtInfo &extInfo = extItems[i]; - CExtInfoBig extInfoBig; - extInfoBig.Ext = extInfo.Ext; - extInfoBig.Associated = false; - for (int p = 0; p < extInfo.Plugins.Size(); p++) - { - int pluginIndex = FindPlugin(extInfo.Plugins[p]); - if (pluginIndex >= 0) - extInfoBig.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, true)); - } - ExtBigItems.Add(extInfoBig); - } - */ for (int pluginIndex = 0; pluginIndex < Plugins.Size(); pluginIndex++) { - const CPluginInfo &pluginInfo = Plugins[pluginIndex]; + const CPluginInfo &plugin = Plugins[pluginIndex]; - CPluginLibrary pluginLibrary; + CPluginLibrary pluginLib; CMyComPtr<IFolderManager> folderManager; - if (pluginInfo.FilePath.IsEmpty()) + if (plugin.FilePath.IsEmpty()) folderManager = new CArchiveFolderManager; - else if (pluginLibrary.LoadAndCreateManager(pluginInfo.FilePath, - pluginInfo.ClassID, &folderManager) != S_OK) + else if (pluginLib.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &folderManager) != S_OK) continue; CMyComBSTR extBSTR; if (folderManager->GetExtensions(&extBSTR) != S_OK) return; - const UString ext2 = (const wchar_t *)extBSTR; UStringVector exts; - SplitString(ext2, exts); + SplitString((const wchar_t *)extBSTR, exts); for (int i = 0; i < exts.Size(); i++) { const UString &ext = exts[i]; @@ -76,44 +42,28 @@ void CExtDatabase::Read() if (ext == L"cab") continue; #endif - int index = FindExtInfoBig(ext); - if (index < 0) - { - CExtInfoBig extInfo; - extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false)); - extInfo.Associated = false; - extInfo.Ext = ext; - ExtBigItems.Add(extInfo); - } + + Int32 iconIndex; + CMyComBSTR iconPath; + CPluginToIcon plugPair; + plugPair.PluginIndex = pluginIndex; + if (folderManager->GetIconPath(ext, &iconPath, &iconIndex) == S_OK) + if (iconPath != 0) + { + plugPair.IconPath = (const wchar_t *)iconPath; + plugPair.IconIndex = iconIndex; + } + + int index = FindExt(ext); + if (index >= 0) + Exts[index].Plugins.Add(plugPair); else { - CExtInfoBig &extInfo = ExtBigItems[index]; - int pluginIndexIndex = extInfo.FindPlugin(pluginIndex); - if (pluginIndexIndex < 0) - extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false)); + CExtPlugins extInfo; + extInfo.Plugins.Add(plugPair); + extInfo.Ext = ext; + Exts.Add(extInfo); } } } } - -void CExtDatabase::Save() -{ - /* - CObjectVector<CExtInfo> extItems; - for (int i = 0; i < ExtBigItems.Size(); i++) - { - const CExtInfoBig &extInfoBig = ExtBigItems[i]; - CExtInfo extInfo; - // extInfo.Enabled = extInfoBig.Associated; - extInfo.Ext = extInfoBig.Ext; - for (int p = 0; p < extInfoBig.PluginsPairs.Size(); p++) - { - CPluginEnabledPair pluginPair = extInfoBig.PluginsPairs[p]; - if (pluginPair.Enabled) - extInfo.Plugins.Add(Plugins[pluginPair.Index].Name); - } - extItems.Add(extInfo); - } - WriteInternalAssociations(extItems); - */ -} diff --git a/CPP/7zip/UI/FileManager/FilePlugins.h b/CPP/7zip/UI/FileManager/FilePlugins.h index 1becb9d1..43b05f92 100755 --- a/CPP/7zip/UI/FileManager/FilePlugins.h +++ b/CPP/7zip/UI/FileManager/FilePlugins.h @@ -1,54 +1,33 @@ // FilePlugins.h -#ifndef __FILEPLUGINS_H -#define __FILEPLUGINS_H +#ifndef __FILE_PLUGINS_H +#define __FILE_PLUGINS_H #include "RegistryPlugins.h" -#include "RegistryAssociations.h" -struct CPluginEnabledPair +struct CPluginToIcon { - int Index; - bool Enabled; - CPluginEnabledPair(int index, bool enabled): Index(index),Enabled(enabled) {} + int PluginIndex; + UString IconPath; + int IconIndex; + + CPluginToIcon(): IconIndex(-1) {} }; -struct CExtInfoBig +struct CExtPlugins { UString Ext; - bool Associated; - CRecordVector<CPluginEnabledPair> PluginsPairs; - int FindPlugin(int pluginIndex) - { - for (int i = 0; i < PluginsPairs.Size(); i++) - if (PluginsPairs[i].Index == pluginIndex) - return i; - return -1; - } + CObjectVector<CPluginToIcon> Plugins; }; class CExtDatabase { + int FindExt(const UString &ext); public: - CObjectVector<CExtInfoBig> ExtBigItems; + CObjectVector<CExtPlugins> Exts; CObjectVector<CPluginInfo> Plugins; - int FindExtInfoBig(const UString &ext); - int FindPlugin(const UString &plugin); - - UString GetMainPluginNameForExtItem(int extIndex) const - { - const CExtInfoBig &extInfo = ExtBigItems[extIndex]; - if (extInfo.PluginsPairs.IsEmpty()) - return UString(); - else - return Plugins[extInfo.PluginsPairs.Front().Index].Name; - } - + void Read(); - void Save(); }; - #endif - - diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp index 068b9d47..b7366fed 100755 --- a/CPP/7zip/UI/FileManager/FoldersPage.cpp +++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp @@ -42,7 +42,7 @@ bool CFoldersPage::OnInit() m_WorkPath.Init(*this, IDC_FOLDERS_WORK_EDIT_PATH); m_ButtonSetWorkPath.Init(*this, IDC_FOLDERS_WORK_BUTTON_PATH); - m_WorkPath.SetText(m_WorkDirInfo.Path); + m_WorkPath.SetText(fs2us(m_WorkDirInfo.Path)); MyEnableControls(); @@ -66,7 +66,9 @@ void CFoldersPage::MyEnableControls() void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo) { - m_WorkPath.GetText(workDirInfo.Path); + UString s; + m_WorkPath.GetText(s); + workDirInfo.Path = us2fs(s); workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE); workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode()); } @@ -143,7 +145,7 @@ LONG CFoldersPage::OnApply() return PSNRET_NOERROR; } -static LPCWSTR kFoldersTopic = L"fm/plugins/7-zip/options.htm#folders"; +static LPCWSTR kFoldersTopic = L"fm/options.htm#folders"; void CFoldersPage::OnNotifyHelp() { diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp index a1c17399..3128cb28 100755 --- a/CPP/7zip/UI/FileManager/HelpUtils.cpp +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp @@ -5,8 +5,8 @@ #include <HtmlHelp.h> #include "Common/StringConvert.h" +#include "Windows/DLL.h" #include "HelpUtils.h" -#include "ProgramLocation.h" static LPCWSTR kHelpFileName = L"7-zip.chm::/"; @@ -17,11 +17,7 @@ void ShowHelpWindow(HWND, LPCWSTR) #else void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile) { - UString path; - if (!::GetProgramFolderPath(path)) - return; - path += kHelpFileName; - path += topicFile; - HtmlHelp(hwnd, GetSystemString(path), HH_DISPLAY_TOPIC, NULL); + FString path = NWindows::NDLL::GetModuleDirPrefix(); + HtmlHelp(hwnd, GetSystemString(fs2us(path) + kHelpFileName + topicFile), HH_DISPLAY_TOPIC, NULL); } #endif diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h index 743017b8..d6cce88f 100755 --- a/CPP/7zip/UI/FileManager/IFolder.h +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -70,8 +70,9 @@ FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B) STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath, \ const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \ STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \ + STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \ -FOLDER_INTERFACE(IFolderOperations, 0x06) +FOLDER_INTERFACE(IFolderOperations, 0x12) { INTERFACE_FolderOperations(PURE) }; diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 52f85348..20f4655b 100755 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -2,14 +2,16 @@ #include "StdAfx.h" -#include "LangUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" + +#include "Windows/DLL.h" +#include "Windows/FileFind.h" #include "Windows/Synchronization.h" #include "Windows/Window.h" -#include "Windows/FileFind.h" + +#include "LangUtils.h" #include "RegistryUtils.h" -#include "ProgramLocation.h" using namespace NWindows; @@ -20,20 +22,23 @@ UString g_LangID; extern bool g_IsNT; #endif +static FString GetLangDirPrefix() +{ + return NDLL::GetModuleDirPrefix() + FString(FTEXT("Lang") FSTRING_PATH_SEPARATOR); +} + void ReloadLang() { ReadRegLang(g_LangID); g_Lang.Clear(); if (!g_LangID.IsEmpty() && g_LangID != L"-") { - UString langPath = g_LangID; + FString langPath = us2fs(g_LangID); if (langPath.Find(WCHAR_PATH_SEPARATOR) < 0) { - if (langPath.Find(L'.') < 0) - langPath += L".txt"; - UString folderPath; - if (GetProgramFolderPath(folderPath)) - langPath = folderPath + UString(L"Lang" WSTRING_PATH_SEPARATOR) + langPath; + if (langPath.Find(FTEXT('.')) < 0) + langPath += FTEXT(".txt"); + langPath = GetLangDirPrefix() + langPath; } g_Lang.Open(langPath); } @@ -51,7 +56,7 @@ void LoadLangOneTime() ReloadLang(); } -void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems) +void LangSetDlgItemsText(HWND dialogWindow, const CIDLangPair *idLangPairs, int numItems) { for (int i = 0; i < numItems; i++) { @@ -85,30 +90,26 @@ UString LangString(UINT resourceID, UInt32 langID) UString message; if (g_Lang.GetMessage(langID, message)) return message; - return NWindows::MyLoadStringW(resourceID); + return MyLoadStringW(resourceID); } void LoadLangs(CObjectVector<CLangEx> &langs) { langs.Clear(); - UString folderPath; - if (!::GetProgramFolderPath(folderPath)) - return; - folderPath += L"Lang" WSTRING_PATH_SEPARATOR; - NWindows::NFile::NFind::CEnumeratorW enumerator(folderPath + L"*.txt"); - NWindows::NFile::NFind::CFileInfoW fileInfo; - while (enumerator.Next(fileInfo)) + const FString dirPrefix = GetLangDirPrefix(); + NFile::NFind::CEnumerator enumerator(dirPrefix + FTEXT("*.txt")); + NFile::NFind::CFileInfo fi; + while (enumerator.Next(fi)) { - if (fileInfo.IsDir()) + if (fi.IsDir()) continue; - CLangEx lang; - UString filePath = folderPath + fileInfo.Name; const int kExtSize = 4; - const UString ext = fileInfo.Name.Right(kExtSize); - if (ext.CompareNoCase(L".txt") != 0) + const FString ext = fi.Name.Right(kExtSize); + if (ext.CompareNoCase(FTEXT(".txt")) != 0) continue; - lang.ShortName = fileInfo.Name.Left(fileInfo.Name.Length() - kExtSize); - if (lang.Lang.Open(filePath)) + CLangEx lang; + lang.ShortName = fs2us(fi.Name.Left(fi.Name.Length() - kExtSize)); + if (lang.Lang.Open(dirPrefix + fi.Name)) langs.Add(lang); } } diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h index 40debdfe..d11082f6 100755 --- a/CPP/7zip/UI/FileManager/LangUtils.h +++ b/CPP/7zip/UI/FileManager/LangUtils.h @@ -1,7 +1,7 @@ // LangUtils.h -#ifndef __LANGUTILS_H -#define __LANGUTILS_H +#ifndef __LANG_UTILS_H +#define __LANG_UTILS_H #include "Common/Lang.h" #include "Windows/ResourceString.h" @@ -26,7 +26,7 @@ struct CLangEx void LoadLangs(CObjectVector<CLangEx> &langs); -void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems); +void LangSetDlgItemsText(HWND dialogWindow, const CIDLangPair *idLangPairs, int numItems); void LangSetWindowText(HWND window, UInt32 langID); UString LangString(UInt32 langID); diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp index f70572b9..b3e989c4 100755 --- a/CPP/7zip/UI/FileManager/ListViewDialog.cpp +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -125,17 +125,12 @@ bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header) } case 'A': { - // probably that code is unused ? - /* bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; if (ctrl) { - int numItems = _listView.GetItemCount(); - for (int i = 0; i < numItems; i++) - _listView.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); + _listView.SelectAll(); return true; } - */ } } } diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index e1041204..c3e013b5 100755 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -23,7 +23,7 @@ static CIDLangPair kIDLangPairs[] = { IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, 0x01000310} }; -static LPCWSTR kSystemTopic = L"fm/plugins/7-zip/options.htm#system"; +static LPCWSTR kSystemTopic = L"fm/options.htm#sevenZip"; struct CContextMenuItem { diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp index 3d73ade1..05aa823f 100755 --- a/CPP/7zip/UI/FileManager/MessagesDialog.cpp +++ b/CPP/7zip/UI/FileManager/MessagesDialog.cpp @@ -51,10 +51,7 @@ bool CMessagesDialog::OnInit() LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); #endif _messageList.Attach(GetItem(IDC_MESSAGE_LIST)); - - #ifndef UNDER_CE - _messageList.SetUnicodeFormat(true); - #endif + _messageList.SetUnicodeFormat(); _messageList.InsertColumn(0, L"", 30); diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index ccfd33cc..b16e8948 100755 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -513,6 +513,13 @@ bool ExecuteFileCommand(int id) return true; } +static void MyBenchmark(bool totalMode) +{ + CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]); + CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]); + Benchmark(totalMode); +} + bool OnMenuCommand(HWND hWnd, int id) { if (ExecuteFileCommand(id)) @@ -538,31 +545,31 @@ bool OnMenuCommand(HWND hWnd, int id) break; case IDM_SELECT_ALL: g_App.SelectAll(true); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_DESELECT_ALL: g_App.SelectAll(false); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_INVERT_SELECTION: g_App.InvertSelection(); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_SELECT: g_App.SelectSpec(true); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_DESELECT: g_App.SelectSpec(false); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_SELECT_BY_TYPE: g_App.SelectByType(true); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; case IDM_DESELECT_BY_TYPE: g_App.SelectByType(false); - g_App.RefreshStatusBar(); + g_App.Refresh_StatusBar(); break; //View @@ -646,13 +653,9 @@ bool OnMenuCommand(HWND hWnd, int id) OptionsDialog(hWnd, g_hInstance); break; - case IDM_BENCHMARK: - { - CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]); - CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]); - Benchmark(); - break; - } + case IDM_BENCHMARK: MyBenchmark(false); break; + case IDM_BENCHMARK2: MyBenchmark(true); break; + // Help case IDM_HELP_CONTENTS: ShowHelpWindow(NULL, kFMHelpTopic); diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp index e1fa1965..07387328 100755 --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -136,8 +136,8 @@ STDMETHODIMP CNetFolder::LoadItems() resource.RemoteName = _path + resource.Name; NFile::NFind::CFindFile findFile; - NFile::NFind::CFileInfoW fileInfo; - if (!findFile.FindFirst(resource.RemoteName + UString(WCHAR_PATH_SEPARATOR) + UString(L"*"), fileInfo)) + NFile::NFind::CFileInfo fileInfo; + if (!findFile.FindFirst(us2fs(resource.RemoteName) + FString(FCHAR_PATH_SEPARATOR) + FCHAR_ANY_MASK, fileInfo)) continue; resource.Usage = RESOURCEUSAGE_CONNECTABLE; resource.LocalNameIsDefined = false; @@ -185,7 +185,7 @@ STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder { NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; CMyComPtr<IFolderFolder> subFolder = fsFolderSpec; - RINOK(fsFolderSpec->Init(resource.RemoteName + WCHAR_PATH_SEPARATOR, this)); + RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR), this)); *resultFolder = subFolder.Detach(); } else @@ -253,7 +253,7 @@ STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER || resource.Usage == RESOURCEUSAGE_CONNECTABLE) { - if (GetRealIconIndex(resource.RemoteName, 0, iconIndexTemp)) + if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp)) { *iconIndex = iconIndexTemp; return S_OK; @@ -261,7 +261,7 @@ STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) } else { - if (GetRealIconIndex(TEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp)) + if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp)) { *iconIndex = iconIndexTemp; return S_OK; diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp index 72245ac4..95daf37a 100755 --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -8,6 +8,8 @@ #include "../../Common/FileStreams.h" +#include "../Common/ZipRegistry.h" + #include "OpenCallback.h" #include "PasswordDialog.h" @@ -82,16 +84,15 @@ STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value return S_OK; } -STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, - IInStream **inStream) +STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream) { *inStream = NULL; if (_subArchiveMode) return S_FALSE; - NFile::NFind::CFileInfoW fileInfo; + NFile::NFind::CFileInfo fileInfo; - UString fullPath = _folderPrefix + name; + FString fullPath = _folderPrefix + us2fs(name); if (!fileInfo.Find(fullPath)) return S_FALSE; _fileInfo = fileInfo; @@ -111,6 +112,8 @@ STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { CPasswordDialog dialog; + bool showPassword = NExtract::Read_ShowPassword(); + dialog.ShowPassword = showPassword; ProgressDialog.WaitCreating(); if (dialog.Create(ProgressDialog) == IDCANCEL) @@ -118,6 +121,8 @@ STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password) Password = dialog.Password; PasswordIsDefined = true; + if (dialog.ShowPassword != showPassword) + NExtract::Save_ShowPassword(dialog.ShowPassword); } return StringToBstr(Password, password); } diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h index 559eb8fc..a0c0167e 100755 --- a/CPP/7zip/UI/FileManager/OpenCallback.h +++ b/CPP/7zip/UI/FileManager/OpenCallback.h @@ -27,8 +27,8 @@ class COpenArchiveCallback: public ICryptoGetTextPassword, public CMyUnknownImp { - UString _folderPrefix; - NWindows::NFile::NFind::CFileInfoW _fileInfo; + FString _folderPrefix; + NWindows::NFile::NFind::CFileInfo _fileInfo; NWindows::NSynchronization::CCriticalSection _criticalSection; bool _subArchiveMode; UString _subArchiveName; @@ -75,7 +75,7 @@ public: _subArchiveMode = false; } */ - void LoadFileInfo(const UString &folderPrefix, const UString &fileName) + void LoadFileInfo(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; if (!_fileInfo.Find(_folderPrefix + fileName)) diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp index 7a7e90fb..a1ef1b1d 100755 --- a/CPP/7zip/UI/FileManager/OptionsDialog.cpp +++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp @@ -24,7 +24,6 @@ #include "App.h" #include "LangUtils.h" #include "MyLoadMenu.h" -#include "ProgramLocation.h" #include "resource.h" @@ -42,11 +41,10 @@ static void ShowMenuErrorMessage(const wchar_t *m) static int DllRegisterServer2(const char *name) { - NWindows::NDLL::CLibrary lib; + NDLL::CLibrary lib; - UString prefix; - GetProgramFolderPath(prefix); - if (!lib.Load(prefix + L"7-zip.dll")) + FString prefix = NDLL::GetModuleDirPrefix(); + if (!lib.Load(prefix + FTEXT("7-zip.dll"))) { ShowMenuErrorMessage(L"7-Zip cannot load 7-zip.dll"); return E_FAIL; @@ -94,7 +92,7 @@ void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) CFoldersPage foldersPage; CObjectVector<NControl::CPageInfo> pages; - UINT32 langIDs[] = { 0x03010300, + const UInt32 langIDs[] = { 0x03010300, // 0x03010100, 0xFFFFFFFF, 0x01000200, 0x03010200, 0x03010400, 0x01000400}; diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index 27aa7a54..ebbe12b9 100755 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -79,6 +79,7 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, _mainWindow = mainWindow; _processTimer = true; _processNotify = true; + _processStatusBar = true; _panelCallback = panelCallback; _appState = appState; @@ -91,8 +92,11 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, if (!currentFolderPrefix.IsEmpty()) if (currentFolderPrefix[0] == L'.') - if (!NFile::NDirectory::MyGetFullPathName(currentFolderPrefix, cfp)) - cfp = currentFolderPrefix; + { + FString cfpF; + if (NFile::NDirectory::MyGetFullPathName(us2fs(currentFolderPrefix), cfpF)) + cfp = fs2us(cfpF); + } RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted)); if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE, @@ -104,7 +108,7 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { - switch(message) + switch (message) { case kShiftSelectMessage: OnShiftSelectMessage(); @@ -117,12 +121,15 @@ LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) return 0; case kOpenItemChanged: return OnOpenItemChanged(lParam); - case kRefreshStatusBar: - OnRefreshStatusBar(); + case kRefresh_StatusBar: + if (_processStatusBar) + Refresh_StatusBar(); return 0; - case kRefreshHeaderComboBox: + #ifdef UNDER_CE + case kRefresh_HeaderComboBox: LoadFullPathAndShow(); return 0; + #endif case WM_TIMER: OnTimer(); return 0; @@ -139,15 +146,6 @@ LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) return CWindow2::OnMessage(message, wParam, lParam); } -static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - CWindow tempDialog(hwnd); - CMyListView *w = (CMyListView *)(tempDialog.GetUserDataLongPtr()); - if (w == NULL) - return 0; - return w->OnMessage(message, wParam, lParam); -} - LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_CHAR) @@ -187,7 +185,7 @@ LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0; // bool RightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0; bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; - switch(wParam) + switch (wParam) { /* case VK_RETURN: @@ -233,12 +231,7 @@ LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) _panel->_lastFocusedIsList = true; _panel->_panelCallback->PanelWasFocused(); } - #ifndef _UNICODE - if (g_IsNT) - return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); - else - #endif - return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); + return CListView2::OnMessage(message, wParam, lParam); } /* @@ -365,21 +358,9 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) HWND(*this), (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL)) return false; - #ifndef UNDER_CE - _listView.SetUnicodeFormat(true); - #endif - - _listView.SetUserDataLongPtr(LONG_PTR(&_listView)); + _listView.SetUnicodeFormat(); _listView._panel = this; - - #ifndef _UNICODE - if(g_IsNT) - _listView._origWindowProc = - (WNDPROC)_listView.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc)); - else - #endif - _listView._origWindowProc = - (WNDPROC)_listView.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc)); + _listView.SetWindowProc(); _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL); _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL); @@ -552,7 +533,6 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) // InitListCtrl(); RefreshListCtrl(); - RefreshStatusBar(); return true; } @@ -614,7 +594,7 @@ bool CPanel::OnSize(WPARAM /* wParam */, int xSize, int ySize) bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */) { - switch(header->code) + switch (header->code) { case RBN_HEIGHTCHANGE: { @@ -790,9 +770,10 @@ void CPanel::ChangeFlatMode() } -void CPanel::RefreshStatusBar() +void CPanel::Post_Refresh_StatusBar() { - PostMessage(kRefreshStatusBar); + if (_processStatusBar) + PostMessage(kRefresh_StatusBar); } void CPanel::AddToArchive() @@ -953,6 +934,12 @@ void CPanel::TestArchives() extracter.ExtractCallbackSpec = new CExtractCallbackImp; extracter.ExtractCallback = extracter.ExtractCallbackSpec; extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog; + if (!_parentFolders.IsEmpty()) + { + const CFolderLink &fl = _parentFolders.Back(); + extracter.ExtractCallbackSpec->PasswordIsDefined = fl.UsePassword; + extracter.ExtractCallbackSpec->Password = fl.Password; + } if (indices.IsEmpty()) return; diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 9cda94a4..e33a37a2 100755 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -85,13 +85,14 @@ public: struct CTempFileInfo { - UString ItemName; - UString FolderPath; - UString FilePath; - NWindows::NFile::NFind::CFileInfoW FileInfo; + UInt32 FileIndex; // index of file in folder + UString RelPath; // Relative path of file from Folder + FString FolderPath; + FString FilePath; + NWindows::NFile::NFind::CFileInfo FileInfo; bool NeedDelete; - CTempFileInfo(): NeedDelete(false) {} + CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {} void DeleteDirAndFile() const { if (NeedDelete) @@ -100,7 +101,7 @@ struct CTempFileInfo NWindows::NFile::NDirectory::MyRemoveDirectory(FolderPath); } } - bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const { return newFileInfo.Size != FileInfo.Size || CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; @@ -118,7 +119,7 @@ struct CFolderLink: public CTempFileInfo UString VirtualPath; CFolderLink(): UsePassword(false), IsVirtual(false) {} - bool WasChanged(const NWindows::NFile::NFind::CFileInfoW &newFileInfo) const + bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const { return IsVirtual || CTempFileInfo::WasChanged(newFileInfo); } @@ -131,18 +132,19 @@ enum MyMessages kReLoadMessage, kSetFocusToListView, kOpenItemChanged, - kRefreshStatusBar, - kRefreshHeaderComboBox + kRefresh_StatusBar + #ifdef UNDER_CE + , kRefresh_HeaderComboBox + #endif }; UString GetFolderPath(IFolderFolder * folder); class CPanel; -class CMyListView: public NWindows::NControl::CListView +class CMyListView: public NWindows::NControl::CListView2 { public: - WNDPROC _origWindowProc; CPanel *_panel; LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; @@ -482,34 +484,33 @@ public: bool _processTimer; bool _processNotify; + bool _processStatusBar; class CDisableTimerProcessing { bool _processTimerMem; bool _processNotifyMem; + bool _processStatusBarMem; CPanel &_panel; public: - CDisableTimerProcessing(CPanel &panel): _panel(panel) - { - Disable(); - } + CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); } + ~CDisableTimerProcessing() { Restore(); } void Disable() { _processTimerMem = _panel._processTimer; _processNotifyMem = _panel._processNotify; + _processStatusBarMem = _panel._processStatusBar; _panel._processTimer = false; _panel._processNotify = false; + _panel._processStatusBar = false; } void Restore() { _panel._processTimer = _processTimerMem; _panel._processNotify = _processNotifyMem; - } - ~CDisableTimerProcessing() - { - Restore(); + _panel._processStatusBar = _processStatusBarMem; } CDisableTimerProcessing& operator=(const CDisableTimerProcessing &) {; } }; @@ -544,11 +545,11 @@ public: const UString &virtualFilePath, const UString &arcFormat, bool &encrypted); - HRESULT OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted); + HRESULT OpenItemAsArchive(const UString &relPath, const UString &arcFormat, bool &encrypted); HRESULT OpenItemAsArchive(int index); void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode); - HRESULT OnOpenItemChanged(const UString &folderPath, const UString &itemName, bool usePassword, const UString &password); + HRESULT OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password); LRESULT OnOpenItemChanged(LPARAM lParam); void OpenItem(int index, bool tryInternal, bool tryExternal); @@ -565,8 +566,8 @@ public: void ChangeFlatMode(); bool GetFlatMode() const { return _flatMode; } - void RefreshStatusBar(); - void OnRefreshStatusBar(); + void Post_Refresh_StatusBar(); + void Refresh_StatusBar(); void AddToArchive(); diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index 6b00a9b5..2dd5e7ce 100755 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -29,13 +29,13 @@ static const UInt32 kBufSize = (1 << 15); struct CDirEnumerator { bool FlatMode; - UString BasePrefix; - UStringVector FileNames; + FString BasePrefix; + FStringVector FileNames; - CObjectVector<NFind::CEnumeratorW> Enumerators; - UStringVector Prefixes; + CObjectVector<NFind::CEnumerator> Enumerators; + FStringVector Prefixes; int Index; - HRESULT GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &fullPath); + HRESULT GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &fullPath); void Init(); CDirEnumerator(): FlatMode(false) {}; @@ -54,7 +54,7 @@ static HRESULT GetNormalizedError() return (errorCode == 0) ? E_FAIL : errorCode; } -HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath) +HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &resPath) { filled = false; for (;;) @@ -63,8 +63,8 @@ HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, U { if (Index >= FileNames.Size()) return S_OK; - const UString &path = FileNames[Index]; - int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + const FString &path = FileNames[Index]; + int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); resPath.Empty(); if (pos >= 0) resPath = path.Left(pos + 1); @@ -106,8 +106,8 @@ HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, U resPath += fileInfo.Name; if (!FlatMode && fileInfo.IsDir()) { - UString prefix = resPath + WCHAR_PATH_SEPARATOR; - Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)NName::kAnyStringWildcard)); + FString prefix = resPath + FCHAR_PATH_SEPARATOR; + Enumerators.Add(NFind::CEnumerator(BasePrefix + prefix + FCHAR_ANY_MASK)); Prefixes.Add(prefix); } filled = true; @@ -212,13 +212,13 @@ HRESULT CThreadCrc::ProcessVirt() for (;;) { - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; bool filled; - UString resPath; + FString resPath; HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); if (errorCode != 0) { - ErrorPath1 = resPath; + SetErrorPath1(resPath); return errorCode; } if (!filled) @@ -228,7 +228,7 @@ HRESULT CThreadCrc::ProcessVirt() totalSize += fileInfo.Size; NumFilesScan++; } - sync.SetCurrentFileName(scanningStr + resPath); + sync.SetCurrentFileName(scanningStr + fs2us(resPath)); sync.SetProgress(totalSize, 0); RINOK(sync.SetPosAndCheckPaused(0)); } @@ -239,13 +239,13 @@ HRESULT CThreadCrc::ProcessVirt() for (;;) { - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; bool filled; - UString resPath; + FString resPath; HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); if (errorCode != 0) { - ErrorPath1 = resPath; + SetErrorPath1(resPath); return errorCode; } if (!filled) @@ -263,10 +263,10 @@ HRESULT CThreadCrc::ProcessVirt() if (!inFile.Open(Enumerator.BasePrefix + resPath)) { errorCode = GetNormalizedError(); - ErrorPath1 = resPath; + SetErrorPath1(resPath); return errorCode; } - sync.SetCurrentFileName(resPath); + sync.SetCurrentFileName(fs2us(resPath)); sync.SetNumFilesCur(NumFiles); NumFiles++; for (;;) @@ -275,7 +275,7 @@ HRESULT CThreadCrc::ProcessVirt() if (!inFile.Read(buffer, kBufSize, processedSize)) { errorCode = GetNormalizedError(); - ErrorPath1 = resPath; + SetErrorPath1(resPath); return errorCode; } if (processedSize == 0) @@ -323,8 +323,8 @@ void CApp::CalculateCrc() { CThreadCrc t; for (int i = 0; i < indices.Size(); i++) - t.Enumerator.FileNames.Add(srcPanel.GetItemRelPath(indices[i])); - t.Enumerator.BasePrefix = srcPanel.GetFsPath(); + t.Enumerator.FileNames.Add(us2fs(srcPanel.GetItemRelPath(indices[i]))); + t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath()); t.Enumerator.FlatMode = GetFlatMode(); t.ProgressDialog.ShowCompressionInfo = false; diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index eb5ad871..02bccc03 100755 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -10,6 +10,7 @@ #include "Windows/Memory.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" #include "Windows/Shell.h" #include "../Common/ArchiveName.h" @@ -26,7 +27,7 @@ using namespace NWindows; extern bool g_IsNT; #endif -static wchar_t *kTempDirPrefix = L"7zE"; +static CFSTR kTempDirPrefix = FTEXT("7zE"); static LPCTSTR kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder"); //////////////////////////////////////////////////////// @@ -304,12 +305,12 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) // CSelectedState selState; // SaveSelectedState(selState); - UString dirPrefix; - NFile::NDirectory::CTempDirectoryW tempDirectory; + FString dirPrefix; + NFile::NDirectory::CTempDir tempDirectory; bool isFSFolder = IsFSFolder(); if (isFSFolder) - dirPrefix = _currentFolderPrefix; + dirPrefix = us2fs(_currentFolderPrefix); else { tempDirectory.Create(kTempDirPrefix); @@ -330,7 +331,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) s = GetItemRelPath(index); else s = GetItemName(index); - names.Add(dirPrefix + s); + names.Add(fs2us(dirPrefix) + s); } if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names)) return; @@ -341,7 +342,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) dropSourceSpec->NeedExtract = !isFSFolder; dropSourceSpec->Panel = this; dropSourceSpec->Indices = indices; - dropSourceSpec->Folder = dirPrefix; + dropSourceSpec->Folder = fs2us(dirPrefix); dropSourceSpec->DataObjectSpec = dataObjectSpec; dropSourceSpec->DataObject = dataObjectSpec; @@ -748,9 +749,9 @@ void CPanel::CompressDropFiles(HDROP dr) } */ -static bool IsFolderInTemp(const UString &path) +static bool IsFolderInTemp(const FString &path) { - UString tempPath; + FString tempPath; if (!NFile::NDirectory::MyGetTempPath(tempPath)) return false; if (tempPath.IsEmpty()) @@ -760,9 +761,10 @@ static bool IsFolderInTemp(const UString &path) static bool AreThereNamesFromTemp(const UStringVector &fileNames) { - UString tempPath; - if (!NFile::NDirectory::MyGetTempPath(tempPath)) + FString tempPathF; + if (!NFile::NDirectory::MyGetTempPath(tempPathF)) return false; + UString tempPath = fs2us(tempPathF); if (tempPath.IsEmpty()) return false; for (int i = 0; i < fileNames.Size(); i++) @@ -784,8 +786,10 @@ void CPanel::CompressDropFiles(const UStringVector &fileNames, const UString &fo UString folderPath2 = folderPath; if (folderPath2.IsEmpty()) { - NFile::NDirectory::GetOnlyDirPrefix(fileNames.Front(), folderPath2); - if (IsFolderInTemp(folderPath2)) + FString folderPath2F; + NFile::NDirectory::GetOnlyDirPrefix(us2fs(fileNames.Front()), folderPath2F); + folderPath2 = fs2us(folderPath2F); + if (IsFolderInTemp(folderPath2F)) folderPath2 = ROOT_FS_FOLDER; } const UString archiveName = CreateArchiveName(fileNames.Front(), (fileNames.Size() > 1), false); diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index afa4c041..995124be 100755 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -5,6 +5,7 @@ #include "Common/StringConvert.h" #include "Common/Wildcard.h" +#include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "../../PropID.h" @@ -73,11 +74,11 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo CloseOpenFolders(); UString sysPath = fullPath; - CFileInfoW fileInfo; + CFileInfo fileInfo; UStringVector reducedParts; while (!sysPath.IsEmpty()) { - if (fileInfo.Find(sysPath)) + if (fileInfo.Find(us2fs(sysPath))) break; int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0) @@ -104,17 +105,14 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo } else { - UString dirPrefix; - if (!NDirectory::GetOnlyDirPrefix(sysPath, dirPrefix)) - dirPrefix.Empty(); - if (_folder->BindToFolder(dirPrefix, &newFolder) == S_OK) + FString dirPrefix, fileName; + NDirectory::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); + if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK) { _folder = newFolder; LoadFullPath(); - UString fileName; - if (NDirectory::GetOnlyName(sysPath, fileName)) { - HRESULT res = OpenItemAsArchive(fileName, arcFormat, encrypted); + HRESULT res = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted); if (res != S_FALSE) { RINOK(res); @@ -176,14 +174,14 @@ void CPanel::LoadFullPath() { const CFolderLink &folderLink = _parentFolders[i]; _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder); - _currentFolderPrefix += folderLink.ItemName; + _currentFolderPrefix += folderLink.RelPath; _currentFolderPrefix += WCHAR_PATH_SEPARATOR; } if (_folder) _currentFolderPrefix += GetFolderPath(_folder); } -static int GetRealIconIndex(LPCWSTR path, DWORD attributes) +static int GetRealIconIndex(CFSTR path, DWORD attributes) { int index = -1; if (GetRealIconIndex(path, attributes, index) != 0) @@ -209,15 +207,22 @@ void CPanel::LoadFullPathAndShow() #else 1 #endif - && path[path.Length() - 1] == WCHAR_PATH_SEPARATOR) - path.Delete(path.Length() - 1); + && path.Back() == WCHAR_PATH_SEPARATOR) + path.DeleteBack(); - CFileInfoW info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; - if (info.Find(path)) - attrib = info.Attrib; - - item.iImage = GetRealIconIndex(path, attrib); + + // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path + UString excludePrefix = L"\\\\.\\"; + UString path2 = L"_TestFolder_"; + if (excludePrefix != path.Left(excludePrefix.Length())) + { + path2 = path; + CFileInfo info; + if (info.Find(us2fs(path))) + attrib = info.Attrib; + } + item.iImage = GetRealIconIndex(us2fs(path2), attrib); if (item.iImage >= 0) { @@ -356,11 +361,11 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) UString name = pathParts[i]; sumPass += name; sumPass += WCHAR_PATH_SEPARATOR; - CFileInfoW info; + CFileInfo info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; - if (info.Find(sumPass)) + if (info.Find(us2fs(sumPass))) attrib = info.Attrib; - AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(sumPass, attrib), i, false); + AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(us2fs(sumPass), attrib), i, false); ComboBoxPaths.Add(sumPass); } @@ -374,16 +379,16 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) name = RootFolder_GetName_Computer(iconIndex); AddComboBoxItem(name, iconIndex, 0, true); - UStringVector driveStrings; + FStringVector driveStrings; MyGetLogicalDriveStrings(driveStrings); for (i = 0; i < driveStrings.Size(); i++) { - UString s = driveStrings[i]; - ComboBoxPaths.Add(s); + FString s = driveStrings[i]; + ComboBoxPaths.Add(fs2us(s)); int iconIndex = GetRealIconIndex(s, 0); - if (s.Length() > 0 && s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) - s.Delete(s.Length() - 1); - AddComboBoxItem(s, iconIndex, 1, false); + if (s.Length() > 0 && s.Back() == FCHAR_PATH_SEPARATOR) + s.DeleteBack(); + AddComboBoxItem(fs2us(s), iconIndex, 1, false); } name = RootFolder_GetName_Network(iconIndex); @@ -407,9 +412,8 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) { PostMessage(kSetFocusToListView); #ifdef UNDER_CE - PostMessage(kRefreshHeaderComboBox); + PostMessage(kRefresh_HeaderComboBox); #endif - return true; } } @@ -522,7 +526,7 @@ void CPanel::OpenParentFolder() CFolderLink &link = _parentFolders.Back(); _folder = link.ParentFolder; _library.Attach(link.Library.Detach()); - focucedName = link.ItemName; + focucedName = link.RelPath; if (_parentFolders.Size() > 1) OpenParentArchiveFolder(); _parentFolders.DeleteBack(); @@ -540,7 +544,6 @@ void CPanel::OpenParentFolder() // ::SetCurrentDirectory(::_currentFolderPrefix); RefreshListCtrl(focucedName, -1, true, selectedItems); _listView.EnsureVisible(_listView.GetFocusedItem(), false); - RefreshStatusBar(); } void CPanel::CloseOpenFolders() @@ -607,7 +610,6 @@ void CPanel::OpenFolder(int index) LoadFullPath(); // ::SetCurrentDirectory(::_currentFolderPrefix); RefreshListCtrl(); - UINT state = LVIS_SELECTED; - _listView.SetItemState(_listView.GetFocusedItem(), state, state); + _listView.SetItemState_Selected(_listView.GetFocusedItem()); _listView.EnsureVisible(_listView.GetFocusedItem(), false); } diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index 934e98d3..6c4309c6 100755 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -2,12 +2,15 @@ #include "StdAfx.h" +#include <tlhelp32.h> + #include "Common/AutoPtr.h" #include "Common/StringConvert.h" #include "Windows/Error.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "Windows/Process.h" #include "Windows/PropVariant.h" #include "Windows/Thread.h" @@ -33,8 +36,122 @@ using namespace NDirectory; extern bool g_IsNT; #endif -static wchar_t *kTempDirPrefix = L"7zO"; +static CFSTR kTempDirPrefix = FTEXT("7zO"); + +#ifndef UNDER_CE + +class CProcessSnapshot +{ + HANDLE _handle; +public: + CProcessSnapshot(): _handle(INVALID_HANDLE_VALUE) {}; + ~CProcessSnapshot() { Close(); } + + bool Close() + { + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; + } + + bool Create() + { + _handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + return (_handle != INVALID_HANDLE_VALUE); + } + + bool GetFirstProcess(PROCESSENTRY32 *pe) { return BOOLToBool(Process32First(_handle, pe)); } + bool GetNextProcess(PROCESSENTRY32 *pe) { return BOOLToBool(Process32Next(_handle, pe)); } +}; + +#endif + +typedef DWORD (WINAPI *GetProcessIdFunc)(HANDLE process); + +class CChildProcesses +{ + #ifndef UNDER_CE + CRecordVector<DWORD> _ids; + #endif +public: + CRecordVector<HANDLE> Handles; + CRecordVector<bool> NeedWait; + + ~CChildProcesses() { CloseAll(); } + void DisableWait(int index) { NeedWait[index] = false; } + + void CloseAll() + { + for (int i = 0; i < Handles.Size(); i++) + { + HANDLE h = Handles[i]; + if (h != NULL) + CloseHandle(h); + } + Handles.Clear(); + NeedWait.Clear(); + } + + void AddProcess(HANDLE h) + { + #ifndef UNDER_CE + GetProcessIdFunc func = (GetProcessIdFunc)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId"); + if (func) + _ids.AddToUniqueSorted(func(h)); + #endif + Handles.Add(h); + NeedWait.Add(true); + } + + void Update() + { + #ifndef UNDER_CE + CRecordVector<DWORD> ids, parents; + { + CProcessSnapshot snapshot; + if (snapshot.Create()) + { + PROCESSENTRY32 pe; + memset(&pe, 0, sizeof(pe)); + pe.dwSize = sizeof(pe); + BOOL res = snapshot.GetFirstProcess(&pe); + while (res) + { + ids.Add(pe.th32ProcessID); + parents.Add(pe.th32ParentProcessID); + res = snapshot.GetNextProcess(&pe); + } + } + } + for (;;) + { + int i; + for (i = 0; i < ids.Size(); i++) + { + DWORD id = ids[i]; + if (_ids.FindInSorted(parents[i]) >= 0 && + _ids.FindInSorted(id) < 0) + { + HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, id); + if (hProcess) + { + _ids.AddToUniqueSorted(id); + Handles.Add(hProcess); + NeedWait.Add(true); + break; + } + } + } + if (i == ids.Size()) + break; + } + #endif + } +}; static bool IsNameVirus(const UString &name) { @@ -43,11 +160,12 @@ static bool IsNameVirus(const UString &name) struct CTmpProcessInfo: public CTempFileInfo { - HANDLE ProcessHandle; + CChildProcesses Processes; HWND Window; UString FullPathFolderPrefix; bool UsePassword; UString Password; + CTmpProcessInfo(): UsePassword(false) {} }; @@ -56,8 +174,8 @@ class CTmpProcessInfoRelease CTmpProcessInfo *_tmpProcessInfo; public: bool _needDelete; - CTmpProcessInfoRelease(CTmpProcessInfo &tmpProcessInfo): - _tmpProcessInfo(&tmpProcessInfo), _needDelete(true) {} + CTmpProcessInfoRelease(CTmpProcessInfo &tpi): + _tmpProcessInfo(&tpi), _needDelete(true) {} ~CTmpProcessInfoRelease() { if (_needDelete) @@ -96,7 +214,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, UString password; RINOK(OpenFileFolderPlugin(inStream, - folderLink.FilePath.IsEmpty() ? virtualFilePath : folderLink.FilePath, + folderLink.FilePath.IsEmpty() ? us2fs(virtualFilePath) : folderLink.FilePath, arcFormat, &library, &newFolder, GetParent(), encrypted, password)); @@ -157,13 +275,14 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, return S_OK; } -HRESULT CPanel::OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted) +HRESULT CPanel::OpenItemAsArchive(const UString &relPath, const UString &arcFormat, bool &encrypted) { CTempFileInfo tfi; - tfi.ItemName = name; - tfi.FolderPath = _currentFolderPrefix; - tfi.FilePath = _currentFolderPrefix + name; - return OpenItemAsArchive(NULL, tfi, _currentFolderPrefix + name, arcFormat, encrypted); + tfi.RelPath = relPath; + tfi.FolderPath = us2fs(_currentFolderPrefix); + const UString fullPath = _currentFolderPrefix + relPath; + tfi.FilePath = us2fs(fullPath); + return OpenItemAsArchive(NULL, tfi, fullPath, arcFormat, encrypted); } HRESULT CPanel::OpenItemAsArchive(int index) @@ -180,21 +299,21 @@ HRESULT CPanel::OpenParentArchiveFolder() CDisableTimerProcessing disableTimerProcessing1(*this); if (_parentFolders.Size() < 2) return S_OK; + const CFolderLink &folderLinkPrev = _parentFolders[_parentFolders.Size() - 2]; const CFolderLink &folderLink = _parentFolders.Back(); - NFind::CFileInfoW newFileInfo; + NFind::CFileInfo newFileInfo; if (newFileInfo.Find(folderLink.FilePath)) { if (folderLink.WasChanged(newFileInfo)) { - UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, - 0x03020280, folderLink.ItemName); + UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, 0x03020280, folderLink.RelPath); if (::MessageBoxW(HWND(*this), message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) { - if (OnOpenItemChanged(folderLink.FolderPath, folderLink.ItemName, - folderLink.UsePassword, folderLink.Password) != S_OK) + if (OnOpenItemChanged(folderLink.FileIndex, folderLink.FilePath, + folderLinkPrev.UsePassword, folderLinkPrev.Password) != S_OK) { ::MessageBoxW(HWND(*this), MyFormatNew(IDS_CANNOT_UPDATE_FILE, - 0x03020281, folderLink.FilePath), L"7-Zip", MB_OK | MB_ICONSTOP); + 0x03020281, fs2us(folderLink.FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); return S_OK; } } @@ -263,9 +382,11 @@ static HRESULT StartEditApplication(const UString &path, HWND window, CProcess & #ifdef UNDER_CE command = L"\\Windows\\"; #else - if (!MyGetWindowsDirectory(command)) + FString winDir; + if (!MyGetWindowsDirectory(winDir)) return 0; - NFile::NName::NormalizeDirPathPrefix(command); + NFile::NName::NormalizeDirPathPrefix(winDir); + command = fs2us(winDir); #endif command += L"notepad.exe"; } @@ -466,8 +587,8 @@ class CThreadCopyFrom: public CProgressThreadVirt { HRESULT ProcessVirt(); public: - UString PathPrefix; - UString Name; + UString FullPath; + UInt32 ItemIndex; CMyComPtr<IFolderOperations> FolderOperations; CMyComPtr<IProgress> UpdateCallback; @@ -476,14 +597,10 @@ public: HRESULT CThreadCopyFrom::ProcessVirt() { - UStringVector fileNames; - CRecordVector<const wchar_t *> fileNamePointers; - fileNames.Add(Name); - fileNamePointers.Add(fileNames[0]); - return FolderOperations->CopyFrom(PathPrefix, &fileNamePointers.Front(), fileNamePointers.Size(), UpdateCallback); + return FolderOperations->CopyFromFile(ItemIndex, FullPath, UpdateCallback); } -HRESULT CPanel::OnOpenItemChanged(const UString &folderPath, const UString &itemName, +HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password) { CMyComPtr<IFolderOperations> folderOperations; @@ -497,41 +614,48 @@ HRESULT CPanel::OnOpenItemChanged(const UString &folderPath, const UString &item t.UpdateCallbackSpec = new CUpdateCallback100Imp; t.UpdateCallback = t.UpdateCallbackSpec; t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog; - t.Name = itemName; - t.PathPrefix = folderPath; - NName::NormalizeDirPathPrefix(t.PathPrefix); + t.ItemIndex = index; + t.FullPath = fullFilePath; t.FolderOperations = folderOperations; t.UpdateCallbackSpec->Init(usePassword, password); - RINOK(t.Create(itemName, (HWND)*this)); + RINOK(t.Create(GetItemName(index), (HWND)*this)); return t.Result; } LRESULT CPanel::OnOpenItemChanged(LPARAM lParam) { - CTmpProcessInfo &tmpProcessInfo = *(CTmpProcessInfo *)lParam; - // LoadCurrentPath() - if (tmpProcessInfo.FullPathFolderPrefix != _currentFolderPrefix) + CTmpProcessInfo &tpi = *(CTmpProcessInfo *)lParam; + if (tpi.FullPathFolderPrefix != _currentFolderPrefix) return 0; + UInt32 fileIndex = tpi.FileIndex; + UInt32 numItems; + _folder->GetNumberOfItems(&numItems); + + // This code is not 100% OK for cases when there are several files with + // tpi.RelPath name and there are changes in archive before update. + // So tpi.FileIndex can point to another file. + + if (fileIndex >= numItems || GetItemRelPath(fileIndex) != tpi.RelPath) + { + UInt32 i; + for (i = 0; i < numItems; i++) + if (GetItemRelPath(i) == tpi.RelPath) + break; + if (i == numItems) + return 0; + fileIndex = i; + } CSelectedState state; SaveSelectedState(state); - HRESULT result = OnOpenItemChanged(tmpProcessInfo.FolderPath, tmpProcessInfo.ItemName, - tmpProcessInfo.UsePassword, tmpProcessInfo.Password); + HRESULT result = OnOpenItemChanged(fileIndex, tpi.FilePath, tpi.UsePassword, tpi.Password); if (result != S_OK) return 0; RefreshListCtrl(state); return 1; } -/* -class CTmpProcessInfoList -{ -public: - CObjectVector<CTmpProcessInfo> _items; -} g_TmpProcessInfoList; -*/ - class CExitEventLauncher { public: @@ -547,42 +671,64 @@ public: static THREAD_FUNC_DECL MyThreadFunction(void *param) { CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param); - const CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); + CTmpProcessInfo *tpi = tmpProcessInfoPtr.get(); + CChildProcesses &processes = tpi->Processes; - HANDLE hProcess = tmpProcessInfo->ProcessHandle; - HANDLE events[2] = { g_ExitEventLauncher._exitEvent, hProcess}; - DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); - ::CloseHandle(hProcess); - if (waitResult == WAIT_OBJECT_0 + 0) - return 0; - if (waitResult != WAIT_OBJECT_0 + 1) - return 1; - Sleep(200); - NFind::CFileInfoW newFileInfo; - if (newFileInfo.Find(tmpProcessInfo->FilePath)) + for (;;) + { + CRecordVector<HANDLE> handles; + CRecordVector<int> indices; + for (int i = 0; i < processes.Handles.Size(); i++) + { + if (processes.NeedWait[i]) + { + handles.Add(processes.Handles[i]); + indices.Add(i); + } + } + if (handles.IsEmpty()) + break; + + handles.Add(g_ExitEventLauncher._exitEvent); + + DWORD waitResult = ::WaitForMultipleObjects(handles.Size(), &handles.Front(), FALSE, INFINITE); + + if (waitResult >= (DWORD)handles.Size() - 1) + { + processes.CloseAll(); + return waitResult >= (DWORD)handles.Size() ? 1 : 0; + } + processes.Update(); + processes.DisableWait(indices[waitResult]); + } + + NFind::CFileInfo newFileInfo; + if (newFileInfo.Find(tpi->FilePath)) { - if (tmpProcessInfo->WasChanged(newFileInfo)) + if (tpi->WasChanged(newFileInfo)) { UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, - 0x03020280, tmpProcessInfo->ItemName); + 0x03020280, tpi->RelPath); if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) { - if (SendMessage(tmpProcessInfo->Window, kOpenItemChanged, 0, (LONG_PTR)tmpProcessInfo) != 1) + if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1) { ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE, - 0x03020281, tmpProcessInfo->FilePath), L"7-Zip", MB_OK | MB_ICONSTOP); + 0x03020281, fs2us(tpi->FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); return 0; } } } } - tmpProcessInfo->DeleteDirAndFile(); + tpi->DeleteDirAndFile(); return 0; } void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode) { const UString name = GetItemName(index); + const UString relPath = GetItemRelPath(index); + if (IsNameVirus(name)) { MessageBoxErrorLang(IDS_VIRUS, 0x03020284); @@ -598,18 +744,22 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name)); - UString fullVirtPath = _currentFolderPrefix + name; + UString fullVirtPath = _currentFolderPrefix + relPath; - NFile::NDirectory::CTempDirectoryW tempDirectory; - tempDirectory.Create(kTempDirPrefix); - UString tempDir = tempDirectory.GetPath(); - UString tempDirNorm = tempDir; + NFile::NDirectory::CTempDir tempDirectory; + if (!tempDirectory.Create(kTempDirPrefix)) + { + MessageBoxLastError(); + return; + } + FString tempDir = tempDirectory.GetPath(); + FString tempDirNorm = tempDir; NFile::NName::NormalizeDirPathPrefix(tempDirNorm); - - UString tempFilePath = tempDirNorm + GetCorrectFsPath(name); + FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name)); CTempFileInfo tempFileInfo; - tempFileInfo.ItemName = name; + tempFileInfo.FileIndex = index; + tempFileInfo.RelPath = relPath; tempFileInfo.FolderPath = tempDir; tempFileInfo.FilePath = tempFilePath; tempFileInfo.NeedDelete = true; @@ -655,7 +805,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo password = fl.Password; } - HRESULT result = CopyTo(indices, tempDirNorm, false, true, &messages, usePassword, password); + HRESULT result = CopyTo(indices, fs2us(tempDirNorm), false, true, &messages, usePassword, password); if (_parentFolders.Size() > 0) { @@ -686,17 +836,17 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo } CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo()); - CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); - tmpProcessInfo->FolderPath = tempDir; - tmpProcessInfo->FilePath = tempFilePath; - tmpProcessInfo->NeedDelete = true; - tmpProcessInfo->UsePassword = usePassword; - tmpProcessInfo->Password = password; - - if (!tmpProcessInfo->FileInfo.Find(tempFilePath)) + CTmpProcessInfo *tpi = tmpProcessInfoPtr.get(); + tpi->FolderPath = tempDir; + tpi->FilePath = tempFilePath; + tpi->NeedDelete = true; + tpi->UsePassword = usePassword; + tpi->Password = password; + + if (!tpi->FileInfo.Find(tempFilePath)) return; - CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo); + CTmpProcessInfoRelease tmpProcessInfoRelease(*tpi); if (!tryExternal) return; @@ -704,20 +854,21 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo CProcess process; HRESULT res; if (editMode) - res = StartEditApplication(tempFilePath, (HWND)*this, process); + res = StartEditApplication(fs2us(tempFilePath), (HWND)*this, process); else - res = StartApplication(tempDirNorm, tempFilePath, (HWND)*this, process); + res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); if ((HANDLE)process == 0) return; - tmpProcessInfo->Window = (HWND)(*this); - tmpProcessInfo->FullPathFolderPrefix = _currentFolderPrefix; - tmpProcessInfo->ItemName = name; - tmpProcessInfo->ProcessHandle = process.Detach(); + tpi->Window = (HWND)(*this); + tpi->FullPathFolderPrefix = _currentFolderPrefix; + tpi->FileIndex = index; + tpi->RelPath = relPath; + tpi->Processes.AddProcess(process.Detach()); NWindows::CThread thread; - if (thread.Create(MyThreadFunction, tmpProcessInfo) != S_OK) + if (thread.Create(MyThreadFunction, tpi) != S_OK) throw 271824; tempDirectory.DisableDeleting(); tmpProcessInfoPtr.release(); @@ -744,7 +895,7 @@ void DeleteOldTempFiles() UString searchWildCard = tempPath + kTempDirPrefix + L"*.tmp"; searchWildCard += WCHAR(NName::kAnyStringWildcard); NFind::CEnumeratorW enumerator(searchWildCard); - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; while(enumerator.Next(fileInfo)) { if (!fileInfo.IsDir()) diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 17cc3fcb..daa150c6 100755 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -416,7 +416,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (_currentFolderPrefix.IsEmpty()) { int iconIndexTemp; - GetRealIconIndex(itemName + WCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); + GetRealIconIndex(us2fs(itemName) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp); item.iImage = iconIndexTemp; } else @@ -450,6 +450,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool /* _listView.UpdateWindow(); */ + Refresh_StatusBar(); return S_OK; } @@ -458,7 +459,7 @@ void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const indices.Clear(); /* int itemIndex = -1; - while ((itemIndex = _listView.GetNextItem(itemIndex, LVNI_SELECTED)) != -1) + while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1) { LPARAM param; if (_listView.GetItemParam(itemIndex, param)) @@ -481,7 +482,7 @@ void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const int focusedItem = _listView.GetFocusedItem(); if (focusedItem >= 0) { - if (_listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) + if (_listView.IsItemSelected(focusedItem)) { int realIndex = GetRealItemIndex(focusedItem); if (realIndex != kParentIndex) @@ -565,8 +566,7 @@ void CPanel::OpenSelectedItems(bool tryInternal) if (focusedItem >= 0) { int realIndex = GetRealItemIndex(focusedItem); - if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && - _listView.GetItemState(focusedItem, LVIS_SELECTED) == LVIS_SELECTED) + if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && _listView.IsItemSelected(focusedItem)) indices.Insert(0, realIndex); } @@ -787,7 +787,6 @@ void CPanel::OnReload() HRESULT res = RefreshListCtrlSaveFocused(); if (res != S_OK) MessageBoxError(res); - OnRefreshStatusBar(); } void CPanel::OnTimer() diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 2051b5c6..f28311a4 100755 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -77,7 +77,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (_dontShowMode) return 0; - UINT32 realIndex = GetRealIndex(item); + UInt32 realIndex = GetRealIndex(item); /* if ((item.mask & LVIF_IMAGE) != 0) { @@ -113,7 +113,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (realIndex == kParentIndex) return 0; UString s; - UINT32 subItemIndex = item.iSubItem; + UInt32 subItemIndex = item.iSubItem; PROPID propID = _visibleProperties[subItemIndex].ID; /* { @@ -222,7 +222,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) { if (!_mySelectMode) OnItemChanged((LPNMLISTVIEW)header); - RefreshStatusBar(); + Post_Refresh_StatusBar(); } return false; } @@ -248,7 +248,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) case LVN_KEYDOWN: { bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header), result); - RefreshStatusBar(); + Post_Refresh_StatusBar(); return boolResult; } @@ -273,7 +273,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) break; case NM_RCLICK: - RefreshStatusBar(); + Post_Refresh_StatusBar(); break; /* @@ -301,7 +301,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) { // we need SetFocusToList, if we drag-select items from other panel. SetFocusToList(); - RefreshStatusBar(); + Post_Refresh_StatusBar(); if (_mySelectMode) #ifndef UNDER_CE if (g_ComCtl32Version >= MAKELONG(71, 4)) @@ -325,7 +325,7 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result) case LVN_BEGINDRAG: { OnDrag((LPNMLISTVIEW)header); - RefreshStatusBar(); + Post_Refresh_StatusBar(); break; } // case LVN_BEGINRDRAG: @@ -390,9 +390,9 @@ bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result) return false; } -void CPanel::OnRefreshStatusBar() +void CPanel::Refresh_StatusBar() { - CRecordVector<UINT32> indices; + CRecordVector<UInt32> indices; GetOperatedItemIndices(indices); _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, 0x02000301, NumberToString(indices.Size()))); diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 549b28da..badf531b 100755 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -564,6 +564,7 @@ bool CPanel::InvokePluginCommand(int id, CMINVOKECOMMANDINFOEX #endif commandInfo; + memset(&commandInfo, 0, sizeof(commandInfo)); commandInfo.cbSize = sizeof(commandInfo); commandInfo.fMask = 0 #ifndef UNDER_CE @@ -576,8 +577,8 @@ bool CPanel::InvokePluginCommand(int id, CSysString currentFolderSys = GetSystemString(_currentFolderPrefix); commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys); commandInfo.nShow = SW_SHOW; - commandInfo.lpParameters = NULL; #ifndef UNDER_CE + commandInfo.lpParametersW = NULL; commandInfo.lpTitle = ""; commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset)); UString currentFolderUnicode = _currentFolderPrefix; diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 0c6d3122..9c109d0d 100755 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -284,6 +284,24 @@ BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) return FALSE; } +static UString GetLastPart(const UString name) +{ + int slashPos = name.ReverseFind(L'/'); + #ifdef _WIN32 + int slash1Pos = name.ReverseFind(L'\\'); + slashPos = MyMax(slashPos, slash1Pos); + #endif + return name.Mid(slashPos + 1); +} + +bool IsCorrectFsName(const UString name) +{ + const UString lastPart = GetLastPart(name); + return + lastPart != L"." && + lastPart != L".."; +} + BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) { if (lpnmh->item.pszText == NULL) @@ -295,6 +313,11 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) return FALSE; } const UString newName = lpnmh->item.pszText; + if (!IsCorrectFsName(newName)) + { + MessageBoxError(E_INVALIDARG); + return FALSE; + } CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); SaveSelectedState(_selectedState); @@ -353,6 +376,11 @@ void CPanel::CreateFolder() return; UString newName = comboDialog.Value; + if (!IsCorrectFsName(newName)) + { + MessageBoxError(E_INVALIDARG); + return; + } { CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER); diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index 29cf576b..b31c2e9d 100755 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -78,7 +78,7 @@ void CPanel::OnInsert() UINT state = (_listView.GetItemState(focusedItem, LVIS_CUT) == 0) ? LVIS_CUT : 0; _listView.SetItemState(focusedItem, state, LVIS_CUT); - // _listView.SetItemState(focusedItem, LVIS_SELECTED, LVIS_SELECTED); + // _listView.SetItemState_Selected(focusedItem); */ int focusedItem = _listView.GetFocusedItem(); @@ -90,7 +90,7 @@ void CPanel::OnInsert() _selectedStatusVector[realIndex] = isSelected; if (!_mySelectMode) - _listView.SetItemState(focusedItem, isSelected ? LVIS_SELECTED: 0, LVIS_SELECTED); + _listView.SetItemState_Selected(focusedItem, isSelected); _listView.RedrawItem(focusedItem); @@ -135,11 +135,7 @@ void CPanel::UpdateSelection() { int realIndex = GetRealItemIndex(i); if (realIndex != kParentIndex) - { - UINT value = 0; - value = _selectedStatusVector[realIndex] ? LVIS_SELECTED: 0; - _listView.SetItemState(i, value, LVIS_SELECTED); - } + _listView.SetItemState_Selected(i, _selectedStatusVector[realIndex]); } _enableItemChangeNotify = enableTemp; } @@ -174,7 +170,7 @@ void CPanel::SelectByType(bool selectMode) bool isItemFolder = IsItemFolder(realIndex); /* - UINT32 numItems; + UInt32 numItems; _folder->GetNumberOfItems(&numItems); if ((UInt32)_selectedStatusVector.Size() != numItems) throw 11111; @@ -251,7 +247,7 @@ void CPanel::KillSelection() int realIndex = GetRealItemIndex(focused); if (realIndex != kParentIndex) _selectedStatusVector[realIndex] = true; - _listView.SetItemState(focused, LVIS_SELECTED, LVIS_SELECTED); + _listView.SetItemState_Selected(focused); } } } diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index 186315b3..5ac04800 100755 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -63,8 +63,8 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) NCOM::CPropVariant prop1, prop2; // Name must be first property - panel->_folder->GetProperty((UINT32)lParam1, propID, &prop1); - panel->_folder->GetProperty((UINT32)lParam2, propID, &prop2); + panel->_folder->GetProperty((UInt32)lParam1, propID, &prop1); + panel->_folder->GetProperty((UInt32)lParam2, propID, &prop2); if (prop1.vt != prop2.vt) { return MyCompare(prop1.vt, prop2.vt); diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index 213c2d48..ba0bedf8 100755 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -7,6 +7,7 @@ #include "Windows/Error.h" #include "Windows/FileIO.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "../GUI/ExtractRes.h" @@ -89,8 +90,8 @@ class CThreadSplit: public CProgressThreadVirt { HRESULT ProcessVirt(); public: - UString FilePath; - UString VolBasePath; + FString FilePath; + FString VolBasePath; UInt64 NumVolumes; CRecordVector<UInt64> VolumeSizes; }; @@ -136,15 +137,15 @@ HRESULT CThreadSplit::ProcessVirt() needSize = processedSize; if (curVolSize == 0) { - UString name = VolBasePath; - name += L'.'; - name += seqName.GetNextName(); - sync.SetCurrentFileName(name); + FString name = VolBasePath; + name += FTEXT('.'); + name += us2fs(seqName.GetNextName()); + sync.SetCurrentFileName(fs2us(name)); sync.SetNumFilesCur(numFiles++); if (!outFile.Create(name, false)) { HRESULT res = GetLastError(); - ErrorPath1 = name; + SetErrorPath1(name); return res; } } @@ -206,8 +207,8 @@ void CApp::Split() if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL) return; - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(srcPath + itemName)) + NFile::NFind::CFileInfo fileInfo; + if (!fileInfo.Find(us2fs(srcPath + itemName))) { srcPanel.MessageBoxMyError(L"Can not find file"); return; @@ -230,7 +231,7 @@ void CApp::Split() path = splitDialog.Path; NFile::NName::NormalizeDirPathPrefix(path); - if (!NFile::NDirectory::CreateComplexDirectory(path)) + if (!NFile::NDirectory::CreateComplexDirectory(us2fs(path))) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); return; @@ -253,8 +254,8 @@ void CApp::Split() progressDialog.Sync.SetTitleFileName(itemName); - spliter.FilePath = srcPath + itemName; - spliter.VolBasePath = path + itemName; + spliter.FilePath = us2fs(srcPath + itemName); + spliter.VolBasePath = us2fs(path + itemName); spliter.VolumeSizes = splitDialog.VolumeSizes; // if (splitDialog.VolumeSizes.Size() == 0) return; @@ -279,9 +280,9 @@ class CThreadCombine: public CProgressThreadVirt { HRESULT ProcessVirt(); public: - UString InputDirPrefix; - UStringVector Names; - UString OutputPath; + FString InputDirPrefix; + FStringVector Names; + FString OutputPath; UInt64 TotalSize; }; @@ -291,7 +292,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!outFile.Create(OutputPath, false)) { HRESULT res = GetLastError(); - ErrorPath1 = OutputPath; + SetErrorPath1(OutputPath); return res; } @@ -306,21 +307,21 @@ HRESULT CThreadCombine::ProcessVirt() for (int i = 0; i < Names.Size(); i++) { NFile::NIO::CInFile inFile; - const UString nextName = InputDirPrefix + Names[i]; + const FString nextName = InputDirPrefix + Names[i]; if (!inFile.Open(nextName)) { HRESULT res = GetLastError(); - ErrorPath1 = nextName; + SetErrorPath1(nextName); return res; } - sync.SetCurrentFileName(nextName); + sync.SetCurrentFileName(fs2us(nextName)); for (;;) { UInt32 processedSize; if (!inFile.Read(buffer, kBufSize, processedSize)) { HRESULT res = GetLastError(); - ErrorPath1 = nextName; + SetErrorPath1(nextName); return res; } if (processedSize == 0) @@ -329,7 +330,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!outFile.Write(buffer, needSize, processedSize)) { HRESULT res = GetLastError(); - ErrorPath1 = OutputPath; + SetErrorPath1(OutputPath); return res; } if (needSize != processedSize) @@ -392,10 +393,10 @@ void CApp::Combine() combiner.TotalSize = 0; for (;;) { - NFile::NFind::CFileInfoW fileInfo; - if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir()) + NFile::NFind::CFileInfo fileInfo; + if (!fileInfo.Find(us2fs(srcPath + nextName)) || fileInfo.IsDir()) break; - combiner.Names.Add(nextName); + combiner.Names.Add(us2fs(nextName)); combiner.TotalSize += fileInfo.Size; nextName = volSeqName.GetNextName(); } @@ -419,12 +420,12 @@ void CApp::Combine() int i; for (i = 0; i < combiner.Names.Size() && i < 2; i++) - AddInfoFileName(combiner.Names[i], info); + AddInfoFileName(fs2us(combiner.Names[i]), info); if (i != combiner.Names.Size()) { if (i + 1 != combiner.Names.Size()) AddInfoFileName(L"...", info); - AddInfoFileName(combiner.Names.Back(), info); + AddInfoFileName(fs2us(combiner.Names.Back()), info); } { @@ -441,7 +442,7 @@ void CApp::Combine() } NFile::NName::NormalizeDirPathPrefix(path); - if (!NFile::NDirectory::CreateComplexDirectory(path)) + if (!NFile::NDirectory::CreateComplexDirectory(us2fs(path))) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); return; @@ -450,18 +451,17 @@ void CApp::Combine() UString outName = volSeqName.UnchangedPart; while (!outName.IsEmpty()) { - int lastIndex = outName.Length() - 1; - if (outName[lastIndex] != L'.') + if (outName.Back() != L'.') break; - outName.Delete(lastIndex); + outName.DeleteBack(); } if (outName.IsEmpty()) outName = L"file"; - NFile::NFind::CFileInfoW fileInfo; + NFile::NFind::CFileInfo fileInfo; UString destFilePath = path + outName; - combiner.OutputPath = destFilePath; - if (fileInfo.Find(destFilePath)) + combiner.OutputPath = us2fs(destFilePath); + if (fileInfo.Find(combiner.OutputPath)) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath)); return; @@ -477,7 +477,7 @@ void CApp::Combine() progressDialog.MainTitle = progressWindowTitle; progressDialog.MainAddTitle = title + UString(L" "); - combiner.InputDirPrefix = srcPath; + combiner.InputDirPrefix = us2fs(srcPath); // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp index eaf90a24..92826a1f 100755 --- a/CPP/7zip/UI/FileManager/PasswordDialog.cpp +++ b/CPP/7zip/UI/FileManager/PasswordDialog.cpp @@ -18,6 +18,17 @@ static CIDLangPair kIDLangPairs[] = }; #endif +void CPasswordDialog::ReadControls() +{ + _passwordControl.GetText(Password); + ShowPassword = IsButtonCheckedBool(IDC_CHECK_PASSWORD_SHOW); +} + +void CPasswordDialog::SetTextSpec() +{ + _passwordControl.SetPasswordChar(ShowPassword ? 0: TEXT('*')); + _passwordControl.SetText(Password); +} bool CPasswordDialog::OnInit() { @@ -26,8 +37,8 @@ bool CPasswordDialog::OnInit() LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); #endif _passwordControl.Attach(GetItem(IDC_EDIT_PASSWORD)); - _passwordControl.SetText(Password); - _passwordControl.SetPasswordChar(TEXT('*')); + CheckButton(IDC_CHECK_PASSWORD_SHOW, ShowPassword); + SetTextSpec(); return CModalDialog::OnInit(); } @@ -35,10 +46,8 @@ bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { if (buttonID == IDC_CHECK_PASSWORD_SHOW) { - _passwordControl.SetPasswordChar(IsButtonCheckedBool(IDC_CHECK_PASSWORD_SHOW) ? 0: TEXT('*')); - UString password; - _passwordControl.GetText(password); - _passwordControl.SetText(password); + ReadControls(); + SetTextSpec(); return true; } return CDialog::OnButtonClicked(buttonID, buttonHWND); @@ -46,6 +55,6 @@ bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND) void CPasswordDialog::OnOK() { - _passwordControl.GetText(Password); + ReadControls(); CModalDialog::OnOK(); } diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h index e5a96073..1d903249 100755 --- a/CPP/7zip/UI/FileManager/PasswordDialog.h +++ b/CPP/7zip/UI/FileManager/PasswordDialog.h @@ -1,7 +1,7 @@ // PasswordDialog.h -#ifndef __PASSWORDDIALOG_H -#define __PASSWORDDIALOG_H +#ifndef __PASSWORD_DIALOG_H +#define __PASSWORD_DIALOG_H #include "Windows/Control/Dialog.h" #include "Windows/Control/Edit.h" @@ -13,8 +13,12 @@ class CPasswordDialog: public NWindows::NControl::CModalDialog virtual void OnOK(); virtual bool OnInit(); virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + void SetTextSpec(); + void ReadControls(); public: UString Password; + bool ShowPassword; + CPasswordDialog(): ShowPassword(false) {} INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_DIALOG_PASSWORD, parentWindow); } }; diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h index 3cf15aa5..cb7d4d7c 100755 --- a/CPP/7zip/UI/FileManager/PluginLoader.h +++ b/CPP/7zip/UI/FileManager/PluginLoader.h @@ -5,6 +5,8 @@ #include "Windows/DLL.h" +#include "IFolder.h" + typedef UINT32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); class CPluginLibrary: public NWindows::NDLL::CLibrary @@ -17,7 +19,7 @@ public: return GetLastError(); return createObject(&clsID, &IID_IFolderManager, (void **)manager); } - HRESULT LoadAndCreateManager(LPCWSTR filePath, REFGUID clsID, IFolderManager **manager) + HRESULT LoadAndCreateManager(CFSTR filePath, REFGUID clsID, IFolderManager **manager) { if (!Load(filePath)) return GetLastError(); diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp index ce2d178e..50ca5ca5 100755 --- a/CPP/7zip/UI/FileManager/ProgramLocation.cpp +++ b/CPP/7zip/UI/FileManager/ProgramLocation.cpp @@ -1,24 +1,3 @@ // ProgramLocation.cpp #include "StdAfx.h" - -#include "../../../../C/Types.h" - -#include "ProgramLocation.h" - -#include "Windows/DLL.h" - -using namespace NWindows; - -extern HINSTANCE g_hInstance; - -bool GetProgramFolderPath(UString &folder) -{ - if (!NDLL::MyGetModuleFileName(g_hInstance, folder)) - return false; - int pos = folder.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos < 0) - return false; - folder = folder.Left(pos + 1); - return true; -} diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h index 55c56144..6bfb711e 100755 --- a/CPP/7zip/UI/FileManager/ProgramLocation.h +++ b/CPP/7zip/UI/FileManager/ProgramLocation.h @@ -3,8 +3,4 @@ #ifndef __PROGRAM_LOCATION_H #define __PROGRAM_LOCATION_H -#include "Common/MyString.h" - -bool GetProgramFolderPath(UString &folder); // normalized - #endif diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index 3d878a61..bd77d20d 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -146,6 +146,7 @@ bool CProgressDialog::OnInit() m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); _messageList.Attach(GetItem(IDC_PROGRESS_LIST)); + _messageList.SetUnicodeFormat(); _wasCreated = true; _dialogCreatedEvent.Set(); @@ -154,7 +155,6 @@ bool CProgressDialog::OnInit() LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); #endif - CWindow window(GetItem(IDC_BUTTON_PROGRESS_PRIORITY)); window.GetText(backgroundString); backgroundedString = backgroundString; @@ -171,11 +171,6 @@ bool CProgressDialog::OnInit() SetPauseText(); SetPriorityText(); - - #ifndef UNDER_CE - _messageList.SetUnicodeFormat(true); - #endif - _messageList.InsertColumn(0, L"", 30); const UString s = LangStringSpec(IDS_MESSAGES_DIALOG_MESSAGE_COLUMN, 0x02000A80); @@ -957,10 +952,8 @@ UString HResultToMessage(HRESULT errorCode) UString message; if (errorCode == E_OUTOFMEMORY) message = LangStringSpec(IDS_MEM_ERROR, 0x0200060B); - else if (!NError::MyFormatMessage(errorCode, message)) - message.Empty(); - if (message.IsEmpty()) - message = L"Error"; + else + message = NError::MyFormatMessageW(errorCode); return message; } @@ -989,8 +982,8 @@ void CProgressThreadVirt::Process() m = HResultToMessage(Result); } AddMessageToString(m, ErrorMessage); - AddMessageToString(m, ErrorPath1); - AddMessageToString(m, ErrorPath2); + AddMessageToString(m, fs2us(ErrorPath1)); + AddMessageToString(m, fs2us(ErrorPath2)); if (m.IsEmpty()) { diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index ed096f06..81a64e32 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -323,10 +323,10 @@ public: class CProgressThreadVirt { + FString ErrorPath1; + FString ErrorPath2; protected: UString ErrorMessage; - UString ErrorPath1; - UString ErrorPath2; UString OkMessage; UString OkMessageTitle; @@ -350,6 +350,9 @@ public: return 0; } + void SetErrorPath1(const FString &path) { ErrorPath1 = path; } + void SetErrorPath2(const FString &path) { ErrorPath2 = path; } + HRESULT Create(const UString &title, HWND parentWindow = 0); CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} }; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h index 21ac03c2..be5af607 100755 --- a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h @@ -35,7 +35,11 @@ #define IDC_PROGRESS_ERRORS_VALUE 1031 #define IDC_PROGRESS_LIST 1032 +#ifdef UNDER_CE #define MY_PROGRESS_VALUE_UNITS 44 +#else +#define MY_PROGRESS_VALUE_UNITS 76 +#endif #define MY_PROGRESS_LABEL_UNITS_MIN 60 #define MY_PROGRESS_LABEL_UNITS_START 90 #define MY_PROGRESS_PAD_UNITS 4 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp index f7edbb4b..487b6060 100755 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -2,234 +2,151 @@ #include "StdAfx.h" -#include "RegistryAssociations.h" - #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/Registry.h" -#include "Windows/Synchronization.h" -#include "StringUtils.h" +#include "RegistryAssociations.h" using namespace NWindows; using namespace NRegistry; -namespace NRegistryAssociations { +namespace NRegistryAssoc { -static NSynchronization::CCriticalSection g_CriticalSection; - -#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM") - -/* - -static const TCHAR *kCUKeyPath = REG_PATH_FM; -static const WCHAR *kExtPlugins = L"Plugins"; -static const TCHAR *kExtEnabled = TEXT("Enabled"); - -#define kAssociations TEXT("Associations") -#define kAssociationsPath REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) kAssociations - -bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo) -{ - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CKey key; - if (key.Open(HKEY_CURRENT_USER, - CSysString(kAssociationsPath TEXT(STRING_PATH_SEPARATOR)) + - GetSystemString(ext), KEY_READ) != ERROR_SUCCESS) - return false; - UString pluginsString; - key.QueryValue(kExtPlugins, pluginsString); - SplitString(pluginsString, extInfo.Plugins); - return true; -} - -void ReadInternalAssociations(CObjectVector<CExtInfo> &items) -{ - items.Clear(); - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CKey associationsKey; - if (associationsKey.Open(HKEY_CURRENT_USER, kAssociationsPath, KEY_READ) != ERROR_SUCCESS) - return; - CSysStringVector extNames; - associationsKey.EnumKeys(extNames); - for(int i = 0; i < extNames.Size(); i++) - { - const CSysString extName = extNames[i]; - CExtInfo extInfo; - // extInfo.Enabled = false; - extInfo.Ext = GetUnicodeString(extName); - CKey key; - if (key.Open(associationsKey, extName, KEY_READ) != ERROR_SUCCESS) - return; - UString pluginsString; - key.QueryValue(kExtPlugins, pluginsString); - SplitString(pluginsString, extInfo.Plugins); - // if (key.QueryValue(kExtEnabled, extInfo.Enabled) != ERROR_SUCCESS) - // extInfo.Enabled = false; - items.Add(extInfo); - } -} - -void WriteInternalAssociations(const CObjectVector<CExtInfo> &items) -{ - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CKey mainKey; - mainKey.Create(HKEY_CURRENT_USER, kCUKeyPath); - mainKey.RecurseDeleteKey(kAssociations); - CKey associationsKey; - associationsKey.Create(mainKey, kAssociations); - for(int i = 0; i < items.Size(); i++) - { - const CExtInfo &extInfo = items[i]; - CKey key; - key.Create(associationsKey, GetSystemString(extInfo.Ext)); - key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins)); - // key.SetValue(kExtEnabled, extInfo.Enabled); - } -} -*/ - -/////////////////////////////////// -// External +// static NSynchronization::CCriticalSection g_CriticalSection; -static const TCHAR *kShellNewKeyName = TEXT("ShellNew"); -static const TCHAR *kShellNewDataValueName = TEXT("Data"); - +static const TCHAR *kClasses = TEXT("Software\\Classes\\"); +// static const TCHAR *kShellNewKeyName = TEXT("ShellNew"); +// static const TCHAR *kShellNewDataValueName = TEXT("Data"); static const TCHAR *kDefaultIconKeyName = TEXT("DefaultIcon"); static const TCHAR *kShellKeyName = TEXT("shell"); static const TCHAR *kOpenKeyName = TEXT("open"); static const TCHAR *kCommandKeyName = TEXT("command"); static const TCHAR *k7zipPrefix = TEXT("7-Zip."); -static CSysString GetExtensionKeyName(const CSysString &extension) +static CSysString GetExtProgramKeyName(const CSysString &ext) { - return CSysString(TEXT(".")) + extension; + return CSysString(k7zipPrefix) + ext; } -static CSysString GetExtProgramKeyName(const CSysString &extension) +static CSysString GetFullKeyPath(HKEY hkey, const CSysString &name) { - return CSysString(k7zipPrefix) + extension; + CSysString s; + if (hkey != HKEY_CLASSES_ROOT) + s = kClasses; + return s + name; } -static bool CheckShellExtensionInfo2(const CSysString &extension, - CSysString programKeyName, UString &iconPath, int &iconIndex) +static CSysString GetExtKeyPath(HKEY hkey, const CSysString &ext) { - iconIndex = -1; - iconPath.Empty(); - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CKey extKey; - if (extKey.Open(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension), KEY_READ) != ERROR_SUCCESS) - return false; - if (extKey.QueryValue(NULL, programKeyName) != ERROR_SUCCESS) - return false; - UString s = GetUnicodeString(k7zipPrefix); - if (s.CompareNoCase(GetUnicodeString(programKeyName.Left(s.Length()))) != 0) - return false; - CKey iconKey; - if (extKey.Open(HKEY_CLASSES_ROOT, programKeyName + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName, KEY_READ) != ERROR_SUCCESS) - return false; - UString value; - if (extKey.QueryValue(NULL, value) == ERROR_SUCCESS) + return GetFullKeyPath(hkey, (TEXT(".")) + ext); +} + +bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) +{ + ProgramKey.Empty(); + IconPath.Empty(); + IconIndex = -1; + // NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + { + CKey extKey; + if (extKey.Open(hkey, GetExtKeyPath(hkey, ext), KEY_READ) != ERROR_SUCCESS) + return false; + if (extKey.QueryValue(NULL, ProgramKey) != ERROR_SUCCESS) + return false; + } { - int pos = value.ReverseFind(L','); - iconPath = value; - if (pos >= 0) + CKey iconKey; + if (iconKey.Open(hkey, GetFullKeyPath(hkey, ProgramKey + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName), KEY_READ) == ERROR_SUCCESS) { - const wchar_t *end; - UInt64 index = ConvertStringToUInt64((const wchar_t *)value + pos + 1, &end); - if (*end == 0) + UString value; + if (iconKey.QueryValue(NULL, value) == ERROR_SUCCESS) { - iconIndex = (int)index; - iconPath = value.Left(pos); + int pos = value.ReverseFind(L','); + IconPath = value; + if (pos >= 0) + { + const wchar_t *end; + Int64 index = ConvertStringToInt64((const wchar_t *)value + pos + 1, &end); + if (*end == 0) + { + IconIndex = (int)index; + IconPath = value.Left(pos); + } + } } } } return true; } -bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex) -{ - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CSysString programKeyName; - if (!CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex)) - return false; - CKey extProgKey; - return (extProgKey.Open(HKEY_CLASSES_ROOT, programKeyName, KEY_READ) == ERROR_SUCCESS); -} - -static void DeleteShellExtensionKey(const CSysString &extension) +bool CShellExtInfo::IsIt7Zip() const { - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); - CKey rootKey; - rootKey.Attach(HKEY_CLASSES_ROOT); - rootKey.RecurseDeleteKey(GetExtensionKeyName(extension)); - rootKey.Detach(); + UString s = GetUnicodeString(k7zipPrefix); + return (s.CompareNoCase(GetUnicodeString(ProgramKey.Left(s.Length()))) == 0); } -static void DeleteShellExtensionProgramKey(const CSysString &extension) +LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext) { - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + // NSynchronization::CCriticalSectionLock lock(g_CriticalSection); CKey rootKey; - rootKey.Attach(HKEY_CLASSES_ROOT); - rootKey.RecurseDeleteKey(GetExtProgramKeyName(extension)); + rootKey.Attach(hkey); + LONG res = rootKey.RecurseDeleteKey(GetExtKeyPath(hkey, ext)); + // then we delete only 7-Zip.* key. + rootKey.RecurseDeleteKey(GetFullKeyPath(hkey, GetExtProgramKeyName(ext))); rootKey.Detach(); + return res; } -void DeleteShellExtensionInfo(const CSysString &extension) -{ - CSysString programKeyName; - UString iconPath; - int iconIndex; - if (CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex)) - DeleteShellExtensionKey(extension); - DeleteShellExtensionProgramKey(extension); -} - -void AddShellExtensionInfo(const CSysString &extension, +LONG AddShellExtensionInfo(HKEY hkey, + const CSysString &ext, const UString &programTitle, const UString &programOpenCommand, - const UString &iconPath, int iconIndex, - const void *shellNewData, int shellNewDataSize) + const UString &iconPath, int iconIndex + // , const void *shellNewData, int shellNewDataSize + ) { - DeleteShellExtensionKey(extension); - DeleteShellExtensionProgramKey(extension); - NSynchronization::CCriticalSectionLock lock(g_CriticalSection); + LONG res = 0; + DeleteShellExtensionInfo(hkey, ext); + // NSynchronization::CCriticalSectionLock lock(g_CriticalSection); CSysString programKeyName; { - CSysString ext = extension; + CSysString ext2 = ext; if (iconIndex < 0) - ext = TEXT("*"); - programKeyName = GetExtProgramKeyName(ext); + ext2 = TEXT("*"); + programKeyName = GetExtProgramKeyName(ext2); } { CKey extKey; - extKey.Create(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension)); + res = extKey.Create(hkey, GetExtKeyPath(hkey, ext)); extKey.SetValue(NULL, programKeyName); + /* if (shellNewData != NULL) { CKey shellNewKey; shellNewKey.Create(extKey, kShellNewKeyName); shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize); } + */ } CKey programKey; - programKey.Create(HKEY_CLASSES_ROOT, programKeyName); + programKey.Create(hkey, GetFullKeyPath(hkey, programKeyName)); programKey.SetValue(NULL, programTitle); { CKey iconKey; - iconKey.Create(programKey, kDefaultIconKeyName); UString iconPathFull = iconPath; if (iconIndex < 0) iconIndex = 0; // if (iconIndex >= 0) { - iconPathFull += L","; + iconPathFull += L','; wchar_t s[16]; - ConvertUInt32ToString(iconIndex, s); + ConvertInt64ToString(iconIndex, s); iconPathFull += s; } + iconKey.Create(programKey, kDefaultIconKeyName); iconKey.SetValue(NULL, iconPathFull); } @@ -243,70 +160,8 @@ void AddShellExtensionInfo(const CSysString &extension, CKey commandKey; commandKey.Create(openKey, kCommandKeyName); - commandKey.SetValue(NULL, programOpenCommand); + return res; } -/////////////////////////// -// ContextMenu -/* - -static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); -static const TCHAR *kContextMenuHandlerCLASSIDValue = - TEXT("{23170F69-40C1-278A-1000-000100020000}"); -static const TCHAR *kRootKeyNameForFile = TEXT("*"); -static const TCHAR *kRootKeyNameForFolder = TEXT("Folder"); - -static CSysString GetFullContextMenuKeyName(const CSysString &aKeyName) - { return (aKeyName + kContextMenuKeyName); } - -static bool CheckContextMenuHandlerCommon(const CSysString &aKeyName) -{ - NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true); - CKey aKey; - if (aKey.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName), KEY_READ) - != ERROR_SUCCESS) - return false; - CSysString aValue; - if (aKey.QueryValue(NULL, aValue) != ERROR_SUCCESS) - return false; - return (aValue.CompareNoCase(kContextMenuHandlerCLASSIDValue) == 0); -} - -bool CheckContextMenuHandler() -{ - return CheckContextMenuHandlerCommon(kRootKeyNameForFile) && - CheckContextMenuHandlerCommon(kRootKeyNameForFolder); -} - -static void DeleteContextMenuHandlerCommon(const CSysString &aKeyName) -{ - CKey rootKey; - rootKey.Attach(HKEY_CLASSES_ROOT); - rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(aKeyName)); - rootKey.Detach(); -} - -void DeleteContextMenuHandler() -{ - DeleteContextMenuHandlerCommon(kRootKeyNameForFile); - DeleteContextMenuHandlerCommon(kRootKeyNameForFolder); -} - -static void AddContextMenuHandlerCommon(const CSysString &aKeyName) -{ - DeleteContextMenuHandlerCommon(aKeyName); - NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true); - CKey aKey; - aKey.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName)); - aKey.SetValue(NULL, kContextMenuHandlerCLASSIDValue); -} - -void AddContextMenuHandler() -{ - AddContextMenuHandlerCommon(kRootKeyNameForFile); - AddContextMenuHandlerCommon(kRootKeyNameForFolder); -} -*/ - } diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.h b/CPP/7zip/UI/FileManager/RegistryAssociations.h index 5390b9db..0be8244e 100755 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.h +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.h @@ -1,46 +1,31 @@ // RegistryAssociations.h -#ifndef __REGISTRYASSOCIATIONS_H -#define __REGISTRYASSOCIATIONS_H +#ifndef __REGISTRY_ASSOCIATIONS_H +#define __REGISTRY_ASSOCIATIONS_H #include "Common/MyString.h" -namespace NRegistryAssociations { +namespace NRegistryAssoc { - /* - struct CExtInfo + struct CShellExtInfo { - UString Ext; - UStringVector Plugins; - // bool Enabled; - }; - bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo); - void ReadInternalAssociations(CObjectVector<CExtInfo> &items); - void WriteInternalAssociations(const CObjectVector<CExtInfo> &items); - */ + CSysString ProgramKey; + UString IconPath; + int IconIndex; - bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex); + bool ReadFromRegistry(HKEY hkey, const CSysString &ext); + bool IsIt7Zip() const; + }; - // void ReadCompressionInfo(NZipSettings::NCompression::CInfo &anInfo, - void DeleteShellExtensionInfo(const CSysString &extension); + LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext); - void AddShellExtensionInfo(const CSysString &extension, + LONG AddShellExtensionInfo(HKEY hkey, + const CSysString &ext, const UString &programTitle, const UString &programOpenCommand, - const UString &iconPath, int iconIndex, - const void *shellNewData, int shellNewDataSize); - - - /////////////////////////// - // ContextMenu - /* - bool CheckContextMenuHandler(); - void AddContextMenuHandler(); - void DeleteContextMenuHandler(); - */ - + const UString &iconPath, int iconIndex + // , const void *shellNewData, int shellNewDataSize + ); } -// bool GetProgramDirPrefix(CSysString &aFolder); - #endif diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp index d49eaa6e..54254f1f 100755 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp @@ -3,12 +3,11 @@ #include "StdAfx.h" #include "Windows/DLL.h" -#include "Windows/PropVariant.h" #include "Windows/FileFind.h" +#include "Windows/PropVariant.h" -#include "ProgramLocation.h" -#include "RegistryPlugins.h" #include "IFolder.h" +#include "RegistryPlugins.h" using namespace NWindows; using namespace NFile; @@ -91,23 +90,20 @@ static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll) return true; } -UString GetProgramFolderPrefix(); - void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins) { plugins.Clear(); - UString baseFolderPrefix; - GetProgramFolderPath(baseFolderPrefix); + FString baseFolderPrefix = NDLL::GetModuleDirPrefix(); { CPluginInfo pluginInfo; - pluginInfo.FilePath = baseFolderPrefix + L"7-zip.dll"; + pluginInfo.FilePath = baseFolderPrefix + FTEXT("7-zip.dll"); if (::ReadPluginInfo(pluginInfo, false)) plugins.Add(pluginInfo); } - UString folderPath = baseFolderPrefix + L"Plugins" WSTRING_PATH_SEPARATOR; - NFind::CEnumeratorW enumerator(folderPath + L"*"); - NFind::CFileInfoW fileInfo; + FString folderPath = baseFolderPrefix + FTEXT("Plugins") FSTRING_PATH_SEPARATOR; + NFind::CEnumerator enumerator(folderPath + FCHAR_ANY_MASK); + NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.h b/CPP/7zip/UI/FileManager/RegistryPlugins.h index 77055ac7..20f2ec34 100755 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.h +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.h @@ -1,7 +1,7 @@ // RegistryPlugins.h -#ifndef __REGISTRYPLUGINS_H -#define __REGISTRYPLUGINS_H +#ifndef __REGISTRY_PLUGINS_H +#define __REGISTRY_PLUGINS_H #include "Common/MyString.h" @@ -12,7 +12,7 @@ enum EPluginType struct CPluginInfo { - UString FilePath; + FString FilePath; EPluginType Type; UString Name; CLSID ClassID; diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 0715a8be..a81f94c1 100755 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -30,7 +30,7 @@ static const STATPROPSTG kProps[] = UString RootFolder_GetName_Computer(int &iconIndex) { #ifdef UNDER_CE - GetRealIconIndex(L"\\", FILE_ATTRIBUTE_DIRECTORY, iconIndex); + GetRealIconIndex(FTEXT("\\"), FILE_ATTRIBUTE_DIRECTORY, iconIndex); #else iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); #endif @@ -123,7 +123,7 @@ UString GetMyDocsPath() us = GetUnicodeString(s2); } #endif - if (us.Length() > 0 && us[us.Length() - 1] != WCHAR_PATH_SEPARATOR) + if (us.Length() > 0 && us.Back() != WCHAR_PATH_SEPARATOR) us += WCHAR_PATH_SEPARATOR; return us; } @@ -159,7 +159,7 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde { NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; subFolder = fsFolderSpec; - RINOK(fsFolderSpec->Init(s, NULL)); + RINOK(fsFolderSpec->Init(us2fs(s), NULL)); } } #endif @@ -227,7 +227,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu name2 += WCHAR_PATH_SEPARATOR; NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; subFolder = fsFolderSpec; - if (fsFolderSpec->Init(name2, 0) != S_OK) + if (fsFolderSpec->Init(us2fs(name2), 0) != S_OK) { #ifndef UNDER_CE if (name2[0] == WCHAR_PATH_SEPARATOR) diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index 10d063f7..866b0b2d 100755 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -10,7 +10,6 @@ #include "HelpUtils.h" #include "LangUtils.h" -#include "ProgramLocation.h" #include "RegistryUtils.h" #include "SettingsPage.h" diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index e359ed2b..e537621e 100755 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -24,7 +24,7 @@ int GetIconIndexForCSIDL(int csidl) SHGFI_PIDL | SHGFI_SYSICONINDEX); IMalloc *pMalloc; SHGetMalloc(&pMalloc); - if(pMalloc) + if (pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); @@ -34,16 +34,6 @@ int GetIconIndexForCSIDL(int csidl) return 0; } -DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex) -{ - SHFILEINFO shellInfo; - DWORD_PTR res = ::SHGetFileInfo(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, - sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); - iconIndex = shellInfo.iIcon; - return res; -} - - #ifndef _UNICODE typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); @@ -70,28 +60,32 @@ static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *ps pszPath, attrib, psfi, cbFileInfo, uFlags); } -#ifndef _UNICODE -// static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex) +DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) { - if(g_IsNT) + #ifndef _UNICODE + if (!g_IsNT) { - SHFILEINFOW shellInfo; - DWORD_PTR res = ::MySHGetFileInfoW(path, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + SHFILEINFO shellInfo; + DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); iconIndex = shellInfo.iIcon; return res; } else - return GetRealIconIndex(UnicodeStringToMultiByte(path), attrib, iconIndex); + #endif + { + SHFILEINFOW shellInfo; + DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); + iconIndex = shellInfo.iIcon; + return res; + } } -#endif -DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, - int &iconIndex, UString &typeName) +DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString &typeName) { #ifndef _UNICODE - if(!g_IsNT) + if (!g_IsNT) { SHFILEINFO shellInfo; shellInfo.szTypeName[0] = 0; diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h index 5ba9c57f..129de781 100755 --- a/CPP/7zip/UI/FileManager/SysIconUtils.h +++ b/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -39,10 +39,7 @@ public: int GetIconIndex(DWORD attrib, const UString &fileName); }; -DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attrib, int &iconIndex); -#ifndef _UNICODE -DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attrib, int &iconIndex); -#endif +DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex); int GetIconIndexForCSIDL(int csidl); inline HIMAGELIST GetSysImageList(bool smallIcons) diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index 3681992d..359656ea 100755 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -1,172 +1,266 @@ // SystemPage.cpp #include "StdAfx.h" -#include "SystemPageRes.h" -#include "SystemPage.h" #include "Common/StringConvert.h" -#include "Common/MyCom.h" -#include "Windows/Defs.h" -#include "Windows/Control/ListView.h" -#include "Windows/FileFind.h" +#include "Windows/DLL.h" +#include "Windows/Error.h" -#include "IFolder.h" #include "HelpUtils.h" +#include "IFolder.h" #include "LangUtils.h" -#include "PluginLoader.h" -#include "ProgramLocation.h" -#include "StringUtils.h" - #include "PropertyNameRes.h" -#include "../Agent/Agent.h" +#include "SystemPage.h" +#include "SystemPageRes.h" -using namespace NRegistryAssociations; +static const CIDLangPair kIDLangPairs[] = +{ + { IDC_SYSTEM_STATIC_ASSOCIATE, 0x03010302} + // { IDC_SYSTEM_SELECT_ALL, 0x03000330} +}; -const int kRefreshpluginsListMessage = WM_USER + 1; -const int kUpdateDatabase = kRefreshpluginsListMessage + 1; +static LPCWSTR kSystemTopic = L"FM/options.htm#system"; -static CIDLangPair kIDLangPairs[] = +CSysString CModifiedExtInfo::GetString() const { - { IDC_SYSTEM_STATIC_ASSOCIATE, 0x03010302}, - { IDC_SYSTEM_SELECT_ALL, 0x03000330} + if (State == kExtState_7Zip) + return TEXT("7-Zip"); + if (State == kExtState_Clear) + return TEXT(""); + if (Other7Zip) + return TEXT("[7-Zip]"); + return ProgramKey; }; -static LPCWSTR kSystemTopic = L"FM/options.htm#system"; +int CSystemPage::AddIcon(const UString &iconPath, int iconIndex) +{ + if (iconPath.IsEmpty()) + return -1; + if (iconIndex == -1) + iconIndex = 0; + HICON hicon; + #ifdef UNDER_CE + ExtractIconExW(iconPath, iconIndex, NULL, &hicon, 1); + if (!hicon) + #else + // we expand path from REG_EXPAND_SZ registry item. + UString path; + DWORD size = MAX_PATH + 10; + DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuffer((int)size + 1), size); + path.ReleaseBuffer(); + if (needLen == 0 || needLen >= size) + path = iconPath; + int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1); + if (num != 1 || !hicon) + #endif + return -1; + _imageList.AddIcon(hicon); + DestroyIcon(hicon); + return _numIcons++; +} +void CSystemPage::RefreshListItem(int group, int listIndex) +{ + const CAssoc &assoc = _items[GetRealIndex(listIndex)]; + _listView.SetSubItem(listIndex, group + 1, assoc.Pair[group].GetString()); + LVITEMW newItem; + memset(&newItem, 0, sizeof(newItem)); + newItem.iItem = listIndex; + newItem.mask = LVIF_IMAGE; + newItem.iImage = assoc.GetIconIndex(); + _listView.SetItem(&newItem); +} + +void CSystemPage::ChangeState(int group, const CIntVector &indices) +{ + if (indices.IsEmpty()) + return; + + bool thereAreClearItems = false; + int counters[3] = { 0, 0, 0 }; + + int i; + for (i = 0; i < indices.Size(); i++) + { + const CModifiedExtInfo &mi = _items[GetRealIndex(indices[i])].Pair[group]; + int state = kExtState_7Zip; + if (mi.State == kExtState_7Zip) + state = kExtState_Clear; + else if (mi.State == kExtState_Clear) + { + thereAreClearItems = true; + if (mi.Other) + state = kExtState_Other; + } + counters[state]++; + } + + int state = kExtState_Clear; + if (counters[kExtState_Other] != 0) + state = kExtState_Other; + else if (counters[kExtState_7Zip] != 0) + state = kExtState_7Zip; + + for (i = 0; i < indices.Size(); i++) + { + int listIndex = indices[i]; + CAssoc &assoc = _items[GetRealIndex(listIndex)]; + CModifiedExtInfo &mi = assoc.Pair[group]; + bool change = false; + switch (state) + { + case kExtState_Clear: change = true; break; + case kExtState_Other: change = mi.Other; break; + default: change = !(mi.Other && thereAreClearItems); break; + } + if (change) + { + mi.State = state; + RefreshListItem(group, listIndex); + } + } + Changed(); +} bool CSystemPage::OnInit() { - _initMode = true; - LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + LangSetDlgItemsText((HWND)*this, kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0])); + + _listView.Attach(GetItem(IDC_SYSTEM_LIST_ASSOCIATE)); + _listView.SetUnicodeFormat(); + DWORD newFlags = LVS_EX_FULLROWSELECT; + _listView.SetExtendedListViewStyle(newFlags, newFlags); - _listViewExt.Attach(GetItem(IDC_SYSTEM_LIST_ASSOCIATE)); - _listViewPlugins.Attach(GetItem(IDC_SYSTEM_LIST_PLUGINS)); + _numIcons = 0; + _imageList.Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 0); - /* - CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, - NRegistryAssociations::CheckContextMenuHandler()); - */ + _listView.SetImageList(_imageList, LVSIL_SMALL); - UINT32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; - _listViewExt.SetExtendedListViewStyle(newFlags, newFlags); - _listViewPlugins.SetExtendedListViewStyle(newFlags, newFlags); + _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE, 0x02000214), 72); - _listViewExt.InsertColumn(0, LangString(IDS_PROP_EXTENSION, 0x02000205), 40); - const UString s = LangString(IDS_PLUGIN, 0x03010310); - _listViewExt.InsertColumn(1, s, 40); + CSysString s; - _listViewPlugins.InsertColumn(0, s, 40); + #if NUM_EXT_GROUPS == 1 + s = TEXT("Program"); + #else + #ifndef UNDER_CE + DWORD size = 256; + BOOL res = GetUserName(s.GetBuffer(size), &size); + s.ReleaseBuffer(); + if (!res) + #endif + s = TEXT("Current User"); + #endif - _extDatabase.Read(); + LVCOLUMN ci; + ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; + ci.cx = 100; + ci.pszText = (TCHAR *)(const TCHAR *)s; + ci.iSubItem = 1; + ci.fmt = LVCFMT_CENTER; + _listView.InsertColumn(1, &ci); - for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++) + #if NUM_EXT_GROUPS > 1 { - CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i]; - - int itemIndex = _listViewExt.InsertItem(i, (LPCWSTR)extInfo.Ext); + ci.iSubItem = 2; + ci.pszText = TEXT("All Users"); + _listView.InsertColumn(2, &ci); + } + #endif - UString iconPath; - int iconIndex; - extInfo.Associated = NRegistryAssociations::CheckShellExtensionInfo(GetSystemString(extInfo.Ext), iconPath, iconIndex); - if (extInfo.Associated && !NWindows::NFile::NFind::DoesFileExist(iconPath)) - extInfo.Associated = false; - _listViewExt.SetCheckState(itemIndex, extInfo.Associated); + _extDB.Read(); + _items.Clear(); - SetMainPluginText(itemIndex, i); + for (int i = 0; i < _extDB.Exts.Size(); i++) + { + const CExtPlugins &extInfo = _extDB.Exts[i]; + + LVITEMW item; + item.iItem = i; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + item.lParam = i; + item.iSubItem = 0; + // ListView always uses internal iImage that is 0 by default? + // so we always use LVIF_IMAGE. + item.iImage = -1; + item.pszText = (wchar_t *)(const wchar_t *)(LPCWSTR)extInfo.Ext; + + CAssoc assoc; + const CPluginToIcon &plug = extInfo.Plugins[0]; + assoc.SevenZipImageIndex = AddIcon(plug.IconPath, plug.IconIndex); + + CSysString texts[NUM_EXT_GROUPS]; + int g; + for (g = 0; g < NUM_EXT_GROUPS; g++) + { + CModifiedExtInfo &mi = assoc.Pair[g]; + mi.ReadFromRegistry(GetHKey(g), GetSystemString(extInfo.Ext)); + mi.SetState(plug.IconPath); + mi.ImageIndex = AddIcon(mi.IconPath, mi.IconIndex); + texts[g] = mi.GetString(); + } + item.iImage = assoc.GetIconIndex(); + int itemIndex = _listView.InsertItem(&item); + for (g = 0; g < NUM_EXT_GROUPS; g++) + _listView.SetSubItem(itemIndex, 1 + g, texts[g]); + _items.Add(assoc); } - // _listViewExt.SortItems(); - if (_listViewExt.GetItemCount() > 0) - _listViewExt.SetItemState_FocusedSelected(0); - RefreshPluginsList(-1); - _initMode = false; + if (_listView.GetItemCount() > 0) + _listView.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); return CPropertyPage::OnInit(); } -void CSystemPage::SetMainPluginText(int itemIndex, int indexInDatabase) -{ - _listViewExt.SetSubItem(itemIndex, 1, _extDatabase.GetMainPluginNameForExtItem(indexInDatabase)); -} - static UString GetProgramCommand() { - UString path = L"\""; - UString folder; - if (GetProgramFolderPath(folder)) - path += folder; - path += L"7zFM.exe\" \"%1\""; - return path; -} - -static UString GetIconPath(const UString &filePath, - const CLSID &clsID, const UString &extension, Int32 &iconIndex) -{ - CPluginLibrary library; - CMyComPtr<IFolderManager> folderManager; - CMyComPtr<IFolderFolder> folder; - if (filePath.IsEmpty()) - folderManager = new CArchiveFolderManager; - else if (library.LoadAndCreateManager(filePath, clsID, &folderManager) != S_OK) - return UString(); - CMyComBSTR extBSTR; - if (folderManager->GetExtensions(&extBSTR) != S_OK) - return UString(); - const UString ext2 = (const wchar_t *)extBSTR; - UStringVector exts; - SplitString(ext2, exts); - for (int i = 0; i < exts.Size(); i++) - { - const UString &plugExt = exts[i]; - if (extension.CompareNoCase((const wchar_t *)plugExt) == 0) - { - CMyComBSTR iconPathTemp; - if (folderManager->GetIconPath(plugExt, &iconPathTemp, &iconIndex) != S_OK) - break; - if (iconPathTemp != 0) - return (const wchar_t *)iconPathTemp; - } - } - return UString(); + return L"\"" + fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zFM.exe\" \"%1\""; } LONG CSystemPage::OnApply() { - UpdateDatabase(); - _extDatabase.Save(); - UString command = GetProgramCommand(); + const UString command = GetProgramCommand(); - for (int i = 0; i < _extDatabase.ExtBigItems.Size(); i++) + LONG res = 0; + + for (int listIndex = 0; listIndex < _extDB.Exts.Size(); listIndex++) { - const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[i]; - if (extInfo.Associated) + int realIndex = GetRealIndex(listIndex); + const CExtPlugins &extInfo = _extDB.Exts[realIndex]; + CAssoc &assoc = _items[realIndex]; + + for (int g = 0; g < NUM_EXT_GROUPS; g++) { - UString title = extInfo.Ext + UString(L" Archive"); - UString command = GetProgramCommand(); - UString iconPath; - Int32 iconIndex = -1; - if (!extInfo.PluginsPairs.IsEmpty()) + CModifiedExtInfo &mi = assoc.Pair[g]; + HKEY key = GetHKey(g); + if (mi.OldState != mi.State) { - const CPluginInfo &plugin = _extDatabase.Plugins[extInfo.PluginsPairs[0].Index]; - iconPath = GetIconPath(plugin.FilePath, plugin.ClassID, extInfo.Ext, iconIndex); + LONG res2 = 0; + if (mi.State == kExtState_7Zip) + { + UString title = extInfo.Ext + UString(L" Archive"); + const CPluginToIcon &plug = extInfo.Plugins[0]; + res2 = NRegistryAssoc::AddShellExtensionInfo(key, GetSystemString(extInfo.Ext), + title, command, plug.IconPath, plug.IconIndex); + } + else if (mi.State == kExtState_Clear) + res2 = NRegistryAssoc::DeleteShellExtensionInfo(key, GetSystemString(extInfo.Ext)); + if (res == 0) + res = res2; + if (res2 == 0) + mi.OldState = mi.State; + mi.State = mi.OldState; + RefreshListItem(g, listIndex); } - NRegistryAssociations::AddShellExtensionInfo(GetSystemString(extInfo.Ext), - title, command, iconPath, iconIndex, NULL, 0); } - else - NRegistryAssociations::DeleteShellExtensionInfo(GetSystemString(extInfo.Ext)); } - /* - if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) - NRegistryAssociations::AddContextMenuHandler(); - else - NRegistryAssociations::DeleteContextMenuHandler(); - */ #ifndef UNDER_CE SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); WasChanged = true; #endif + if (res != 0) + MessageBoxW(*this, NWindows::NError::MyFormatMessageW(res), L"7-Zip", MB_ICONERROR); return PSNRET_NOERROR; } @@ -175,228 +269,119 @@ void CSystemPage::OnNotifyHelp() ShowHelpWindow(NULL, kSystemTopic); } -void CSystemPage::SelectAll() -{ - int count = _listViewExt.GetItemCount(); - for (int i = 0; i < count; i++) - _listViewExt.SetCheckState(i, true); - UpdateDatabase(); -} - bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch(buttonID) + switch (buttonID) { + /* case IDC_SYSTEM_SELECT_ALL: - { - SelectAll(); - Changed(); + _listView.SelectAll(); + return true; + */ + case IDC_SYSTEM_BUTTON_CURRENT: + case IDC_SYSTEM_BUTTON_ALL: + ChangeState(buttonID == IDC_SYSTEM_BUTTON_CURRENT ? 0 : 1); return true; - } } return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) { - if (lParam->hwndFrom == HWND(_listViewExt)) + if (lParam->hwndFrom == HWND(_listView)) { - switch(lParam->code) + switch (lParam->code) { - case (LVN_ITEMCHANGED): - return OnItemChanged((const NMLISTVIEW *)lParam); - case NM_RCLICK: - case NM_DBLCLK: - case LVN_KEYDOWN: - case NM_CLICK: - case LVN_BEGINRDRAG: - PostMessage(kRefreshpluginsListMessage, 0); - PostMessage(kUpdateDatabase, 0); - break; - } - } - else if (lParam->hwndFrom == HWND(_listViewPlugins)) - { - switch(lParam->code) - { - case NM_RCLICK: - case NM_DBLCLK: - // case LVN_KEYDOWN: + case NM_RETURN: + { + ChangeState(0); + return true; + } + break; case NM_CLICK: - case LVN_BEGINRDRAG: - PostMessage(kUpdateDatabase, 0); - break; - - case (LVN_ITEMCHANGED): { - OnItemChanged((const NMLISTVIEW *)lParam); - PostMessage(kUpdateDatabase, 0); + #ifdef UNDER_CE + NMLISTVIEW *item = (NMLISTVIEW *)lParam; + #else + NMITEMACTIVATE *item = (NMITEMACTIVATE *)lParam; + if (item->uKeyFlags == 0) + #endif + { + int realIndex = GetRealIndex(item->iItem); + if (realIndex >= 0) + { + if (item->iSubItem >= 1 && item->iSubItem <= 2) + { + CIntVector indices; + indices.Add(item->iItem); + ChangeState(item->iSubItem < 2 ? 0 : 1, indices); + } + } + } break; } case LVN_KEYDOWN: { - OnPluginsKeyDown((LPNMLVKEYDOWN)lParam); - PostMessage(kUpdateDatabase, 0); + if (OnListKeyDown(LPNMLVKEYDOWN(lParam))) + return true; break; } + /* + case NM_RCLICK: + case NM_DBLCLK: + case LVN_BEGINRDRAG: + // PostMessage(kRefreshpluginsListMessage, 0); + PostMessage(kUpdateDatabase, 0); + break; + */ } } return CPropertyPage::OnNotify(controlID, lParam); } -bool CSystemPage::OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo) +void CSystemPage::ChangeState(int group) { - bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; - // bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - switch(keyDownInfo->wVKey) - { - case VK_UP: - { - if (alt) - MovePlugin(true); - return true; - } - case VK_DOWN: - { - if (alt) - MovePlugin(false); - return true; - } - } - return false; + CIntVector indices; + int itemIndex = -1; + while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1) + indices.Add(itemIndex); + if (indices.IsEmpty()) + for (int i = 0; i < _items.Size(); i++) + indices.Add(i); + ChangeState(group, indices); } -void CSystemPage::MovePlugin(bool upDirection) +bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) { - int selectedPlugin = _listViewPlugins.GetSelectionMark(); - if (selectedPlugin < 0) - return; - int newIndex = selectedPlugin + (upDirection ? -1: 1); - if (newIndex < 0 || newIndex >= _listViewPlugins.GetItemCount()) - return; - int selectedExtIndex = GetSelectedExtIndex(); - if (selectedExtIndex < 0) - return; - CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; - CPluginEnabledPair pluginPairTemp = extInfo.PluginsPairs[newIndex]; - extInfo.PluginsPairs[newIndex] = extInfo.PluginsPairs[selectedPlugin]; - extInfo.PluginsPairs[selectedPlugin] = pluginPairTemp; - - SetMainPluginText(_listViewExt.GetSelectionMark(), selectedExtIndex); - RefreshPluginsList(newIndex); - - Changed(); -} - -bool CSystemPage::OnItemChanged(const NMLISTVIEW *info) -{ - if (_initMode) - return true; - if ((info->uChanged & LVIF_STATE) != 0) - { - UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK; - UINT newState = info->uNewState & LVIS_STATEIMAGEMASK; - if (oldState != newState) - Changed(); - } - // PostMessage(kRefreshpluginsListMessage, 0); - // RefreshPluginsList(); - return true; -} - -bool CSystemPage::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case kRefreshpluginsListMessage: - RefreshPluginsList(-1); - return true; - case kUpdateDatabase: - UpdateDatabase(); - return true; - } - return CPropertyPage::OnMessage(message, wParam, lParam); -} + bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; + bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0; -void CSystemPage::UpdateDatabase() -{ - int i; - for (i = 0; i < _listViewExt.GetItemCount(); i++) - { - LPARAM param; - if (!_listViewExt.GetItemParam(i, param)) - return; - CExtInfoBig &extInfo = _extDatabase.ExtBigItems[(int)param]; - extInfo.Associated = _listViewExt.GetCheckState(i); - } + if (alt) + return false; - int selectedExtIndex = GetSelectedExtIndex(); - if (selectedExtIndex < 0) - return; - - CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; - for (i = 0; i < _listViewPlugins.GetItemCount(); i++) + if ((ctrl && keyDownInfo->wVKey == 'A') || + (!ctrl && keyDownInfo->wVKey == VK_MULTIPLY)) { - extInfo.PluginsPairs[i].Enabled = _listViewPlugins.GetCheckState(i); + _listView.SelectAll(); + return true; } -} - - - -int CSystemPage::GetSelectedExtIndex() -{ - int selectedIndex = _listViewExt.GetSelectionMark(); - if (selectedIndex < 0) - return -1; - LPARAM param; - if (!_listViewExt.GetItemParam(selectedIndex, param)) - return -1; - return (int)param; -} - - -void CSystemPage::RefreshPluginsList(int selectIndex) -{ - _listViewPlugins.DeleteAllItems(); - int selectedExtIndex = GetSelectedExtIndex(); - if (selectedExtIndex < 0) - return; - const CExtInfoBig &extInfo = _extDatabase.ExtBigItems[selectedExtIndex]; - _initMode = true; - for (int i = 0; i < extInfo.PluginsPairs.Size(); i++) + switch (keyDownInfo->wVKey) { - CPluginEnabledPair pluginPair = extInfo.PluginsPairs[i]; - int itemIndex = _listViewPlugins.InsertItem(i, _extDatabase.Plugins[pluginPair.Index].Name); - _listViewPlugins.SetCheckState(itemIndex, pluginPair.Enabled); - } - if (_listViewPlugins.GetItemCount() > 0) - { - if (selectIndex < 0) - selectIndex = 0; - _listViewPlugins.SetItemState_FocusedSelected(selectIndex); + case VK_SPACE: + case VK_ADD: + case VK_SUBTRACT: + case VK_SEPARATOR: + case VK_DIVIDE: + #ifndef UNDER_CE + case VK_OEM_PLUS: + case VK_OEM_MINUS: + #endif + if (!ctrl) + { + ChangeState(keyDownInfo->wVKey == VK_SPACE ? 0 : 1); + return true; + } } - _initMode = false; + return false; } - - - -/* -static BYTE kZipShellNewData[] = - { 0x50-1, 0x4B, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0 }; - -static BYTE kRarShellNewData[] = - { 0x52-1, 0x61, 0x72, 0x21, 0x1A, 7, 0, 0xCF, 0x90, 0x73, 0, 0, 0x0D, 0, 0, 0, 0, 0, 0, 0}; - -class CSignatureMaker -{ -public: - CSignatureMaker() - { - kZipShellNewData[0]++; - kRarShellNewData[0]++; - }; -}; - -static CSignatureMaker g_SignatureMaker; -*/ diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h index 967731fd..a4b4ab92 100755 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -3,39 +3,117 @@ #ifndef __SYSTEM_PAGE_H #define __SYSTEM_PAGE_H -#include "Windows/Control/PropertyPage.h" +#include "Windows/Control/ImageList.h" #include "Windows/Control/ListView.h" +#include "Windows/Control/PropertyPage.h" #include "FilePlugins.h" +#include "RegistryAssociations.h" + +enum EExtState +{ + kExtState_Clear = 0, + kExtState_Other, + kExtState_7Zip +}; + +struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo +{ + int OldState; + int State; + int ImageIndex; + bool Other; + bool Other7Zip; + + CModifiedExtInfo(): ImageIndex(-1) {} + + CSysString GetString() const; + + void SetState(const UString &iconPath) + { + State = kExtState_Clear; + Other = false; + Other7Zip = false; + if (!ProgramKey.IsEmpty()) + { + State = kExtState_Other; + Other = true; + if (IsIt7Zip()) + { + Other7Zip = (iconPath.CompareNoCase(IconPath) != 0); + if (!Other7Zip) + { + State = kExtState_7Zip; + Other = false; + } + } + } + OldState = State; + }; +}; + +struct CAssoc +{ + CModifiedExtInfo Pair[2]; + int SevenZipImageIndex; + + int GetIconIndex() const + { + for (int i = 0; i < 2; i++) + { + const CModifiedExtInfo &pair = Pair[i]; + if (pair.State == kExtState_Clear) + continue; + if (pair.State == kExtState_7Zip) + return SevenZipImageIndex; + if (pair.ImageIndex != -1) + return pair.ImageIndex; + } + return -1; + } +}; + +#ifdef UNDER_CE + #define NUM_EXT_GROUPS 1 +#else + #define NUM_EXT_GROUPS 2 +#endif class CSystemPage: public NWindows::NControl::CPropertyPage { - bool _initMode; - CExtDatabase _extDatabase; + CExtDatabase _extDB; + CObjectVector<CAssoc> _items; - NWindows::NControl::CListView _listViewExt; - NWindows::NControl::CListView _listViewPlugins; + int _numIcons; + NWindows::NControl::CImageList _imageList; + NWindows::NControl::CListView _listView; - void SetMainPluginText(int itemIndex, int indexInDatabase); + const HKEY GetHKey(int group) const + { + #if NUM_EXT_GROUPS == 1 + return HKEY_CLASSES_ROOT; + #else + return group == 0 ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; + #endif + } - int GetSelectedExtIndex(); - void RefreshPluginsList(int selectIndex); - void MovePlugin(bool upDirection); - void UpdateDatabase(); - void SelectAll(); + int AddIcon(const UString &path, int iconIndex); + int GetRealIndex(int listIndex) const { return listIndex; } + void RefreshListItem(int group, int listIndex); + void ChangeState(int group, const CIntVector &indices); + void ChangeState(int group); + bool OnListKeyDown(LPNMLVKEYDOWN keyDownInfo); + public: bool WasChanged; CSystemPage(): WasChanged(false) {} - virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnInit(); virtual void OnNotifyHelp(); virtual bool OnNotify(UINT controlID, LPNMHDR lParam); - virtual bool OnItemChanged(const NMLISTVIEW *info); - virtual LONG OnApply(); virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); - bool OnPluginsKeyDown(LPNMLVKEYDOWN keyDownInfo); }; #endif diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc index 52e60d19..49581c9b 100755 --- a/CPP/7zip/UI/FileManager/SystemPage.rc +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -2,16 +2,18 @@ #include "../../GuiCommon.rc" #define xc 200 -#define yc 200 +#define yc 250 IDD_SYSTEM MY_PAGE CAPTION "System" BEGIN LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 + PUSHBUTTON "+", IDC_SYSTEM_BUTTON_CURRENT, 72, m + 12, 40, bys + PUSHBUTTON "+", IDC_SYSTEM_BUTTON_ALL, 140, m + 12, 40, bys CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", - LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, - m, m + 12, xc, (yc - m - 12 - 1 - bys) - PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys), 90, bys + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, m + 32, xc, (yc - m - 32 - 1) +; PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, m + 12, 60, bys END #ifdef UNDER_CE @@ -28,10 +30,11 @@ IDD_SYSTEM_2 MY_PAGE CAPTION "System" BEGIN LTEXT "Associate 7-Zip with:", IDC_SYSTEM_STATIC_ASSOCIATE, m, m, xc, 8 + PUSHBUTTON "+", IDC_SYSTEM_BUTTON_CURRENT, 60, m + 12, 40, bys CONTROL "List1", IDC_SYSTEM_LIST_ASSOCIATE, "SysListView32", - LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, - m, m + 12, xc, (yc - m - 12 - 1 - bys - 8) - PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, (ys - m - bys - 8), 90, bys + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, m + 32, xc, (yc - m - 32 - 1 - 8) +; PUSHBUTTON "Select all", IDC_SYSTEM_SELECT_ALL, m, m + 12, 60, bys END #endif diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h index b60b4533..133996e7 100755 --- a/CPP/7zip/UI/FileManager/SystemPageRes.h +++ b/CPP/7zip/UI/FileManager/SystemPageRes.h @@ -4,5 +4,7 @@ // #define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010 #define IDC_SYSTEM_STATIC_ASSOCIATE 1020 #define IDC_SYSTEM_LIST_ASSOCIATE 1021 -#define IDC_SYSTEM_LIST_PLUGINS 1022 -#define IDC_SYSTEM_SELECT_ALL 1023 +// #define IDC_SYSTEM_LIST_PLUGINS 1022 +// #define IDC_SYSTEM_SELECT_ALL 1023 +#define IDC_SYSTEM_BUTTON_CURRENT 1024 +#define IDC_SYSTEM_BUTTON_ALL 1025 diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index 13c8e0e7..cdb77edf 100755 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -52,6 +52,7 @@ #define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 463 #define IDM_OPTIONS 510 #define IDM_BENCHMARK 511 +#define IDM_BENCHMARK2 512 #define IDM_HELP_CONTENTS 610 #define IDM_ABOUT 620 #define IDS_BOOKMARK 720 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 833cb374..2952ce5a 100755 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -95,6 +95,9 @@ BEGIN BEGIN MENUITEM "&Options...", IDM_OPTIONS MENUITEM "&Benchmark", IDM_BENCHMARK + #ifdef UNDER_CE + MENUITEM "&Benchmark2", IDM_BENCHMARK2 + #endif #ifndef UNDER_CE END POPUP "&Help" diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index e4d6c019..8ca87f8f 100755 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -4,6 +4,7 @@ #include "Common/IntToString.h" #include "Common/MyException.h" +#include "Common/StringConvert.h" #include "Windows/Error.h" #include "Windows/System.h" @@ -85,6 +86,25 @@ bool CBenchmarkDialog::OnInit() Sync.Init(); + if (TotalMode) + { + _consoleEdit.Attach(GetItem(IDC_BENCHMARK2_EDIT)); + LOGFONT f; + memset(&f, 0, sizeof(f)); + f.lfHeight = 14; + f.lfWidth = 0; + f.lfWeight = FW_DONTCARE; + f.lfCharSet = DEFAULT_CHARSET; + f.lfOutPrecision = OUT_DEFAULT_PRECIS; + f.lfClipPrecision = CLIP_DEFAULT_PRECIS; + f.lfQuality = DEFAULT_QUALITY; + + f.lfPitchAndFamily = FIXED_PITCH; + MyStringCopy(f.lfFaceName, TEXT("")); + _font.Create(&f); + if (_font._font) + _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE); + } UInt32 numCPUs = NSystem::GetNumberOfProcessors(); if (numCPUs < 1) @@ -101,8 +121,8 @@ bool CBenchmarkDialog::OnInit() int cur = 0; for (UInt32 num = 1; num <= numCPUs * 2;) { - TCHAR s[40]; - ConvertUInt64ToString(num, s); + TCHAR s[16]; + ConvertUInt32ToString(num, s); int index = (int)m_NumThreads.AddString(s); m_NumThreads.SetItemData(index, num); if (num <= Sync.NumThreads) @@ -143,8 +163,8 @@ bool CBenchmarkDialog::OnInit() UInt32 dictionary = (1 << i) + (j << (i - 1)); if (dictionary > kMaxDicSize) continue; - TCHAR s[40]; - ConvertUInt64ToString((dictionary >> 20), s); + TCHAR s[16]; + ConvertUInt32ToString((dictionary >> 20), s); lstrcat(s, kMB); int index = (int)m_Dictionary.AddString(s); m_Dictionary.SetItemData(index, dictionary); @@ -158,10 +178,47 @@ bool CBenchmarkDialog::OnInit() Sync._startEvent.Set(); _timer = SetTimer(kTimerID, kTimerElapse); - NormalizePosition(); + if (TotalMode) + NormalizeSize(true); + else + NormalizePosition(); return CModalDialog::OnInit(); } +bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + if (!TotalMode) + return false; + int mx, my; + GetMargins(8, mx, my); + int bx1, bx2, by; + GetItemSizes(IDCANCEL, bx1, by); + GetItemSizes(IDHELP, bx2, by); + int y = ySize - my - by; + int x = xSize - mx - bx1; + + InvalidateRect(NULL); + + MoveItem(IDCANCEL, x, y, bx1, by); + MoveItem(IDHELP, x - mx - bx2, y, bx2, by); + if (_consoleEdit) + { + int yPos = ySize - my - by; + RECT rect; + GetClientRectOfItem(IDC_BENCHMARK2_EDIT, rect); + int y = rect.top; + int ySize2 = yPos - my - y; + const int kMinYSize = 20; + int xx = xSize - mx * 2; + if (ySize2 < kMinYSize) + { + ySize2 = kMinYSize; + } + _consoleEdit.Move(mx, y, xx, ySize2); + } + return false; +} + UInt32 CBenchmarkDialog::GetNumberOfThreads() { return (UInt32)m_NumThreads.GetItemData(m_NumThreads.GetCurSel()); @@ -209,7 +266,7 @@ void CBenchmarkDialog::OnChangeSettings() EnableItem(IDC_BUTTON_STOP, true); UInt32 dictionary = OnChangeDictionary(); TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; - ConvertUInt64ToString(NSystem::GetNumberOfProcessors(), s + 2); + ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); SetItemText(IDC_BENCHMARK_HARDWARE_THREADS, s); for (int i = 0; i < sizeof(g_IDs) / sizeof(g_IDs[0]); i++) SetItemText(g_IDs[i], kProcessingString); @@ -305,15 +362,32 @@ void CBenchmarkDialog::PrintResults( rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, size * info.NumIterations); PrintRating(rating, ratingID); - PrintRating(GetRatingPerUsage(info, rating), rpuID); - PrintUsage(GetUsage(info), usageID); + PrintRating(info.GetRatingPerUsage(rating), rpuID); + PrintUsage(info.GetUsage(), usageID); } bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { - PrintTime(); + bool printTime = true; + if (TotalMode) + { + if (Sync.WasStopped()) + printTime = false; + } + if (printTime) + PrintTime(); NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS); + if (TotalMode) + { + if (Sync.TextWasChanged) + { + _consoleEdit.SetText(GetSystemString(Sync.Text)); + Sync.TextWasChanged = false; + } + return true; + } + TCHAR s[40]; ConvertUInt64ToString((Sync.ProcessedSize >> 20), s); lstrcat(s, kMB); @@ -377,9 +451,11 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) Sync.DecompressingInfo.PackSize, 1); PrintRating((comprRating + decomprRating) / 2, IDC_BENCHMARK_TOTAL_RATING_VALUE); PrintRating(( - GetRatingPerUsage(Sync.CompressingInfo, comprRating) + - GetRatingPerUsage(Sync.DecompressingInfo, decomprRating)) / 2, IDC_BENCHMARK_TOTAL_RPU_VALUE); - PrintUsage((GetUsage(Sync.CompressingInfo) + GetUsage(Sync.DecompressingInfo)) / 2, IDC_BENCHMARK_TOTAL_USAGE_VALUE); + Sync.CompressingInfo.GetRatingPerUsage(comprRating) + + Sync.DecompressingInfo.GetRatingPerUsage(decomprRating)) / 2, IDC_BENCHMARK_TOTAL_RPU_VALUE); + PrintUsage( + (Sync.CompressingInfo.GetUsage() + + Sync.DecompressingInfo.GetUsage()) / 2, IDC_BENCHMARK_TOTAL_USAGE_VALUE); } } return true; @@ -414,7 +490,6 @@ bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) struct CThreadBenchmark { CBenchmarkDialog *BenchmarkDialog; - UInt64 _startTime; DECL_EXTERNAL_CODECS_VARS // UInt32 dictionarySize; // UInt32 numThreads; @@ -478,6 +553,35 @@ HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) return S_OK; } +struct CBenchCallback2: public IBenchPrintCallback +{ + CProgressSyncInfo *Sync; + + void Print(const char *s); + void NewLine(); + HRESULT CheckBreak(); +}; + +void CBenchCallback2::Print(const char *s) +{ + NSynchronization::CCriticalSectionLock lock(Sync->CS); + Sync->Text += s; + Sync->TextWasChanged = true; +} + +void CBenchCallback2::NewLine() +{ + Print("\xD\n"); +} + +HRESULT CBenchCallback2::CheckBreak() +{ + if (Sync->Changed || Sync->Paused || Sync->Stopped) + return E_ABORT; + return S_OK; +} + + HRESULT CThreadBenchmark::Process() { CProgressSyncInfo &sync = BenchmarkDialog->Sync; @@ -508,12 +612,44 @@ HRESULT CThreadBenchmark::Process() CBenchCallback callback; callback.dictionarySize = dictionarySize; callback.Sync = &sync; + CBenchCallback2 callback2; + callback2.Sync = &sync; HRESULT result; try { - result = LzmaBench( - EXTERNAL_CODECS_VARS - numThreads, dictionarySize, &callback); + CObjectVector<CProperty> props; + if (BenchmarkDialog->TotalMode) + { + props = BenchmarkDialog->Props; + } + else + { + { + CProperty prop; + prop.Name = L"mt"; + wchar_t s[16]; + ConvertUInt32ToString(numThreads, s); + prop.Value = s; + props.Add(prop); + } + { + CProperty prop; + prop.Name = L"d"; + wchar_t s[16]; + ConvertUInt32ToString(dictionarySize, s); + prop.Name += s; + prop.Name += 'b'; + props.Add(prop); + } + } + result = Bench(EXTERNAL_CODECS_VARS + BenchmarkDialog->TotalMode ? &callback2 : NULL, + BenchmarkDialog->TotalMode ? NULL : &callback, + props, 1, false); + if (BenchmarkDialog->TotalMode) + { + sync.Stop(); + } } catch(...) { @@ -561,7 +697,7 @@ HRESULT CThreadBenchmark::Process() HRESULT Benchmark( DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent) + const CObjectVector<CProperty> props, HWND hwndParent) { CThreadBenchmark benchmarker; #ifdef EXTERNAL_CODECS @@ -569,13 +705,21 @@ HRESULT Benchmark( benchmarker._externalCodecs = *externalCodecs; #endif - CBenchmarkDialog benchmarkDialog; - benchmarkDialog.Sync.DictionarySize = dictionarySize; - benchmarkDialog.Sync.NumThreads = numThreads; + CBenchmarkDialog bd; + bd.Props = props; + bd.TotalMode = false; + for (int i = 0; i < props.Size(); i++) + { + const CProperty &prop = props[i]; + if (prop.Name.CompareNoCase(L"m") == 0 && prop.Value == L"*") + bd.TotalMode = true; + } + bd.Sync.DictionarySize = (UInt32)-1; + bd.Sync.NumThreads = (UInt32)-1; + benchmarker.BenchmarkDialog = &bd; - benchmarker.BenchmarkDialog = &benchmarkDialog; NWindows::CThread thread; RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker)); - benchmarkDialog.Create(hwndParent); + bd.Create(hwndParent); return thread.Wait(); } diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h index 2b6216fd..b3ab9dcb 100755 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -5,6 +5,7 @@ #include "Windows/Synchronization.h" #include "Windows/Control/ComboBox.h" +#include "Windows/Control/Edit.h" #include "../Common/Bench.h" @@ -37,6 +38,9 @@ public: CBenchInfo2 DecompressingInfoTemp; CBenchInfo2 DecompressingInfo; + AString Text; + bool TextWasChanged; + CProgressSyncInfo() { if (_startEvent.Create() != S_OK) @@ -56,6 +60,9 @@ public: NumPasses = 0; // NumErrors = 0; + + Text.Empty(); + TextWasChanged = true; } void Stop() { @@ -85,14 +92,33 @@ public: void WaitCreating() { _startEvent.Lock(); } }; +struct CMyFont +{ + HFONT _font; + CMyFont(): _font(NULL) {} + ~CMyFont() + { + if (_font) + DeleteObject(_font); + } + void Create(const LOGFONT *lplf) + { + _font = CreateFontIndirect(lplf); + } +}; + + class CBenchmarkDialog: public NWindows::NControl::CModalDialog { NWindows::NControl::CComboBox m_Dictionary; NWindows::NControl::CComboBox m_NumThreads; + NWindows::NControl::CEdit _consoleEdit; UINT_PTR _timer; UINT32 _startTime; + CMyFont _font; + bool OnSize(WPARAM /* wParam */, int xSize, int ySize); bool OnTimer(WPARAM timerID, LPARAM callback); virtual bool OnInit(); void OnRestartButton(); @@ -115,12 +141,14 @@ class CBenchmarkDialog: void OnChangeSettings(); public: CProgressSyncInfo Sync; + bool TotalMode; + CObjectVector<CProperty> Props; - CBenchmarkDialog(): _timer(0) {} + CBenchmarkDialog(): _timer(0), TotalMode(false) {} INT_PTR Create(HWND wndParent = 0) { BIG_DIALOG_SIZE(332, 228); - return CModalDialog::Create(SIZED_DIALOG(IDD_DIALOG_BENCHMARK), wndParent); + return CModalDialog::Create(TotalMode ? IDD_DIALOG_BENCHMARK_TOTAL : SIZED_DIALOG(IDD_DIALOG_BENCHMARK), wndParent); } void MessageBoxError(LPCWSTR message) { @@ -130,6 +158,6 @@ public: HRESULT Benchmark( DECL_EXTERNAL_CODECS_LOC_VARS - UInt32 numThreads, UInt32 dictionarySize, HWND hwndParent = NULL); + const CObjectVector<CProperty> props, HWND hwndParent = NULL); #endif diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc index b77bac5f..6b17a12a 100755 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -41,6 +41,12 @@ #define g3xs 36 #define g3x (m + g2xs) +#undef GROUP_Y_SIZE +#ifdef UNDER_CE +#define GROUP_Y_SIZE 8 +#else +#define GROUP_Y_SIZE 40 +#endif IDD_DIALOG_BENCHMARK DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX CAPTION "Benchmark" @@ -66,7 +72,7 @@ BEGIN RTEXT "Rating / Usage", IDC_BENCHMARK_RPU_LABEL, xRpu, 54, sRpu, 8 RTEXT "Rating", IDC_BENCHMARK_RATING_LABEL, xRating, 54, sRating, 8 - GROUPBOX "Compressing", IDC_BENCHMARK_COMPRESSING, m, 64, xc, 40 + GROUPBOX "Compressing", IDC_BENCHMARK_COMPRESSING, m, 64, xc, GROUP_Y_SIZE LTEXT "Current", IDC_BENCHMARK_CURRENT, g4x, 76, sLabel, 8 RTEXT "100%", IDC_BENCHMARK_COMPRESSING_USAGE, xUsage, 76, sUsage, 8 @@ -80,7 +86,7 @@ BEGIN RTEXT "0", IDC_BENCHMARK_COMPRESSING_RPU2, xRpu, 89, sRpu, 8 RTEXT "0", IDC_BENCHMARK_COMPRESSING_RATING2, xRating, 89, sRating, 8 - GROUPBOX "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 111, xc, 40 + GROUPBOX "Decompressing", IDC_BENCHMARK_DECOMPRESSING, m, 111, xc, GROUP_Y_SIZE LTEXT "Current", IDC_BENCHMARK_CURRENT2, g4x, 123, sLabel, 8 RTEXT "100%", IDC_BENCHMARK_DECOMPRESSING_USAGE, xUsage, 123, sUsage, 8 @@ -94,7 +100,7 @@ BEGIN RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RPU2, xRpu, 136, sRpu, 8 RTEXT "0", IDC_BENCHMARK_DECOMPRESSING_RATING2, xRating, 136, sRating, 8 - GROUPBOX "Total Rating", IDC_BENCHMARK_TOTAL_RATING, xTotalRating, 163, sTotalRating, 38 + GROUPBOX "Total Rating", IDC_BENCHMARK_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y_SIZE RTEXT "0", IDC_BENCHMARK_TOTAL_USAGE_VALUE, xUsage, 181, sUsage, 8 RTEXT "0", IDC_BENCHMARK_TOTAL_RPU_VALUE, xRpu, 181, sRpu, 8 RTEXT "0", IDC_BENCHMARK_TOTAL_RATING_VALUE, xRating, 181, sRating, 8 @@ -225,3 +231,18 @@ BEGIN END #endif + +#include "../../GuiCommon.rc" + +#define xc 360 +#define yc 260 + +IDD_DIALOG_BENCHMARK_TOTAL MY_RESIZE_DIALOG +CAPTION "Benchmark" +{ + LTEXT "Elapsed time:", IDC_BENCHMARK_ELAPSED, m, m, 58, 8 + RTEXT "00:00:00", IDC_BENCHMARK_ELAPSED_VALUE, m + 58, m, 38, 8 + EDITTEXT IDC_BENCHMARK2_EDIT, m, m + 14, xc, yc - bys - m - 14, ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "&Help", IDHELP, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys +} diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h index 2488bd1c..cf009df3 100755 --- a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h @@ -1,5 +1,7 @@ #define IDD_DIALOG_BENCHMARK 550 #define IDD_DIALOG_BENCHMARK_2 650 +#define IDD_DIALOG_BENCHMARK_TOTAL 750 +#define IDD_DIALOG_BENCHMARK_TOTAL_2 750 #define IDC_BUTTON_STOP 1001 #define IDC_BUTTON_RESTART 1002 #define IDC_BENCHMARK_DICTIONARY 1010 @@ -53,3 +55,5 @@ #define IDC_BENCHMARK_SIZE_VALUE 1063 #define IDC_BENCHMARK_PASSES 1066 #define IDC_BENCHMARK_PASSES_VALUE 1067 + +#define IDC_BENCHMARK2_EDIT 1090 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index da2b7924..2723f515 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -351,7 +351,10 @@ namespace NCompressDialog #ifndef UNDER_CE NDirectory::MySetCurrentDirectory(CurrentDirPrefix); #endif - return MyGetFullPathName(ArchiveName, result); + FString resultF; + bool res = MyGetFullPathName(us2fs(ArchiveName), resultF); + result = fs2us(resultF); + return res; } } @@ -1236,6 +1239,7 @@ bool CCompressDialog::GetOrderMode() switch (GetMethodID()) { case kPPMd: + case kPPMdZip: return true; } return false; diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index 86f7b173..7b0067fa 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -49,7 +49,7 @@ namespace NCompressDialog UString ArchiveName; // in: Relative for ; out: abs - UString CurrentDirPrefix; + FString CurrentDirPrefix; bool KeepName; bool GetFullPathName(UString &result) const; diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 5f622c76..5a71b043 100755 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -36,6 +36,16 @@ #define yOpt 72 #define yPsw 128 +#undef GROUP_Y_SIZE +#undef GROUP_Y_SIZE_ENCRYPT +#ifdef UNDER_CE +#define GROUP_Y_SIZE 8 +#define GROUP_Y_SIZE_ENCRYPT 8 +#else +#define GROUP_Y_SIZE 48 +#define GROUP_Y_SIZE_ENCRYPT 128 +#endif + IDD_DIALOG_COMPRESS MY_DIALOG CAPTION "Add to Archive" BEGIN @@ -82,13 +92,13 @@ BEGIN LTEXT "&Update mode:",IDC_STATIC_COMPRESS_UPDATE_MODE, g4x, 39, g4xs, 8 COMBOBOX IDC_COMPRESS_COMBO_UPDATE_MODE, g4x, 51, g4xs, 80, MY_COMBO - GROUPBOX "Options",IDC_STATIC_COMPRESS_OPTIONS, g4x, yOpt, g4xs, 48 + GROUPBOX "Options",IDC_STATIC_COMPRESS_OPTIONS, g4x, yOpt, g4xs, GROUP_Y_SIZE CONTROL "Create SF&X archive",IDC_COMPRESS_SFX, MY_CHECKBOX, g4x2, yOpt + 14, g4xs2, 10 CONTROL "Compress shared files",IDC_COMPRESS_SHARED, MY_CHECKBOX, g4x2, yOpt + 30, g4xs2, 10 - GROUPBOX "Encryption",IDC_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, 127 + GROUPBOX "Encryption", IDC_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, GROUP_Y_SIZE_ENCRYPT LTEXT "Enter password:",IDC_STATIC_COMPRESS_PASSWORD1, g4x2, yPsw + 14, g4xs2, 8 EDITTEXT IDC_COMPRESS_EDIT_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index 94556639..64ae445e 100755 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -352,4 +352,3 @@ void CExtractDialog::OnHelp() CModalDialog::OnHelp(); } #endif - diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc index db8a5b24..ec4c20c2 100755 --- a/CPP/7zip/UI/GUI/ExtractDialog.rc +++ b/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -18,6 +18,13 @@ #define g2xs (xc - g1xs - gSpace) #define g2xs2 (g2xs - m - m) +#undef GROUP_Y_SIZE +#ifdef UNDER_CE +#define GROUP_Y_SIZE 8 +#else +#define GROUP_Y_SIZE 56 +#endif + IDD_DIALOG_EXTRACT MY_DIALOG CAPTION "Extract" BEGIN @@ -31,11 +38,7 @@ BEGIN LTEXT "Overwrite mode:", IDC_EXTRACT_OVERWRITE_MODE, m, m + 68, g1xs, 8 COMBOBOX IDC_EXTRACT_COMBO_OVERWRITE_MODE, m, m + 80, g1xs, 140, MY_COMBO - #ifdef UNDER_CE - LTEXT "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 8 - #else - GROUPBOX "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, 56 - #endif + GROUPBOX "Password", IDC_EXTRACT_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE EDITTEXT IDC_EXTRACT_EDIT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Show Password", IDC_EXTRACT_CHECK_SHOW_PASSWORD, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index a976833c..9d39bffd 100755 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -8,6 +8,7 @@ #include "Windows/Error.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" +#include "Windows/FileName.h" #include "Windows/Thread.h" #include "../FileManager/ExtractCallback.h" @@ -128,7 +129,7 @@ HRESULT ExtractGUI( if (!options.TestMode) { - UString outputDir = options.OutputDir; + FString outputDir = options.OutputDir; #ifndef UNDER_CE if (outputDir.IsEmpty()) NFile::NDirectory::MyGetCurrentDirectory(outputDir); @@ -136,20 +137,22 @@ HRESULT ExtractGUI( if (showDialog) { CExtractDialog dialog; - if (!NFile::NDirectory::MyGetFullPathName(outputDir, dialog.DirectoryPath)) + FString outputDirFull; + if (!NFile::NDirectory::MyGetFullPathName(outputDir, outputDirFull)) { ShowErrorMessage(kIncorrectOutDir); messageWasDisplayed = true; return E_FAIL; } - NFile::NName::NormalizeDirPathPrefix(dialog.DirectoryPath); + NFile::NName::NormalizeDirPathPrefix(outputDirFull); + dialog.DirectoryPath = fs2us(outputDirFull); // dialog.OverwriteMode = options.OverwriteMode; // dialog.PathMode = options.PathMode; if (dialog.Create(hwndParent) != IDOK) return E_ABORT; - outputDir = dialog.DirectoryPath; + outputDir = us2fs(dialog.DirectoryPath); options.OverwriteMode = dialog.OverwriteMode; options.PathMode = dialog.PathMode; #ifndef _SFX diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 377c7841..0a40b58e 100755 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -121,7 +121,7 @@ static int Main2() #ifdef EXTERNAL_CODECS codecs, &externalCodecs, #endif - options.NumThreads, options.DictionarySize); + options.Properties); if (res != S_OK) throw CSystemException(res); } @@ -146,7 +146,7 @@ static int Main2() eo.TestMode = options.Command.IsTestMode(); eo.CalcCrc = options.CalcCrc; #if !defined(_7ZIP_ST) && !defined(_SFX) - eo.Properties = options.ExtractProperties; + eo.Properties = options.Properties; #endif bool messageWasDisplayed = false; @@ -280,4 +280,3 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, return NExitCode::kFatalError; } } - diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index d54e944f..382f592e 100755 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -585,6 +585,14 @@ SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index 7ee74fc8..ec56492f 100755 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -10,6 +10,7 @@ #include "Windows/Error.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" #include "Windows/Thread.h" #include "../Common/WorkDir.h" @@ -17,7 +18,6 @@ #include "../Explorer/MyMessages.h" #include "../FileManager/LangUtils.h" -#include "../FileManager/ProgramLocation.h" #include "../FileManager/StringUtils.h" #include "../FileManager/resourceGui.h" @@ -29,7 +29,7 @@ using namespace NWindows; using namespace NFile; -static const wchar_t *kDefaultSfxModule = L"7z.sfx"; +static CFSTR kDefaultSfxModule = FTEXT("7z.sfx"); static const wchar_t *kSFXExtension = L"exe"; extern void AddMessageToString(UString &dest, const UString &src); @@ -52,8 +52,8 @@ HRESULT CThreadUpdating::ProcessVirt() HRESULT res = UpdateArchive(codecs, *WildcardCensor, *Options, ei, UpdateCallbackGUI, UpdateCallbackGUI); ErrorMessage = ei.Message; - ErrorPath1 = ei.FileName; - ErrorPath2 = ei.FileName2; + SetErrorPath1(ei.FileName); + SetErrorPath2(ei.FileName2); if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) return ei.SystemError; return res; @@ -197,7 +197,7 @@ static HRESULT ShowDialog( { if (options.Commands.Size() != 1) throw "It must be one command"; - UString currentDirPrefix; + FString currentDirPrefix; #ifndef UNDER_CE { if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix)) @@ -207,7 +207,7 @@ static HRESULT ShowDialog( #endif bool oneFile = false; - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; UString name; if (censor.Pairs.Size() > 0) { @@ -224,7 +224,7 @@ static HRESULT ShowDialog( name += WCHAR_PATH_SEPARATOR; name += item.PathParts[i]; } - if (fileInfo.Find(name)) + if (fileInfo.Find(us2fs(name))) { if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1) oneFile = !fileInfo.IsDir(); @@ -253,7 +253,7 @@ static HRESULT ShowDialog( // di.ArchiveName = options.ArchivePath.GetFinalPath(); di.ArchiveName = options.ArchivePath.GetPathWithoutExt(); - dialog.OriginalFileName = options.ArchivePath.Prefix + fileInfo.Name; + dialog.OriginalFileName = options.ArchivePath.Prefix + fs2us(fileInfo.Name); di.CurrentDirPrefix = currentDirPrefix; di.SFXMode = options.SfxMode; @@ -338,9 +338,10 @@ static HRESULT ShowDialog( options.WorkingDir.Empty(); if (workDirInfo.Mode != NWorkDir::NMode::kCurrent) { - UString fullPath; - NDirectory::MyGetFullPathName(di.ArchiveName, fullPath); - options.WorkingDir = GetWorkDir(workDirInfo, fullPath); + FString fullPath; + NDirectory::MyGetFullPathName(us2fs(di.ArchiveName), fullPath); + FString namePart; + options.WorkingDir = GetWorkDir(workDirInfo, fullPath, namePart); NDirectory::CreateComplexDirectory(options.WorkingDir); } return S_OK; @@ -362,9 +363,7 @@ HRESULT UpdateGUI( } if (options.SfxMode && options.SfxModule.IsEmpty()) { - UString folder; - if (!GetProgramFolderPath(folder)) - folder.Empty(); + FString folder = NWindows::NDLL::GetModuleDirPrefix(); options.SfxModule = folder + kDefaultSfxModule; } diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile index fdedb44a..cd2c2f55 100755 --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile @@ -6,7 +6,7 @@ CFLAGS = $(CFLAGS) -I ../../../ \ !IFDEF UNDER_CE LIBS = $(LIBS) ceshell.lib Commctrl.lib !ELSE -LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib +LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib gdi32.lib CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE -D_7ZIP_LARGE_PAGES !ENDIF @@ -63,6 +63,7 @@ WIN_CTRL_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\FilterCoder.obj \ + $O\MethodProps.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ diff --git a/CPP/Build.mak b/CPP/Build.mak index 9209a32e..b3465d44 100755 --- a/CPP/Build.mak +++ b/CPP/Build.mak @@ -64,6 +64,10 @@ CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF +!IFNDEF UNDER_CE +LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE +!ENDIF + !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp index b4893d65..7c629390 100755 --- a/CPP/Common/C_FileIO.cpp +++ b/CPP/Common/C_FileIO.cpp @@ -1,9 +1,13 @@ -// Common/C_FileIO.h +// Common/C_FileIO.cpp #include "C_FileIO.h" #include <fcntl.h> +#ifdef _WIN32 +#include <io.h> +#else #include <unistd.h> +#endif namespace NC { namespace NFile { diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h index 27aa5686..ff7a1a11 100755 --- a/CPP/Common/C_FileIO.h +++ b/CPP/Common/C_FileIO.h @@ -9,6 +9,10 @@ #include "Types.h" #include "MyWindows.h" +#ifdef _WIN32 +typedef size_t ssize_t; +#endif + namespace NC { namespace NFile { namespace NIO { diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp index 75dfed42..df4bbac0 100755 --- a/CPP/Common/Lang.cpp +++ b/CPP/Common/Lang.cpp @@ -48,7 +48,7 @@ static int CompareLangItems(void *const *elem1, void *const *elem2, void *) return MyCompare(langPair1.Value, langPair2.Value); } -bool CLang::Open(LPCWSTR fileName) +bool CLang::Open(CFSTR fileName) { _langPairs.Clear(); NWindows::NFile::NIO::CInFile file; diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h index cf978758..2ce53a0d 100755 --- a/CPP/Common/Lang.h +++ b/CPP/Common/Lang.h @@ -3,7 +3,6 @@ #ifndef __COMMON_LANG_H #define __COMMON_LANG_H -#include "MyVector.h" #include "MyString.h" #include "Types.h" @@ -17,7 +16,7 @@ class CLang { CObjectVector<CLangPair> _langPairs; public: - bool Open(LPCWSTR fileName); + bool Open(CFSTR fileName); void Clear() { _langPairs.Clear(); } int FindItem(UInt32 value) const; bool GetMessage(UInt32 value, UString &message) const; diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp index c1c682a2..f9bd18ed 100755 --- a/CPP/Common/ListFileUtils.cpp +++ b/CPP/Common/ListFileUtils.cpp @@ -9,15 +9,16 @@ #include "StringConvert.h" #include "UTFConvert.h" -static const char kQuoteChar = '\"'; +static const char kQuoteChar = '\"'; + static void RemoveQuote(UString &s) { if (s.Length() >= 2) - if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) + if (s[0] == kQuoteChar && s.Back() == kQuoteChar) s = s.Mid(1, s.Length() - 2); } -bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h index c58a8bd4..d43bfdfc 100755 --- a/CPP/Common/ListFileUtils.h +++ b/CPP/Common/ListFileUtils.h @@ -1,11 +1,11 @@ // Common/ListFileUtils.h -#ifndef __COMMON_LISTFILEUTILS_H -#define __COMMON_LISTFILEUTILS_H +#ifndef __COMMON_LIST_FILE_UTILS_H +#define __COMMON_LIST_FILE_UTILS_H #include "MyString.h" #include "Types.h" -bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index 3d1ce2b8..dc254eaf 100755 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -2,7 +2,9 @@ #include "StdAfx.h" -#ifndef _WIN32 +#ifdef _WIN32 +#include <windows.h> +#else #include <ctype.h> #endif @@ -12,10 +14,75 @@ #include "MyString.h" +const char* MyStringGetNextCharPointer(const char *p) +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return CharNextA(p); + #else + return p + 1; + #endif +} + +int FindCharPosInString(const char *s, char c) +{ + for (const char *p = s;;) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + p = MyStringGetNextCharPointer(p); + } +} + +int FindCharPosInString(const wchar_t *s, wchar_t c) +{ + for (const wchar_t *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + } +} #ifdef _WIN32 -#ifndef _UNICODE +#ifdef _UNICODE + +wchar_t MyCharUpper(wchar_t c) +{ + return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); +} + +/* +wchar_t MyCharLower(wchar_t c) +{ + return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); +} + +char MyCharLower(char c) +#ifdef UNDER_CE + { return (char)MyCharLower((wchar_t)c); } +#else + { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } +#endif +*/ + +wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } + +// for WinCE - FString - char +const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) +{ + return p - 1; +} + +#else + +const char * MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } +char * MyStringUpper(char *s) { return CharUpperA(s); } +char * MyStringLower(char *s) { return CharLowerA(s); } wchar_t MyCharUpper(wchar_t c) { @@ -62,7 +129,8 @@ wchar_t * MyStringUpper(wchar_t *s) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); - return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; } wchar_t * MyStringLower(wchar_t *s) @@ -74,57 +142,12 @@ wchar_t * MyStringLower(wchar_t *s) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); - return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; } #endif -/* -inline int ConvertCompareResult(int r) { return r - 2; } - -int MyStringCollate(const wchar_t *s1, const wchar_t *s2) -{ - int res = CompareStringW( - LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); - #ifdef _UNICODE - return ConvertCompareResult(res); - #else - if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return ConvertCompareResult(res); - return MyStringCollate(UnicodeStringToMultiByte(s1), - UnicodeStringToMultiByte(s2)); - #endif -} - -#ifndef UNDER_CE -int MyStringCollate(const char *s1, const char *s2) -{ - return ConvertCompareResult(CompareStringA( - LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); -} - -int MyStringCollateNoCase(const char *s1, const char *s2) -{ - return ConvertCompareResult(CompareStringA( - LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); -} -#endif - -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) -{ - int res = CompareStringW( - LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); - #ifdef _UNICODE - return ConvertCompareResult(res); - #else - if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return ConvertCompareResult(res); - return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), - UnicodeStringToMultiByte(s2)); - #endif -} -*/ - #else wchar_t MyCharUpper(wchar_t c) @@ -132,6 +155,15 @@ wchar_t MyCharUpper(wchar_t c) return toupper(c); } +wchar_t * MyStringUpper(wchar_t *s) +{ + if (s == 0) + return 0; + for (wchar_t *p = s; *p != 0; p++) + *p = MyCharUpper(*p); + return s; +} + /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { @@ -192,9 +224,45 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) } } -/* +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage); +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage); + int MyStringCompareNoCase(const char *s1, const char *s2) { - return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); + return MyStringCompareNoCase(MultiByteToUnicodeString(s1, CP_ACP), MultiByteToUnicodeString(s2, CP_ACP)); } -*/ + +static inline UINT GetCurrentCodePage() +{ + #if defined(UNDER_CE) || !defined(defined) + return CP_ACP; + #else + return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif +} + +#ifdef USE_UNICODE_FSTRING + +AString fs2fas(CFSTR s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +FString fas2fs(const AString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +#else + +UString fs2us(const FString &s) +{ + return MultiByteToUnicodeString((AString)s, GetCurrentCodePage()); +} + +FString us2fs(const wchar_t *s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +#endif diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index eb3c52dc..0312bac6 100755 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -5,6 +5,7 @@ #include <string.h> +#include "Types.h" #include "MyVector.h" template <class T> @@ -16,13 +17,14 @@ inline int MyStringLen(const T *s) } template <class T> -inline T * MyStringCopy(T *dest, const T *src) +inline void MyStringCopy(T *dest, const T *src) { - T *destStart = dest; while ((*dest++ = *src++) != 0); - return destStart; } +int FindCharPosInString(const char *s, char c); +int FindCharPosInString(const wchar_t *s, wchar_t c); + inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) @@ -32,77 +34,25 @@ inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } -#ifdef _WIN32 - -inline const char* MyStringGetNextCharPointer(const char *p) -{ - #ifdef UNDER_CE - return p + 1; - #else - return CharNextA(p); - #endif -} - -inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) - { return CharPrevA(base, p); } - -inline char MyCharUpper(char c) - { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } -#ifdef _UNICODE -inline wchar_t MyCharUpper(wchar_t c) - { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } -#else wchar_t MyCharUpper(wchar_t c); -#endif +// wchar_t MyCharLower(wchar_t c); -#ifdef _UNICODE -inline wchar_t MyCharLower(wchar_t c) - { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } -#else -wchar_t MyCharLower(wchar_t c); -#endif +char *MyStringUpper(char *s); +char *MyStringLower(char *s); -inline char MyCharLower(char c) -#ifdef UNDER_CE - { return (char)MyCharLower((wchar_t)c); } -#else - { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } -#endif +wchar_t *MyStringUpper(wchar_t *s); +wchar_t *MyStringLower(wchar_t *s); -inline char * MyStringUpper(char *s) { return CharUpperA(s); } -#ifdef _UNICODE -inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } -#else -wchar_t * MyStringUpper(wchar_t *s); -#endif - -inline char * MyStringLower(char *s) { return CharLowerA(s); } -#ifdef _UNICODE -inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } -#else -wchar_t * MyStringLower(wchar_t *s); -#endif - -#else // Standard-C -wchar_t MyCharUpper(wchar_t c); -#endif +const char* MyStringGetNextCharPointer(const char *p); +const char* MyStringGetPrevCharPointer(const char *base, const char *p); ////////////////////////////////////// // Compare -/* -#ifndef UNDER_CE -int MyStringCollate(const char *s1, const char *s2); -int MyStringCollateNoCase(const char *s1, const char *s2); -#endif -int MyStringCollate(const wchar_t *s1, const wchar_t *s2); -int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); -*/ - int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); -// int MyStringCompareNoCase(const char *s1, const char *s2); +int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> @@ -338,10 +288,8 @@ public: return Mid(_length - count, count); } - void MakeUpper() - { MyStringUpper(_chars); } - void MakeLower() - { MyStringLower(_chars); } + void MakeUpper() { MyStringUpper(_chars); } + void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } @@ -362,18 +310,11 @@ public: { return MyStringCollateNoCase(_chars, s._chars); } */ - int Find(T c) const { return Find(c, 0); } + int Find(T c) const { return FindCharPosInString(_chars, c); } int Find(T c, int startIndex) const { - const T *p = _chars + startIndex; - for (;;) - { - if (*p == c) - return (int)(p - _chars); - if (*p == 0) - return -1; - p = GetNextCharPointer(p); - } + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : pos + startIndex; } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const @@ -622,4 +563,47 @@ typedef CObjectVector<UString> UStringVector; typedef CObjectVector<CSysString> CSysStringVector; + +// ---------- FString ---------- + +#ifdef _WIN32 + #define USE_UNICODE_FSTRING +#endif + +#ifdef USE_UNICODE_FSTRING + + #define __FTEXT(quote) L##quote + + typedef wchar_t FChar; + typedef UString FString; + + #define fs2us(_x_) (_x_) + #define us2fs(_x_) (_x_) + FString fas2fs(const AString &s); + AString fs2fas(const FChar *s); + +#else + + #define __FTEXT(quote) quote + + typedef char FChar; + typedef AString FString; + + UString fs2us(const FString &s); + FString us2fs(const wchar_t *s); + #define fas2fs(_x_) (_x_) + #define fs2fas(_x_) (_x_) + +#endif + +#define FTEXT(quote) __FTEXT(quote) + +#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) +#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) +#define FCHAR_ANY_MASK FTEXT('*') +#define FSTRING_ANY_MASK FTEXT("*") +typedef const FChar *CFSTR; + +typedef CObjectVector<FString> FStringVector; + #endif diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp index 1283946c..f940fc8a 100755 --- a/CPP/Common/MyWindows.cpp +++ b/CPP/Common/MyWindows.cpp @@ -26,10 +26,13 @@ BSTR SysAllocStringByteLen(LPCSTR psz, UINT len) return 0; *(UINT *)p = len; BSTR bstr = (BSTR)((UINT *)p + 1); - memmove(bstr, psz, len); - Byte *pb = ((Byte *)bstr) + len; - for (int i = 0; i < sizeof(OLECHAR) * 2; i++) - pb[i] = 0; + if (psz) + { + memmove(bstr, psz, len); + Byte *pb = ((Byte *)bstr) + len; + for (unsigned i = 0; i < sizeof(OLECHAR) * 2; i++) + pb[i] = 0; + } return bstr; } diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index 8b0e5c06..780e1f5d 100755 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -1,7 +1,7 @@ // MyWindows.h -#ifndef __MYWINDOWS_H -#define __MYWINDOWS_H +#ifndef __MY_WINDOWS_H +#define __MY_WINDOWS_H #ifdef _WIN32 @@ -40,8 +40,8 @@ typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; -typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; -typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; +typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; @@ -57,7 +57,7 @@ typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; -}FILETIME; +} FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) @@ -179,6 +179,13 @@ typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +typedef struct tagSTATPROPSTG +{ + LPOLESTR lpwstrName; + PROPID propid; + VARTYPE vt; +} STATPROPSTG; + #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp index 9473766b..15474a42 100755 --- a/CPP/Common/StringToInt.cpp +++ b/CPP/Common/StringToInt.cpp @@ -88,3 +88,10 @@ Int64 ConvertStringToInt64(const char *s, const char **end) return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } + +Int64 ConvertStringToInt64(const wchar_t *s, const wchar_t **end) +{ + if (*s == L'-') + return -(Int64)ConvertStringToUInt64(s + 1, end); + return ConvertStringToUInt64(s, end); +} diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h index c0d860ef..cd99f17e 100755 --- a/CPP/Common/StringToInt.h +++ b/CPP/Common/StringToInt.h @@ -1,9 +1,8 @@ // Common/StringToInt.h -#ifndef __COMMON_STRINGTOINT_H -#define __COMMON_STRINGTOINT_H +#ifndef __COMMON_STRING_TO_INT_H +#define __COMMON_STRING_TO_INT_H -#include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); @@ -12,7 +11,6 @@ UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); +Int64 ConvertStringToInt64(const wchar_t *s, const wchar_t **end); #endif - - diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index 476ddebd..87d44971 100755 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -342,9 +342,9 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) bool forFile = true; bool forFolder = true; UString path2 = path; - if (IsCharDirLimiter(path[path.Length() - 1])) + if (IsCharDirLimiter(path.Back())) { - path2.Delete(path.Length() - 1); + path2.DeleteBack(); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp index 3cfa517a..2695ca54 100755 --- a/CPP/Windows/Control/Dialog.cpp +++ b/CPP/Windows/Control/Dialog.cpp @@ -2,10 +2,10 @@ #include "StdAfx.h" +#include "Windows/Control/Dialog.h" #ifndef _UNICODE -#include "Common/StringConvert.h" +#include "../../Common/StringConvert.h" #endif -#include "Windows/Control/Dialog.h" extern HINSTANCE g_hInstance; #ifndef _UNICODE @@ -17,17 +17,16 @@ namespace NControl { static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) { - CWindow dialogTmp(dialogHWND); + CWindow tempDialog(dialogHWND); if (message == WM_INITDIALOG) - dialogTmp.SetUserDataLongPtr(lParam); - CDialog *dialog = (CDialog *)(dialogTmp.GetUserDataLongPtr()); + tempDialog.SetUserDataLongPtr(lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); if (dialog == NULL) return FALSE; if (message == WM_INITDIALOG) dialog->Attach(dialogHWND); - try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } - catch(...) { return true; } + catch(...) { return TRUE; } } bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) @@ -68,7 +67,7 @@ bool CDialog::OnCommand(int code, int itemID, LPARAM lParam) bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */) { - switch(buttonID) + switch (buttonID) { case IDOK: OnOK(); break; case IDCANCEL: OnCancel(); break; diff --git a/CPP/Windows/Control/ListView.cpp b/CPP/Windows/Control/ListView.cpp index 53777bdb..255a17c5 100755 --- a/CPP/Windows/Control/ListView.cpp +++ b/CPP/Windows/Control/ListView.cpp @@ -4,6 +4,10 @@ #include "Windows/Control/ListView.h" +#ifndef _UNICODE +extern bool g_IsNT; +#endif + namespace NWindows { namespace NControl { @@ -93,4 +97,59 @@ int CListView::SetSubItem(int index, int subIndex, LPCWSTR text) #endif +static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow window(hwnd); + CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + #ifndef _UNICODE + if (g_IsNT) + return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); + else + #endif + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} + +void CListView2::SetWindowProc() +{ + SetUserDataLongPtr((LONG_PTR)this); + #ifndef _UNICODE + if (g_IsNT) + _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); + else + #endif + _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); +} + +/* +LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT res = CListView2::OnMessage(message, wParam, lParam); + if (message == WM_GETDLGCODE) + { + // when user presses RETURN, windows sends default (first) button command to parent dialog. + // we disable this: + MSG *msg = (MSG *)lParam; + WPARAM key = wParam; + bool change = false; + if (msg) + { + if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) + change = true; + } + else if (wParam == VK_RETURN) + change = true; + if (change) + res |= DLGC_WANTALLKEYS; + } + return res; +} +*/ + }} diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h index 1258ec93..bebcd9e2 100755 --- a/CPP/Windows/Control/ListView.h +++ b/CPP/Windows/Control/ListView.h @@ -18,9 +18,12 @@ public: HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance, LPVOID createParam); - #ifndef UNDER_CE - bool SetUnicodeFormat(bool fUnicode) { return BOOLToBool(ListView_SetUnicodeFormat(_window, BOOLToBool(fUnicode))); } - #endif + void SetUnicodeFormat() + { + #ifndef UNDER_CE + ListView_SetUnicodeFormat(_window, TRUE); + #endif + } bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); } bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); } @@ -65,8 +68,12 @@ public: { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); } void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); } + void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); } + void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); } + void SelectAll() { SetItemState_Selected(-1); } void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); } UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); } + bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; } bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); } @@ -104,6 +111,22 @@ public: bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); } }; +class CListView2: public CListView +{ + WNDPROC _origWindowProc; +public: + void SetWindowProc(); + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; + +/* +class CListView3: public CListView2 +{ +public: + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; +*/ + }} #endif diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp index 01724797..d7eaab17 100755 --- a/CPP/Windows/Control/PropertyPage.cpp +++ b/CPP/Windows/Control/PropertyPage.cpp @@ -15,50 +15,30 @@ extern bool g_IsNT; namespace NWindows { namespace NControl { -INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, - WPARAM wParam, LPARAM lParam) +static INT_PTR APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) { - CDialog tempDialog(dialogHWND); + CWindow tempDialog(dialogHWND); if (message == WM_INITDIALOG) tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam); CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (dialog == NULL) + return FALSE; if (message == WM_INITDIALOG) dialog->Attach(dialogHWND); - switch (message) - { - case WM_INITDIALOG: - return dialog->OnInit(); - case WM_COMMAND: - return dialog->OnCommand(wParam, lParam); - case WM_NOTIFY: - return dialog->OnNotify((UINT)wParam, (LPNMHDR) lParam); - } - if (dialog == NULL) - return false; - return dialog->OnMessage(message, wParam, lParam); + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } + catch(...) { return TRUE; } } bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam) { - switch(lParam->code) + switch (lParam->code) { - case PSN_APPLY: - SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); - break; - case PSN_KILLACTIVE: - SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); - break; - case PSN_SETACTIVE: - SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); - break; - case PSN_RESET: - OnReset(LPPSHNOTIFY(lParam)); - break; - case PSN_HELP: - OnNotifyHelp(LPPSHNOTIFY(lParam)); - break; - default: - return false; + case PSN_APPLY: SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); break; + case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); break; + case PSN_SETACTIVE: SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); break; + case PSN_RESET: OnReset(LPPSHNOTIFY(lParam)); break; + case PSN_HELP: OnNotifyHelp(LPPSHNOTIFY(lParam)); break; + default: return false; } return true; } @@ -90,7 +70,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare page.hInstance = g_hInstance; page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID); page.pszIcon = NULL; - page.pfnDlgProc = NWindows::NControl::ProperyPageProcedure; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; if (titles[i].IsEmpty()) page.pszTitle = NULL; @@ -111,7 +91,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare page.hInstance = g_hInstance; page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID); page.pszIcon = NULL; - page.pfnDlgProc = NWindows::NControl::ProperyPageProcedure; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; if (pageInfo.Title.IsEmpty()) page.pszTitle = NULL; diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp index 5afd72d9..81eec692 100755 --- a/CPP/Windows/DLL.cpp +++ b/CPP/Windows/DLL.cpp @@ -2,16 +2,14 @@ #include "StdAfx.h" -#ifndef _UNICODE -#include "../Common/StringConvert.h" -#endif - #include "DLL.h" #ifndef _UNICODE extern bool g_IsNT; #endif +extern HINSTANCE g_hInstance; + namespace NWindows { namespace NDLL { @@ -19,92 +17,91 @@ bool CLibrary::Free() { if (_module == 0) return true; - // MessageBox(0, TEXT(""), TEXT("Free"), 0); - // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } -bool CLibrary::LoadOperations(HMODULE newModule) +bool CLibrary::LoadEx(CFSTR path, DWORD flags) { - if (newModule == NULL) - return false; if (!Free()) return false; - _module = newModule; - return true; -} - -bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) -{ - // MessageBox(0, fileName, TEXT("LoadEx"), 0); - return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); -} - -bool CLibrary::Load(LPCTSTR fileName) -{ - // MessageBox(0, fileName, TEXT("Load"), 0); - // Sleep(5000); - // OutputDebugString(fileName); - // OutputDebugString(TEXT("\n")); - return LoadOperations(::LoadLibrary(fileName)); -} - -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } - -bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) -{ - if (g_IsNT) - return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); - return LoadEx(GetSysPath(fileName), flags); -} -bool CLibrary::Load(LPCWSTR fileName) -{ - if (g_IsNT) - return LoadOperations(::LoadLibraryW(fileName)); - return Load(GetSysPath(fileName)); + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); + } + else + #endif + { + _module = ::LoadLibraryExW(fs2us(path), NULL, flags); + } + return (_module != NULL); } -#endif -bool MyGetModuleFileName(HMODULE hModule, CSysString &result) +bool CLibrary::Load(CFSTR path) { - result.Empty(); - TCHAR fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); - if (size <= MAX_PATH && size != 0) + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) { - result = fullPath; - return true; + _module = ::LoadLibrary(fs2fas(path)); } - return false; + else + #endif + { + _module = ::LoadLibraryW(fs2us(path)); + } + return (_module != NULL); } -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result) +bool MyGetModuleFileName(FString &path) { - result.Empty(); - if (g_IsNT) + HMODULE hModule = g_hInstance; + path.Empty(); + #ifndef _UNICODE + if (!g_IsNT) { - wchar_t fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { - result = fullPath; + path = fas2fs(s); return true; } - return false; } - CSysString resultSys; - if (!MyGetModuleFileName(hModule, resultSys)) - return false; - result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); - return true; + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = us2fs(s); + return true; + } + } + return false; +} + +#ifndef _SFX + +FString GetModuleDirPrefix() +{ + FString s; + if (NDLL::MyGetModuleFileName(s)) + { + int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos >= 0) + return s.Left(pos + 1); + } + return FTEXT(".") FSTRING_PATH_SEPARATOR; } + #endif }} diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h index 4a253b32..9f0f5cd7 100755 --- a/CPP/Windows/DLL.h +++ b/CPP/Windows/DLL.h @@ -9,15 +9,13 @@ namespace NWindows { namespace NDLL { #ifdef UNDER_CE -#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName) #else -#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName) #endif class CLibrary { - bool LoadOperations(HMODULE newModule); -protected: HMODULE _module; public: CLibrary(): _module(NULL) {}; @@ -40,19 +38,14 @@ public: } bool Free(); - bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCTSTR fileName); - #ifndef _UNICODE - bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCWSTR fileName); - #endif + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); + bool Load(CFSTR path); FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; -bool MyGetModuleFileName(HMODULE hModule, CSysString &result); -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result); -#endif +bool MyGetModuleFileName(FString &path); + +FString GetModuleDirPrefix(); }} diff --git a/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp index 7b18c29c..c02e3b9e 100755 --- a/CPP/Windows/Error.cpp +++ b/CPP/Windows/Error.cpp @@ -14,37 +14,47 @@ extern bool g_IsNT; namespace NWindows { namespace NError { -bool MyFormatMessage(DWORD messageID, CSysString &message) +static bool MyFormatMessage(DWORD errorCode, UString &message) { LPVOID msgBuf; - if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) - return false; - message = (LPCTSTR)msgBuf; + #ifndef _UNICODE + if (!g_IsNT) + { + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) + return false; + message = GetUnicodeString((LPCTSTR)msgBuf); + } + else + #endif + { + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) + return false; + message = (LPCWSTR)msgBuf; + } ::LocalFree(msgBuf); return true; } -#ifndef _UNICODE -bool MyFormatMessage(DWORD messageID, UString &message) +UString MyFormatMessageW(DWORD errorCode) { - if (g_IsNT) + UString message; + if (!MyFormatMessage(errorCode, message)) { - LPVOID msgBuf; - if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) - return false; - message = (LPCWSTR)msgBuf; - ::LocalFree(msgBuf); - return true; + wchar_t s[16]; + for (int i = 0; i < 8; i++) + { + int t = errorCode & 0xF; + errorCode >>= 4; + s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = '\0'; + message = (UString)L"Error #" + s; } - CSysString messageSys; - bool result = MyFormatMessage(messageID, messageSys); - message = GetUnicodeString(messageSys); - return result; + return message; } -#endif }} diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h index 05b5cd0e..b7da3ca5 100755 --- a/CPP/Windows/Error.h +++ b/CPP/Windows/Error.h @@ -8,25 +8,7 @@ namespace NWindows { namespace NError { -bool MyFormatMessage(DWORD messageID, CSysString &message); -inline CSysString MyFormatMessage(DWORD messageID) -{ - CSysString message; - MyFormatMessage(messageID, message); - return message; -} -#ifdef _UNICODE -inline UString MyFormatMessageW(DWORD messageID) - { return MyFormatMessage(messageID); } -#else -bool MyFormatMessage(DWORD messageID, UString &message); -inline UString MyFormatMessageW(DWORD messageID) -{ - UString message; - MyFormatMessage(messageID, message); - return message; -} -#endif +UString MyFormatMessageW(DWORD errorCode); }} diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 85794603..88215faa 100755 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -17,78 +17,64 @@ extern bool g_IsNT; namespace NWindows { namespace NFile { -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR fileName, UString &res); -bool GetLongPath(LPCWSTR fileName, UString &res); +bool GetLongPathBase(CFSTR fileName, UString &res); +bool GetLongPath(CFSTR fileName, UString &res); #endif namespace NDirectory { -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -static UString GetUnicodePath(const CSysString &sysPath) - { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } -static CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } -#endif - #ifndef UNDER_CE -bool MyGetWindowsDirectory(CSysString &path) +bool MyGetWindowsDirectory(FString &path) { - UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); -} - -bool MyGetSystemDirectory(CSysString &path) -{ - UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } return (needLength > 0 && needLength <= MAX_PATH); } -#endif -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path) +bool MyGetSystemDirectory(FString &path) { - if (g_IsNT) + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) { - UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); } - CSysString sysPath; - if (!MyGetWindowsDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} - -bool MyGetSystemDirectory(UString &path) -{ - if (g_IsNT) + else + #endif { - UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); } - CSysString sysPath; - if (!MyGetSystemDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; + return (needLength > 0 && needLength <= MAX_PATH); } #endif -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) @@ -97,17 +83,15 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return false; } #endif - HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, + HANDLE hDir = ::CreateFileW(fs2us(fileName), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) - hDir = ::CreateFileW(longPath, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif @@ -120,219 +104,122 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return res; } -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) -{ - if (::SetFileAttributes(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); - #endif - return false; -} - -bool MyRemoveDirectory(LPCTSTR pathName) -{ - if (::RemoveDirectory(pathName)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); - #endif - return false; -} - #ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) +bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2) { - if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) + if (!GetLongPathBase(s1, d1) || + !GetLongPathBase(s2, d2)) return false; - if (d1.IsEmpty() && d2.IsEmpty()) return false; - if (d1.IsEmpty()) d1 = s1; - if (d2.IsEmpty()) d2 = s2; + if (d1.IsEmpty() && d2.IsEmpty()) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); return true; } #endif -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) -{ - if (::MoveFile(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH2 - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); - #endif - return false; -} - -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) -{ - if (!g_IsNT) - return MySetFileAttributes(GetSysPath(fileName), fileAttributes); - if (::SetFileAttributesW(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); - #endif - return false; -} - - -bool MyRemoveDirectory(LPCWSTR pathName) +bool MySetFileAttributes(CFSTR fileName, DWORD fileAttributes) { + #ifndef _UNICODE if (!g_IsNT) - return MyRemoveDirectory(GetSysPath(pathName)); - if (::RemoveDirectoryW(pathName)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); + { + if (::SetFileAttributes(fs2fas(fileName), fileAttributes)) + return true; + } + else #endif + { + if (::SetFileAttributesW(fs2us(fileName), fileAttributes)) + return true; + #ifdef WIN_LONG_PATH + UString longPath; + if (GetLongPath(fileName, longPath)) + return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + #endif + } return false; } -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) +bool MyRemoveDirectory(CFSTR path) { + #ifndef _UNICODE if (!g_IsNT) - return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); - if (::MoveFileW(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); + { + if (::RemoveDirectory(fs2fas(path))) + return true; + } + else #endif - return false; -} -#endif - -bool MyCreateDirectory(LPCTSTR pathName) -{ - if (::CreateDirectory(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH2 - if (::GetLastError() != ERROR_ALREADY_EXISTS) { + if (::RemoveDirectoryW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + if (GetLongPath(path, longPath)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + #endif } - #endif return false; } -#ifndef _UNICODE -bool MyCreateDirectory(LPCWSTR pathName) +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName) { + #ifndef _UNICODE if (!g_IsNT) - return MyCreateDirectory(GetSysPath(pathName)); - if (::CreateDirectoryW(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH - if (::GetLastError() != ERROR_ALREADY_EXISTS) { - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + if (::MoveFile(fs2fas(existFileName), fs2fas(newFileName))) + return true; } + else #endif - return false; -} -#endif - -/* -bool CreateComplexDirectory(LPCTSTR pathName) -{ - NName::CParsedPath path; - path.ParsePath(pathName); - CSysString fullPath = path.Prefix; - DWORD errorCode = ERROR_SUCCESS; - for (int i = 0; i < path.PathParts.Size(); i++) - { - const CSysString &string = path.PathParts[i]; - if (string.IsEmpty()) - { - if (i != path.PathParts.Size() - 1) - return false; + { + if (::MoveFileW(fs2us(existFileName), fs2us(newFileName))) return true; - } - fullPath += path.PathParts[i]; - if (!MyCreateDirectory(fullPath)) - { - DWORD errorCode = GetLastError(); - if (errorCode != ERROR_ALREADY_EXISTS) - return false; - } - fullPath += NName::kDirDelimiter; + #ifdef WIN_LONG_PATH + UString d1, d2; + if (GetLongPaths(existFileName, newFileName, d1, d2)) + return BOOLToBool(::MoveFileW(d1, d2)); + #endif } - return true; + return false; } -*/ -bool CreateComplexDirectory(LPCTSTR _aPathName) +bool MyCreateDirectory(CFSTR path) { - CSysString pathName = _aPathName; - int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - if (pos > 0 && pos == pathName.Length() - 1) + #ifndef _UNICODE + if (!g_IsNT) { - if (pathName.Length() == 3 && pathName[1] == ':') - return true; // Disk folder; - pathName.Delete(pos); + if (::CreateDirectory(fs2fas(path), NULL)) + return true; } - CSysString pathName2 = pathName; - pos = pathName.Length(); - for (;;) + else + #endif { - if (MyCreateDirectory(pathName)) - break; - if (::GetLastError() == ERROR_ALREADY_EXISTS) + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; + #ifdef WIN_LONG_PATH + if (::GetLastError() != ERROR_ALREADY_EXISTS) { - NFind::CFileInfo fileInfo; - if (!fileInfo.Find(pathName)) // For network folders - return true; - if (!fileInfo.IsDir()) - return false; - break; + UString longPath; + if (GetLongPath(path, longPath)) + return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } - pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - if (pos < 0 || pos == 0) - return false; - if (pathName[pos - 1] == ':') - return false; - pathName = pathName.Left(pos); - } - pathName = pathName2; - while (pos < pathName.Length()) - { - pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); - if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) - return false; + #endif } - return true; + return false; } -#ifndef _UNICODE - -bool CreateComplexDirectory(LPCWSTR _aPathName) +bool CreateComplexDirectory(CFSTR _aPathName) { - UString pathName = _aPathName; - int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + FString pathName = _aPathName; + int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } - UString pathName2 = pathName; + FString pathName2 = pathName; pos = pathName.Length(); for (;;) { @@ -340,14 +227,14 @@ bool CreateComplexDirectory(LPCWSTR _aPathName) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } - pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') @@ -357,7 +244,7 @@ bool CreateComplexDirectory(LPCWSTR _aPathName) pathName = pathName2; while (pos < pathName.Length()) { - pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); + pos = pathName.Find(FCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) @@ -366,75 +253,42 @@ bool CreateComplexDirectory(LPCWSTR _aPathName) return true; } -#endif - -bool DeleteFileAlways(LPCTSTR name) +bool DeleteFileAlways(CFSTR name) { if (!MySetFileAttributes(name, 0)) return false; - if (::DeleteFile(name)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); - #endif - return false; -} - -#ifndef _UNICODE -bool DeleteFileAlways(LPCWSTR name) -{ + #ifndef _UNICODE if (!g_IsNT) - return DeleteFileAlways(GetSysPath(name)); - if (!MySetFileAttributes(name, 0)) - return false; - if (::DeleteFileW(name)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); + { + if (::DeleteFile(fs2fas(name))) + return true; + } + else #endif - return false; -} -#endif - -static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) -{ - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} - -bool RemoveDirectoryWithSubItems(const CSysString &path) -{ - NFind::CFileInfo fileInfo; - CSysString pathPrefix = path + NName::kDirDelimiter; { - NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) - return false; + if (::DeleteFileW(fs2us(name))) + return true; + #ifdef WIN_LONG_PATH + UString longPath; + if (GetLongPath(name, longPath)) + return BOOLToBool(::DeleteFileW(longPath)); + #endif } - if (!MySetFileAttributes(path, 0)) - return false; - return MyRemoveDirectory(path); + return false; } -#ifndef _UNICODE -static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) +static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } -bool RemoveDirectoryWithSubItems(const UString &path) +bool RemoveDirectoryWithSubItems(const FString &path) { - NFind::CFileInfoW fileInfo; - UString pathPrefix = path + UString(NName::kDirDelimiter); + NFind::CFileInfo fileInfo; + FString pathPrefix = path + FCHAR_PATH_SEPARATOR; { - NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); + NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; @@ -443,74 +297,40 @@ bool RemoveDirectoryWithSubItems(const UString &path) return false; return MyRemoveDirectory(path); } -#endif - -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Left(index); - return true; -} - -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; -} #ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath) -{ - resultPath = fileName; - return true; -} -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +bool MyGetFullPathName(CFSTR fileName, FString &resFullPath) { - resultPath = fileName; - // change it - fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR); - fileNamePartStartIndex++; + resFullPath = fileName; return true; } #else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) -{ - DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - shortPath.ReleaseBuffer(); - return (needLength > 0 && needLength < MAX_PATH); -} - #ifdef WIN_LONG_PATH -static UString GetLastPart(LPCWSTR path) +static FString GetLastPart(CFSTR path) { - int i = (int)wcslen(path); + int i = MyStringLen(path); for (; i > 0; i--) { - WCHAR c = path[i - 1]; - if (c == WCHAR_PATH_SEPARATOR || c == '/') + FChar c = path[i - 1]; + if (c == FCHAR_PATH_SEPARATOR || c == '/') break; } return path + i; } -static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) +static void AddTrailingDots(CFSTR oldPath, FString &newPath) { - int len = (int)wcslen(oldPath); + int len = MyStringLen(oldPath); int i; for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); if (i == 0 || i == len) return; - UString oldName = GetLastPart(oldPath); - UString newName = GetLastPart(newPath); + FString oldName = GetLastPart(oldPath); + FString newName = GetLastPart(newPath); int nonDotsLen = oldName.Length() - (len - i); if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) return; @@ -520,390 +340,248 @@ static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) #endif -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) +bool MyGetFullPathName(CFSTR fileName, FString &resFullPath) { - resultPath.Empty(); - LPTSTR fileNamePointer = 0; - LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); - DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength == 0) - return false; - if (needLength >= MAX_PATH) + resFullPath.Empty(); + #ifndef _UNICODE + if (!g_IsNT) { - #ifdef WIN_LONG_PATH2 - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + LPTSTR fileNamePointer = 0; + DWORD needLength = ::GetFullPathName(fs2fas(fileName), MAX_PATH + 1, s, &fileNamePointer); + if (needLength == 0 || needLength > MAX_PATH) return false; + resFullPath = fas2fs(s); + return true; } - if (fileNamePointer == 0) - fileNamePartStartIndex = lstrlen(fileName); else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); - #ifdef _UNICODE - #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); #endif - #endif - return true; -} - -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) -{ - resultPath.Empty(); - if (g_IsNT) { LPWSTR fileNamePointer = 0; - LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); - DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD needLength = ::GetFullPathNameW(fs2us(fileName), MAX_PATH + 1, s, &fileNamePointer); if (needLength == 0) return false; - if (needLength >= MAX_PATH) + if (needLength <= MAX_PATH) { - #ifdef WIN_LONG_PATH - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif - return false; + resFullPath = us2fs(s); + return true; } - if (fileNamePointer == 0) - fileNamePartStartIndex = MyStringLen(fileName); - else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); + needLength++; + UString temp; + LPWSTR buffer = temp.GetBuffer(needLength + 1); + buffer[0] = 0; + DWORD needLength2 = ::GetFullPathNameW(fs2us(fileName), needLength, buffer, &fileNamePointer); + temp.ReleaseBuffer(); + if (needLength2 > 0 && needLength2 <= needLength) + { + resFullPath = us2fs(temp); + AddTrailingDots(fileName, resFullPath); + return true; + } #endif + return false; + } +} + +bool MySetCurrentDirectory(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); } else + #endif { - CSysString sysPath; - if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) - return false; - UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); - UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); - fileNamePartStartIndex = resultPath1.Length(); - resultPath = resultPath1 + resultPath2; + return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); } - return true; } -#endif - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) +bool MyGetCurrentDirectory(FString &path) { - int index; - return MyGetFullPathName(fileName, path, index); + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &path) -{ - int index; - return MyGetFullPathName(fileName, path, index); -} #endif -#ifndef _UNICODE -bool GetOnlyName(LPCWSTR fileName, UString &resultName) +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; + bool res = MyGetFullPathName(path, resFileName); + if (!res) + resFileName = path; + int pos = resFileName.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos >= 0) + { + resDirPrefix = resFileName.Left(pos + 1); + resFileName = resFileName.Mid(pos + 1); + } + return res; } -#endif -#ifndef _UNICODE -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) { - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Left(index); - return true; + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); } -#endif -bool MyGetCurrentDirectory(CSysString &path) +bool MyGetTempPath(FString &path) { - DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPath(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPathW(MAX_PATH + 1, s);; + path = us2fs(s); + } return (needLength > 0 && needLength <= MAX_PATH); } -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path) +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) { - if (g_IsNT) - return BOOLToBool(::SetCurrentDirectoryW(path)); - return MySetCurrentDirectory(GetSysPath(path)); -} -bool MyGetCurrentDirectory(UString &path) -{ - if (g_IsNT) + UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (unsigned i = 0; i < 100; i++) { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + path = prefix; + if (addRandom) + { + FChar s[16]; + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += FChar('.'); + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += FTEXT(".tmp"); + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (MyCreateDirectory(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; } - CSysString sysPath; - if (!MyGetCurrentDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} -#endif - -bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, - CSysString &resultPath, UINT32 &filePart) -{ - LPTSTR filePartPointer; - DWORD value = ::SearchPath(path, fileName, extension, - MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); - filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); - resultPath.ReleaseBuffer(); - return (value > 0 && value <= MAX_PATH); + path.Empty(); + return false; } -#endif -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, - UString &resultPath, UINT32 &filePart) +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { - if (g_IsNT) - { - LPWSTR filePartPointer = 0; - DWORD value = ::SearchPathW(path, fileName, extension, - MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); - filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); - resultPath.ReleaseBuffer(); - return (value > 0 && value <= MAX_PATH); - } - - CSysString sysPath; - if (!MySearchPath( - path != 0 ? (LPCTSTR)GetSysPath(path): 0, - fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, - extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, - sysPath, filePart)) + if (!Remove()) return false; - UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); - UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); - filePart = resultPath1.Length(); - resultPath = resultPath1 + resultPath2; - return true; -} -#endif - -bool MyGetTempPath(CSysString &path) -{ - DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); -} - -#ifndef _UNICODE -bool MyGetTempPath(UString &path) -{ - path.Empty(); - if (g_IsNT) - { - DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); - } - CSysString sysPath; - if (!MyGetTempPath(sysPath)) + if (!CreateTempFile(prefix, false, _path, outFile)) return false; - path = GetUnicodePath(sysPath); + _mustBeDeleted = true; return true; } -#endif - -UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) -{ - UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return number; -} - -#ifndef _UNICODE -UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) -{ - if (g_IsNT) - { - UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); - path.ReleaseBuffer(); - return number; - } - CSysString sysPath; - UINT number = MyGetTempFileName( - dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, - prefix ? (LPCTSTR)GetSysPath(prefix): 0, - sysPath); - path = GetUnicodePath(sysPath); - return number; -} -#endif - -UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) -{ - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; -} -bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) { - CSysString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - #ifdef UNDER_CE - return false; - #else - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) return false; - return (Create(tempPath, prefix, resultPath) != 0); - #endif + _mustBeDeleted = true; + return true; } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !DeleteFileAlways(_path); return !_mustBeDeleted; } -#ifndef _UNICODE - -UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; + if (deleteDestBefore) + if (NFind::DoesFileExist(name)) + if (!DeleteFileAlways(name)) + return false; + DisableDeleting(); + return MyMoveFile(_path, name); } -bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) +bool CTempDir::Create(CFSTR prefix) { - UString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) return false; - return (Create(tempPath, prefix, resultPath) != 0); + _mustBeDeleted = true; + return true; } -bool CTempFileW::Remove() +bool CTempDir::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !RemoveDirectoryWithSubItems(_path); return !_mustBeDeleted; } -#endif - -bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) -{ - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFile tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(dirName)) - continue; - if (MyCreateDirectory(dirName)) - return true; - if (::GetLastError() != ERROR_ALREADY_EXISTS) - return false; - } -} - -bool CTempDirectory::Create(LPCTSTR prefix) -{ - Remove(); - return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); -} - -#ifndef _UNICODE - -bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) -{ - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFileW tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(dirName)) - continue; - if (MyCreateDirectory(dirName)) - return true; - if (::GetLastError() != ERROR_ALREADY_EXISTS) - return false; - } -} - -bool CTempDirectoryW::Create(LPCWSTR prefix) -{ - Remove(); - return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); -} - -#endif - }}} diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 04542d87..e43c19bd 100755 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h @@ -1,176 +1,71 @@ // Windows/FileDir.h -#ifndef __WINDOWS_FILEDIR_H -#define __WINDOWS_FILEDIR_H +#ifndef __WINDOWS_FILE_DIR_H +#define __WINDOWS_FILE_DIR_H #include "../Common/MyString.h" -#include "Defs.h" +#include "FileIO.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); +bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2); #endif -bool MyGetWindowsDirectory(CSysString &path); -bool MyGetSystemDirectory(CSysString &path); -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path); -bool MyGetSystemDirectory(UString &path); -#endif +bool MyGetWindowsDirectory(FString &path); +bool MyGetSystemDirectory(FString &path); -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +bool MySetFileAttributes(CFSTR fileName, DWORD fileAttributes); +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); +bool MyRemoveDirectory(CFSTR path); +bool MyCreateDirectory(CFSTR path); +bool CreateComplexDirectory(CFSTR path); +bool DeleteFileAlways(CFSTR name); +bool RemoveDirectoryWithSubItems(const FString &path); -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); -bool MyRemoveDirectory(LPCTSTR pathName); -bool MyCreateDirectory(LPCTSTR pathName); -bool CreateComplexDirectory(LPCTSTR pathName); -bool DeleteFileAlways(LPCTSTR name); -bool RemoveDirectoryWithSubItems(const CSysString &path); +bool MyGetFullPathName(CFSTR path, FString &resFullPath); +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); -bool MyRemoveDirectory(LPCWSTR pathName); -bool MyCreateDirectory(LPCWSTR pathName); -bool CreateComplexDirectory(LPCWSTR pathName); -bool DeleteFileAlways(LPCWSTR name); -bool RemoveDirectoryWithSubItems(const UString &path); -#endif +#ifndef UNDER_CE -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); -#ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); -#else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); +bool MySetCurrentDirectory(CFSTR path); +bool MyGetCurrentDirectory(FString &resultPath); -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, - int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool GetOnlyName(LPCWSTR fileName, UString &resultName); -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif -inline bool MySetCurrentDirectory(LPCTSTR path) - { return BOOLToBool(::SetCurrentDirectory(path)); } -bool MyGetCurrentDirectory(CSysString &resultPath); -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path); -bool MyGetCurrentDirectory(UString &resultPath); -#endif - -bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); -#endif - -inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} - -#ifndef _UNICODE -inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} -#endif - -#endif - -bool MyGetTempPath(CSysString &resultPath); -#ifndef _UNICODE -bool MyGetTempPath(UString &resultPath); -#endif - -UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); -#ifndef _UNICODE -UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); -#endif +bool MyGetTempPath(FString &resultPath); class CTempFile { bool _mustBeDeleted; - CSysString _fileName; + FString _path; + void DisableDeleting() { _mustBeDeleted = false; } public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } - void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); - bool Create(LPCTSTR prefix, CSysString &resultPath); + const FString &GetPath() const { return _path; } + bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix + bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); bool Remove(); + bool MoveTo(CFSTR name, bool deleteDestBefore); }; -#ifdef _UNICODE -typedef CTempFile CTempFileW; -#else -class CTempFileW +class CTempDir { bool _mustBeDeleted; - UString _fileName; + FString _path; public: - CTempFileW(): _mustBeDeleted(false) {} - ~CTempFileW() { Remove(); } + CTempDir(): _mustBeDeleted(false) {} + ~CTempDir() { Remove(); } + const FString &GetPath() const { return _path; } void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); - bool Create(LPCWSTR prefix, UString &resultPath); + bool Create(CFSTR namePrefix) ; bool Remove(); }; -#endif - -bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); - -class CTempDirectory -{ - bool _mustBeDeleted; - CSysString _tempDir; -public: - const CSysString &GetPath() const { return _tempDir; } - CTempDirectory(): _mustBeDeleted(false) {} - ~CTempDirectory() { Remove(); } - bool Create(LPCTSTR prefix) ; - bool Remove() - { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); - } - void DisableDeleting() { _mustBeDeleted = false; } -}; - -#ifdef _UNICODE -typedef CTempDirectory CTempDirectoryW; -#else -class CTempDirectoryW -{ - bool _mustBeDeleted; - UString _tempDir; -public: - const UString &GetPath() const { return _tempDir; } - CTempDirectoryW(): _mustBeDeleted(false) {} - ~CTempDirectoryW() { Remove(); } - bool Create(LPCWSTR prefix) ; - bool Remove() - { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); - } - void DisableDeleting() { _mustBeDeleted = false; } -}; -#endif }}} diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index e3358f90..081bd9bc 100755 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -16,41 +16,23 @@ namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n); -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n); -#endif +bool IsDeviceName(CFSTR n); #endif -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 +#if defined(WIN_LONG_PATH) +bool GetLongPath(CFSTR fileName, UString &res); #endif -bool GetLongPath(LPCWSTR fileName, UString &res); - namespace NFind { -static const TCHAR kDot = TEXT('.'); - bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; - if (Name[0] != kDot) - return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); -} - -#ifndef _UNICODE -bool CFileInfoW::IsDots() const -{ - if (!IsDir() || Name.IsEmpty()) - return false; - if (Name[0] != kDot) + if (Name[0] != FTEXT('.')) return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); + return Name.Length() == 1 || (Name.Length() == 2 && Name[1] == FTEXT('.')); } -#endif #define WIN_FD_TO_MY_FI(fi, fd) \ fi.Attrib = fd.dwFileAttributes; \ @@ -68,26 +50,20 @@ bool CFileInfoW::IsDots() const #endif */ -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; + fi.Name = us2fs(fd.cFileName); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) -{ - WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; -} - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) +static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); + fi.Name = fas2fs(fd.cFileName); } #endif @@ -104,36 +80,24 @@ bool CFindFile::Close() return true; } - -bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi) +bool CFindFile::FindFirst(CFSTR wildcard, CFileInfo &fi) { if (!Close()) return false; - WIN32_FIND_DATA fd; - _handle = ::FindFirstFile(wildcard, &fd); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) + #ifndef _UNICODE + if (!g_IsNT) { - UString longPath; - if (GetLongPath(wildcard, longPath)) - _handle = ::FindFirstFileW(longPath, &fd); + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(fs2fas(wildcard), &fd); + if (_handle == INVALID_HANDLE_VALUE) + return false; + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } + else #endif - if (_handle == INVALID_HANDLE_VALUE) - return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return true; -} - -#ifndef _UNICODE -bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) -{ - if (!Close()) - return false; - if (g_IsNT) { WIN32_FIND_DATAW fd; - _handle = ::FindFirstFileW(wildcard, &fd); + _handle = ::FindFirstFileW(fs2us(wildcard), &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { @@ -142,50 +106,33 @@ bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) _handle = ::FindFirstFileW(longPath, &fd); } #endif - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - } - else - { - WIN32_FIND_DATAA fd; - _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, - GetCurrentCodePage()), &fd); - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + if (_handle == INVALID_HANDLE_VALUE) + return false; + ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } - return (_handle != INVALID_HANDLE_VALUE); + return true; } -#endif bool CFindFile::FindNext(CFileInfo &fi) { - WIN32_FIND_DATA fd; - bool result = BOOLToBool(::FindNextFile(_handle, &fd)); - if (result) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return result; -} - -#ifndef _UNICODE -bool CFindFile::FindNext(CFileInfoW &fi) -{ - if (g_IsNT) + #ifndef _UNICODE + if (!g_IsNT) { - WIN32_FIND_DATAW fd; - if (!::FindNextFileW(_handle, &fd)) + WIN32_FIND_DATAA fd; + if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } else + #endif { - WIN32_FIND_DATAA fd; - if (!::FindNextFileA(_handle, &fd)) + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); } return true; } -#endif #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; @@ -198,7 +145,7 @@ void CFileInfoBase::Clear() Attrib = 0; } -bool CFileInfo::Find(LPCTSTR wildcard) +bool CFileInfo::Find(CFSTR wildcard) { #ifdef SUPPORT_DEVICE_FILE if (IsDeviceName(wildcard)) @@ -215,72 +162,66 @@ bool CFileInfo::Find(LPCTSTR wildcard) } #endif CFindFile finder; - return finder.FindFirst(wildcard, *this); -} - - -#ifndef _UNICODE -bool CFileInfoW::Find(LPCWSTR wildcard) -{ - #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) - { - Clear(); - IsDevice = true; - NIO::CInFile inFile; - if (!inFile.Open(wildcard)) - return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; + if (finder.FindFirst(wildcard, *this)) return true; + #ifdef _WIN32 + { + DWORD lastError = GetLastError(); + if (lastError == ERROR_BAD_NETPATH || lastError == ERROR_FILE_NOT_FOUND) + { + int len = MyStringLen(wildcard); + if (len > 2 && wildcard[0] == '\\' && wildcard[1] == '\\') + { + int pos = FindCharPosInString(wildcard + 2, FTEXT('\\')); + if (pos >= 0) + { + pos += 2 + 1; + len -= pos; + CFSTR remString = wildcard + pos; + int pos2 = FindCharPosInString(remString, FTEXT('\\')); + FString s = wildcard; + if (pos2 < 0 || pos2 == len - 1) + { + FString s = wildcard; + if (pos2 < 0) + { + pos2 = len; + s += FTEXT('\\'); + } + s += FCHAR_ANY_MASK; + if (finder.FindFirst(s, *this)) + if (Name == FTEXT(".")) + { + Name = s.Mid(pos, pos2); + return true; + } + ::SetLastError(lastError); + } + } + } + } } #endif - CFindFile finder; - return finder.FindFirst(wildcard, *this); + return false; } -#endif -bool DoesFileExist(LPCTSTR name) +bool DoesFileExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && !fi.IsDir(); } -bool DoesDirExist(LPCTSTR name) +bool DoesDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && fi.IsDir(); } - -bool DoesFileOrDirExist(LPCTSTR name) +bool DoesFileOrDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name); } -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && !fi.IsDir(); -} - -bool DoesDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && fi.IsDir(); -} -bool DoesFileOrDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name); -} -#endif - -///////////////////////////////////// -// CEnumerator - bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) @@ -311,39 +252,6 @@ bool CEnumerator::Next(CFileInfo &fi, bool &found) return (::GetLastError() == ERROR_NO_MORE_FILES); } -#ifndef _UNICODE -bool CEnumeratorW::NextAny(CFileInfoW &fi) -{ - if (_findFile.IsHandleAllocated()) - return _findFile.FindNext(fi); - else - return _findFile.FindFirst(_wildcard, fi); -} - -bool CEnumeratorW::Next(CFileInfoW &fi) -{ - for (;;) - { - if (!NextAny(fi)) - return false; - if (!fi.IsDots()) - return true; - } -} - -bool CEnumeratorW::Next(CFileInfoW &fi, bool &found) -{ - if (Next(fi)) - { - found = true; - return true; - } - found = false; - return (::GetLastError() == ERROR_NO_MORE_FILES); -} - -#endif - //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. @@ -358,104 +266,82 @@ bool CFindChangeNotification::Close() return true; } -HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) -{ - _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH2 - if (!IsHandleAllocated()) - { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); - } - #endif - return _handle; -} - -#ifndef _UNICODE -HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) +HANDLE CFindChangeNotification::FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter) { + #ifndef _UNICODE if (!g_IsNT) - return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); - _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH - if (!IsHandleAllocated()) + _handle = ::FindFirstChangeNotification(fs2fas(pathName), BoolToBOOL(watchSubtree), notifyFilter); + else + #endif { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + _handle = ::FindFirstChangeNotificationW(fs2us(pathName), BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString longPath; + if (GetLongPath(pathName, longPath)) + _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif } - #endif return _handle; } -#endif #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) + +bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings) { driveStrings.Clear(); - UINT32 size = GetLogicalDriveStrings(0, NULL); - if (size == 0) - return false; - CSysString buffer; - UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); - if (newSize == 0) - return false; - if (newSize > size) - return false; - CSysString string; - for (UINT32 i = 0; i < newSize; i++) + #ifndef _UNICODE + if (!g_IsNT) { - TCHAR c = buffer[i]; - if (c == TEXT('\0')) + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + AString buf; + UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) + return false; + AString s; + for (UINT32 i = 0; i < newSize; i++) { - driveStrings.Add(string); - string.Empty(); + char c = buf[i]; + if (c == '\0') + { + driveStrings.Add(fas2fs(s)); + s.Empty(); + } + else + s += c; } - else - string += c; + return s.IsEmpty(); } - if (!string.IsEmpty()) - return false; - return true; -} - -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings) -{ - driveStrings.Clear(); - if (g_IsNT) + else + #endif { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; - UString buffer; - UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); - if (newSize == 0) + UString buf; + UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) return false; - if (newSize > size) - return false; - UString string; + UString s; for (UINT32 i = 0; i < newSize; i++) { - WCHAR c = buffer[i]; + WCHAR c = buf[i]; if (c == L'\0') { - driveStrings.Add(string); - string.Empty(); + driveStrings.Add(us2fs(s)); + s.Empty(); } else - string += c; + s += c; } - return string.IsEmpty(); + return s.IsEmpty(); } - CSysStringVector driveStringsA; - bool res = MyGetLogicalDriveStrings(driveStringsA); - for (int i = 0; i < driveStringsA.Size(); i++) - driveStrings.Add(GetUnicodeString(driveStringsA[i])); - return res; } -#endif #endif diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index 63631f66..97a3b7c2 100755 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -1,12 +1,11 @@ // Windows/FileFind.h -#ifndef __WINDOWS_FILEFIND_H -#define __WINDOWS_FILEFIND_H +#ifndef __WINDOWS_FILE_FIND_H +#define __WINDOWS_FILE_FIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "Defs.h" -#include "FileName.h" namespace NWindows { namespace NFile { @@ -60,24 +59,12 @@ public: struct CFileInfo: public CFileInfoBase { - CSysString Name; + FString Name; bool IsDots() const; - bool Find(LPCTSTR wildcard); + bool Find(CFSTR wildcard); }; -#ifdef _UNICODE -typedef CFileInfo CFileInfoW; -#else -struct CFileInfoW: public CFileInfoBase -{ - UString Name; - - bool IsDots() const; - bool Find(LPCWSTR wildcard); -}; -#endif - class CFindFile { friend class CEnumerator; @@ -85,53 +72,28 @@ class CFindFile public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} - ~CFindFile() { Close(); } - bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); + ~CFindFile() { Close(); } + bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); - #ifndef _UNICODE - bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); - bool FindNext(CFileInfoW &fileInfo); - #endif bool Close(); }; -bool DoesFileExist(LPCTSTR name); -bool DoesDirExist(LPCTSTR name); -bool DoesFileOrDirExist(LPCTSTR name); -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name); -bool DoesDirExist(LPCWSTR name); -bool DoesFileOrDirExist(LPCWSTR name); -#endif +bool DoesFileExist(CFSTR name); +bool DoesDirExist(CFSTR name); +bool DoesFileOrDirExist(CFSTR name); class CEnumerator { CFindFile _findFile; - CSysString _wildcard; + FString _wildcard; + bool NextAny(CFileInfo &fileInfo); public: - CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} - CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} + CEnumerator(const FString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; -#ifdef _UNICODE -typedef CEnumerator CEnumeratorW; -#else -class CEnumeratorW -{ - CFindFile _findFile; - UString _wildcard; - bool NextAny(CFileInfoW &fileInfo); -public: - CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} - CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} - bool Next(CFileInfoW &fileInfo); - bool Next(CFileInfoW &fileInfo, bool &found); -}; -#endif - class CFindChangeNotification { HANDLE _handle; @@ -141,21 +103,14 @@ public: CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); - HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); - #ifndef _UNICODE - HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); - #endif + HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings); -#endif +bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings); #endif }}} #endif - diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp index 938e6c70..e8f98747 100755 --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp @@ -4,13 +4,6 @@ #include "FileIO.h" -#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE) -#include "../Common/MyString.h" -#endif -#ifndef _UNICODE -#include "../Common/StringConvert.h" -#endif - #ifndef _UNICODE extern bool g_IsNT; #endif @@ -19,11 +12,12 @@ namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n) + +bool IsDeviceName(CFSTR n) { #ifdef UNDER_CE int len = (int)MyStringLen(n); - if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0) + if (len < 5 || len > 5 || memcmp(n, FTEXT("DSK"), 3 * sizeof(FCHAR)) != 0) return false; if (n[4] != ':') return false; @@ -34,7 +28,7 @@ bool IsDeviceName(LPCTSTR n) int len = (int)MyStringLen(n); if (len == 6 && n[5] == ':') return true; - if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0) + if (len < 18 || len > 22 || memcmp(n + 4, FTEXT("PhysicalDrive"), 13 * sizeof(FCHAR)) != 0) return false; for (int i = 17; i < len; i++) if (n[i] < '0' || n[i] > '9') @@ -43,22 +37,6 @@ bool IsDeviceName(LPCTSTR n) return true; } -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n) -{ - if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') - return false; - int len = (int)wcslen(n); - if (len == 6 && n[5] == ':') - return true; - if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - return true; -} -#endif #endif #if defined(WIN_LONG_PATH) && defined(_UNICODE) @@ -66,32 +44,34 @@ bool IsDeviceName(LPCWSTR n) #endif #ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR s, UString &res) +bool GetLongPathBase(CFSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); - wchar_t c = s[0]; - if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) + FChar c = s[0]; + if (len < 1 || c == '\\' || c == '.' && (len == 1 || len == 2 && s[1] == '.')) return true; UString curDir; bool isAbs = false; if (len > 3) - isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); + isAbs = (s[1] == ':' && s[2] == '\\' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')); if (!isAbs) - { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); - curDir.ReleaseBuffer(); - if (needLength == 0 || needLength > MAX_PATH) - return false; - if (curDir[curDir.Length() - 1] != L'\\') - curDir += L'\\'; - } - res = UString(L"\\\\?\\") + curDir + s; + { + WCHAR temp[MAX_PATH + 2]; + temp[0] = 0; + DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, temp); + if (needLength == 0 || needLength > MAX_PATH) + return false; + curDir = temp; + if (curDir.Back() != L'\\') + curDir += L'\\'; + } + res = UString(L"\\\\?\\") + curDir + fs2us(s); return true; } -bool GetLongPath(LPCWSTR path, UString &longPath) +bool GetLongPath(CFSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); @@ -103,58 +83,39 @@ namespace NIO { CFileBase::~CFileBase() { Close(); } -bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, +bool CFileBase::Create(CFSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; - _handle = ::CreateFile(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) - { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - } - #endif + #ifdef SUPPORT_DEVICE_FILE IsDeviceFile = false; #endif - return (_handle != INVALID_HANDLE_VALUE); -} -#ifndef _UNICODE -bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ + #ifndef _UNICODE if (!g_IsNT) - return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), - desiredAccess, shareMode, creationDisposition, flagsAndAttributes); - if (!Close()) - return false; - _handle = ::CreateFileW(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); + _handle = ::CreateFile(fs2fas(fileName), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } + else #endif - #ifdef SUPPORT_DEVICE_FILE - IsDeviceFile = false; - #endif + { + _handle = ::CreateFileW(fs2us(fileName), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE) + { + UString longPath; + if (GetLongPath(fileName, longPath)) + _handle = ::CreateFileW(longPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + #endif + } return (_handle != INVALID_HANDLE_VALUE); } -#endif bool CFileBase::Close() { @@ -226,21 +187,23 @@ bool CFileBase::SeekToEnd(UInt64 &newPosition) return Seek(0, FILE_END, newPosition); } -bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const +/* +bool CFileBase::GetFileInformation(CByHandleFileInfo &fi) const { - BY_HANDLE_FILE_INFORMATION winFileInfo; - if (!::GetFileInformationByHandle(_handle, &winFileInfo)) + BY_HANDLE_FILE_INFORMATION wfi; + if (!::GetFileInformationByHandle(_handle, &wfi)) return false; - fileInfo.Attrib = winFileInfo.dwFileAttributes; - fileInfo.CTime = winFileInfo.ftCreationTime; - fileInfo.ATime = winFileInfo.ftLastAccessTime; - fileInfo.MTime = winFileInfo.ftLastWriteTime; - fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; - fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; - fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; - fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; + fi.Attrib = wfi.dwFileAttributes; + fi.CTime = wfi.ftCreationTime; + fi.ATime = wfi.ftLastAccessTime; + fi.MTime = wfi.ftLastWriteTime; + fi.Size = (((UInt64)wfi.nFileSizeHigh) << 32) + wfi.nFileSizeLow; + fi.VolumeSerialNumber = wfi.dwVolumeSerialNumber; + fi.NumLinks = wfi.nNumberOfLinks; + fi.FileIndex = (((UInt64)wfi.nFileIndexHigh) << 32) + wfi.nFileIndexLow; return true; } +*/ ///////////////////////// // CInFile @@ -284,34 +247,19 @@ void CInFile::GetDeviceLength() #define MY_DEVICE_EXTRA_CODE #endif -bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); MY_DEVICE_EXTRA_CODE return res; } -bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) +bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } -bool CInFile::Open(LPCTSTR fileName) +bool CInFile::Open(CFSTR fileName) { return OpenShared(fileName, false); } -#ifndef _UNICODE -bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ - bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); - MY_DEVICE_EXTRA_CODE - return res; -} - -bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) -{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } - -bool CInFile::Open(LPCWSTR fileName) - { return OpenShared(fileName, false); } -#endif - // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES @@ -360,31 +308,18 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) ///////////////////////// // COutFile -bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } - static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } -bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) - { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } - -bool COutFile::Create(LPCTSTR fileName, bool createAlways) - { return Open(fileName, GetCreationDisposition(createAlways)); } - -#ifndef _UNICODE - -bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } -bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) +bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } -bool COutFile::Create(LPCWSTR fileName, bool createAlways) +bool COutFile::Create(CFSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } -#endif - bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index dce692fe..ecd7af96 100755 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -1,9 +1,10 @@ // Windows/FileIO.h -#ifndef __WINDOWS_FILEIO_H -#define __WINDOWS_FILEIO_H +#ifndef __WINDOWS_FILE_IO_H +#define __WINDOWS_FILE_IO_H #include "../Common/Types.h" +#include "../Common/MyString.h" #include "Defs.h" @@ -11,29 +12,27 @@ namespace NWindows { namespace NFile { namespace NIO { +/* struct CByHandleFileInfo { - DWORD Attrib; + UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; + DWORD Attrib; DWORD VolumeSerialNumber; - UInt64 Size; - DWORD NumberOfLinks; + DWORD NumLinks; UInt64 FileIndex; }; +*/ class CFileBase { protected: HANDLE _handle; - bool Create(LPCTSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #ifndef _UNICODE - bool Create(LPCWSTR fileName, DWORD desiredAccess, + bool Create(CFSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #endif public: #ifdef SUPPORT_DEVICE_FILE @@ -55,7 +54,7 @@ public: bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); - bool GetFileInformation(CByHandleFileInfo &fileInfo) const; + // bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM @@ -97,14 +96,10 @@ class CInFile: public CFileBase #endif public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCTSTR fileName, bool shareForWrite); - bool Open(LPCTSTR fileName); - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - bool Open(LPCWSTR fileName); - #endif + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(CFSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName); + bool Read1(void *data, UInt32 size, UInt32 &processedSize); bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); @@ -113,15 +108,9 @@ public: class COutFile: public CFileBase { public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCTSTR fileName, DWORD creationDisposition); - bool Create(LPCTSTR fileName, bool createAlways); - - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCWSTR fileName, DWORD creationDisposition); - bool Create(LPCWSTR fileName, bool createAlways); - #endif + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(CFSTR fileName, DWORD creationDisposition); + bool Create(CFSTR fileName, bool createAlways); bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index 8443a4af..8f464aa8 100755 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp @@ -2,49 +2,28 @@ #include "StdAfx.h" -#include "Windows/FileName.h" -#include "Common/Wildcard.h" +#include "FileName.h" namespace NWindows { namespace NFile { namespace NName { -void NormalizeDirPathPrefix(CSysString &dirPath) +void NormalizeDirPathPrefix(FString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) - dirPath += kDirDelimiter; + if (dirPath.ReverseFind(FCHAR_PATH_SEPARATOR) != dirPath.Length() - 1) + dirPath += FCHAR_PATH_SEPARATOR; } -#ifndef _UNICODE +#ifndef USE_UNICODE_FSTRING void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) - dirPath += wchar_t(kDirDelimiter); + if (dirPath.ReverseFind(WCHAR_PATH_SEPARATOR) != dirPath.Length() - 1) + dirPath += WCHAR_PATH_SEPARATOR; } #endif -const wchar_t kExtensionDelimiter = L'.'; - -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension) -{ - int index = fullName.ReverseFind(kExtensionDelimiter); - if (index < 0) - { - pureName = fullName; - extensionDelimiter.Empty(); - extension.Empty(); - } - else - { - pureName = fullName.Left(index); - extensionDelimiter = kExtensionDelimiter; - extension = fullName.Mid(index + 1); - } -} - }}} diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h index d9807902..9ee57f9d 100755 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h @@ -1,9 +1,7 @@ // Windows/FileName.h -#ifndef __WINDOWS_FILENAME_H -#define __WINDOWS_FILENAME_H - -#include "../../C/Types.h" +#ifndef __WINDOWS_FILE_NAME_H +#define __WINDOWS_FILE_NAME_H #include "../Common/MyString.h" @@ -11,16 +9,8 @@ namespace NWindows { namespace NFile { namespace NName { -const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; -const TCHAR kAnyStringWildcard = '*'; - -void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' -#ifndef _UNICODE -void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' -#endif - -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension); +void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty +void NormalizeDirPathPrefix(UString &dirPath); }}} diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp index 3ebfb752..8bf595b2 100755 --- a/CPP/Windows/FileSystem.cpp +++ b/CPP/Windows/FileSystem.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#ifndef _UNICODE +#include "Common/StringConvert.h" +#endif + #include "FileSystem.h" #include "Defs.h" @@ -14,113 +18,94 @@ namespace NFile { namespace NSystem { bool MyGetVolumeInformation( - LPCTSTR rootPathName, - CSysString &volumeName, + CFSTR rootPath, + UString &volumeName, LPDWORD volumeSerialNumber, LPDWORD maximumComponentLength, LPDWORD fileSystemFlags, - CSysString &fileSystemName) + UString &fileSystemName) { - bool result = BOOLToBool(GetVolumeInformation( - rootPathName, - volumeName.GetBuffer(MAX_PATH), MAX_PATH, - volumeSerialNumber, - maximumComponentLength, - fileSystemFlags, - fileSystemName.GetBuffer(MAX_PATH), MAX_PATH)); - volumeName.ReleaseBuffer(); - fileSystemName.ReleaseBuffer(); - return result; + BOOL res; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR v[MAX_PATH + 2]; v[0] = 0; + TCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformation(fs2fas(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = MultiByteToUnicodeString(v); + fileSystemName = MultiByteToUnicodeString(f); + } + else + #endif + { + WCHAR v[MAX_PATH + 2]; v[0] = 0; + WCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformationW(fs2us(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = v; + fileSystemName = f; + } + return BOOLToBool(res); } - -#ifndef _UNICODE -bool MyGetVolumeInformation( - LPCWSTR rootPathName, - UString &volumeName, - LPDWORD volumeSerialNumber, - LPDWORD maximumComponentLength, - LPDWORD fileSystemFlags, - UString &fileSystemName) +UINT MyGetDriveType(CFSTR pathName) { - if (g_IsNT) + #ifndef _UNICODE + if (!g_IsNT) { - bool result = BOOLToBool(GetVolumeInformationW( - rootPathName, - volumeName.GetBuffer(MAX_PATH), MAX_PATH, - volumeSerialNumber, - maximumComponentLength, - fileSystemFlags, - fileSystemName.GetBuffer(MAX_PATH), MAX_PATH)); - volumeName.ReleaseBuffer(); - fileSystemName.ReleaseBuffer(); - return result; + return GetDriveType(fs2fas(pathName)); } - AString volumeNameA, fileSystemNameA; - bool result = MyGetVolumeInformation(GetSystemString(rootPathName), volumeNameA, - volumeSerialNumber, maximumComponentLength, fileSystemFlags,fileSystemNameA); - if (result) + else + #endif { - volumeName = GetUnicodeString(volumeNameA); - fileSystemName = GetUnicodeString(fileSystemNameA); + return GetDriveTypeW(fs2us(pathName)); } - return result; } -#endif -typedef BOOL (WINAPI * GetDiskFreeSpaceExPointer)( - LPCTSTR lpDirectoryName, // directory name +typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)( + LPCWSTR lpDirectoryName, // directory name PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk ); -bool MyGetDiskFreeSpace(LPCTSTR rootPathName, - UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) { - GetDiskFreeSpaceExPointer pGetDiskFreeSpaceEx = - (GetDiskFreeSpaceExPointer)GetProcAddress( - GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); - + DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters; bool sizeIsDetected = false; - if (pGetDiskFreeSpaceEx) + #ifndef _UNICODE + if (!g_IsNT) { - ULARGE_INTEGER i64FreeBytesToCaller, totalSize2, freeSize2; - sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(rootPathName, - &i64FreeBytesToCaller, - &totalSize2, - &freeSize2)); - totalSize = totalSize2.QuadPart; - freeSize = freeSize2.QuadPart; + if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; + } + else + #endif + { + GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; } - - DWORD numSectorsPerCluster; - DWORD bytesPerSector; - DWORD numberOfFreeClusters; - DWORD totalNumberOfClusters; - - if (!::GetDiskFreeSpace(rootPathName, - &numSectorsPerCluster, - &bytesPerSector, - &numberOfFreeClusters, - &totalNumberOfClusters)) - return false; - clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster; if (!sizeIsDetected) { - totalSize = clusterSize * (UInt64)totalNumberOfClusters; - freeSize = clusterSize * (UInt64)numberOfFreeClusters; + totalSize = clusterSize * (UInt64)numClusters; + freeSize = clusterSize * (UInt64)numFreeClusters; } return true; } -#ifndef _UNICODE -bool MyGetDiskFreeSpace(LPCWSTR rootPathName, - UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) -{ - return MyGetDiskFreeSpace(GetSystemString(rootPathName), clusterSize, totalSize, freeSize); -} -#endif - }}} diff --git a/CPP/Windows/FileSystem.h b/CPP/Windows/FileSystem.h index 727497bb..a7a8d1a9 100755 --- a/CPP/Windows/FileSystem.h +++ b/CPP/Windows/FileSystem.h @@ -1,51 +1,27 @@ // Windows/FileSystem.h -#ifndef __WINDOWS_FILESYSTEM_H -#define __WINDOWS_FILESYSTEM_H +#ifndef __WINDOWS_FILE_SYSTEM_H +#define __WINDOWS_FILE_SYSTEM_H #include "../Common/MyString.h" #include "../Common/Types.h" -#ifndef _UNICODE -#include "../Common/StringConvert.h" -#endif - namespace NWindows { namespace NFile { namespace NSystem { bool MyGetVolumeInformation( - LPCTSTR rootPathName, - CSysString &volumeName, - LPDWORD volumeSerialNumber, - LPDWORD maximumComponentLength, - LPDWORD fileSystemFlags, - CSysString &fileSystemName); - -#ifndef _UNICODE -bool MyGetVolumeInformation( - LPCWSTR rootPathName, + CFSTR rootPath , UString &volumeName, LPDWORD volumeSerialNumber, LPDWORD maximumComponentLength, LPDWORD fileSystemFlags, UString &fileSystemName); -#endif - -inline UINT MyGetDriveType(LPCTSTR pathName) { return GetDriveType(pathName); } -#ifndef _UNICODE -inline UINT MyGetDriveType(LPCWSTR pathName) { return GetDriveType(GetSystemString(pathName)); } -#endif -bool MyGetDiskFreeSpace(LPCTSTR rootPathName, - UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +UINT MyGetDriveType(CFSTR pathName); -#ifndef _UNICODE -bool MyGetDiskFreeSpace(LPCWSTR rootPathName, - UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); -#endif +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); }}} #endif - diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp index 0a9cfab7..f10b4ef2 100755 --- a/CPP/Windows/PropVariantUtils.cpp +++ b/CPP/Windows/PropVariantUtils.cpp @@ -20,7 +20,7 @@ void StringToProp(const AString &s, NCOM::CPropVariant &prop) prop = MultiByteToUnicodeString(s); } -void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop) +AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) { AString s; for (unsigned i = 0; i < num; i++) @@ -31,7 +31,13 @@ void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM: } if (s.IsEmpty()) s = GetHex(value); - StringToProp(s, prop); + return s; +} + + +void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop) +{ + StringToProp(TypePairToString(pairs, num, value), prop); } AString TypeToString(const char *table[], unsigned num, UInt32 value) @@ -56,9 +62,12 @@ AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) UInt32 flag = (UInt32)1 << (unsigned)p.Value; if ((flags & flag) != 0) { - if (!s.IsEmpty()) - s += ' '; - s += p.Name; + if (p.Name[0] != 0) + { + if (!s.IsEmpty()) + s += ' '; + s += p.Name; + } } flags &= ~flag; } @@ -75,4 +84,3 @@ void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM { StringToProp(FlagsToString(pairs, num, flags), prop); } - diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h index 5aaf65cb..5582aaff 100755 --- a/CPP/Windows/PropVariantUtils.h +++ b/CPP/Windows/PropVariantUtils.h @@ -13,6 +13,7 @@ struct CUInt32PCharPair }; void StringToProp(const AString &s, NWindows::NCOM::CPropVariant &prop); +AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value); void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop); AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags); diff --git a/CPP/Windows/Time.cpp b/CPP/Windows/Time.cpp index ec9ca47d..2cb028f9 100755 --- a/CPP/Windows/Time.cpp +++ b/CPP/Windows/Time.cpp @@ -13,8 +13,9 @@ static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt32 kFileTimeStartYear = 1601; static const UInt32 kDosTimeStartYear = 1980; static const UInt32 kUnixTimeStartYear = 1970; -static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * - 60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) { @@ -117,20 +118,52 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) { - UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; + UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) +{ + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (unixTime < 0) + { + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + } + else + { + if (v < unixTime || v > kNumSecondsInFileTime) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; +} + bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) { UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - if (winTime < kUnixTimeStartValue) + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) { unixTime = 0; return false; } - winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; + winTime -= kUnixTimeOffset; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; diff --git a/CPP/Windows/Time.h b/CPP/Windows/Time.h index 6f510b22..537b80e6 100755 --- a/CPP/Windows/Time.h +++ b/CPP/Windows/Time.h @@ -11,7 +11,9 @@ namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); +Int64 FileTimeToUnixTime64(const FILETIME &ft); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); diff --git a/DOC/7zip.inf b/DOC/7zip.inf index ff235405..b78a834f 100755 --- a/DOC/7zip.inf +++ b/DOC/7zip.inf @@ -10,8 +10,8 @@ AppName = "7-Zip" InstallDir = %CE1%\%AppName% [Strings] -AppVer = "9.20" -AppDate = "2010-11-18" +AppVer = "9.21" +AppDate = "2011-04-11" [CEDevice] ; ProcessorType = 2577 ; ARM diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi index 06af769c..977f27e8 100755 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -2,8 +2,8 @@ ;Defines !define VERSION_MAJOR 9 -!define VERSION_MINOR 20 -!define VERSION_POSTFIX_FULL "" +!define VERSION_MINOR 21 +!define VERSION_POSTFIX_FULL "beta" !ifdef WIN64 !ifdef IA64 !define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" @@ -49,7 +49,7 @@ InstallDir "$PROGRAMFILES\7-Zip" ;Get install folder from registry if available - InstallDirRegKey HKLM "Software\7-Zip" "Path" + InstallDirRegKey HKCU "Software\7-Zip" "Path32" ;Compressor !ifndef NO_COMPRESSION @@ -190,6 +190,7 @@ Section File bn.txt File br.txt File ca.txt + File co.txt File cs.txt File cy.txt File da.txt @@ -222,6 +223,8 @@ Section File ko.txt File ku.txt File ku-ckb.txt + File ky.txt + File lij.txt File lt.txt File lv.txt File mk.txt @@ -293,8 +296,10 @@ Section noScErrors: # store install folder - WriteRegStr HKLM "Software\7-Zip" "Path" $INSTDIR - WriteRegStr HKCU "Software\7-Zip" "Path" $INSTDIR + WriteRegStr HKLM "Software\7-Zip" "Path32" $INSTDIR + WriteRegStr HKLM "Software\7-Zip" "Path" $INSTDIR + WriteRegStr HKCU "Software\7-Zip" "Path32" $INSTDIR + WriteRegStr HKCU "Software\7-Zip" "Path" $INSTDIR # write reg entries WriteRegStr HKCR "CLSID\${CLSID_CONTEXT_MENU}" "" "7-Zip Shell Extension" @@ -384,6 +389,7 @@ Section "Uninstall" Delete $INSTDIR\Lang\bn.txt Delete $INSTDIR\Lang\br.txt Delete $INSTDIR\Lang\ca.txt + Delete $INSTDIR\Lang\co.txt Delete $INSTDIR\Lang\cs.txt Delete $INSTDIR\Lang\cy.txt Delete $INSTDIR\Lang\da.txt @@ -416,6 +422,8 @@ Section "Uninstall" Delete $INSTDIR\Lang\ko.txt Delete $INSTDIR\Lang\ku.txt Delete $INSTDIR\Lang\ku-ckb.txt + Delete $INSTDIR\Lang\ky.txt + Delete $INSTDIR\Lang\lij.txt Delete $INSTDIR\Lang\lt.txt Delete $INSTDIR\Lang\lv.txt Delete $INSTDIR\Lang\mk.txt @@ -496,6 +504,7 @@ Section "Uninstall" DeleteRegKey HKCR "Directory\shellex\ContextMenuHandlers\7-Zip" DeleteRegKey HKCR "Folder\shellex\ContextMenuHandlers\7-Zip" + DeleteRegKey HKCR "Drive\shellex\DragDropHandlers\7-Zip" DeleteRegKey HKCR "Directory\shellex\DragDropHandlers\7-Zip" DeleteRegKey HKCR "Folder\shellex\DragDropHandlers\7-Zip" @@ -512,6 +521,7 @@ Section "Uninstall" DeleteRegKey HKCR "7-Zip.cpio" DeleteRegKey HKCR "7-Zip.deb" DeleteRegKey HKCR "7-Zip.dmg" + DeleteRegKey HKCR "7-Zip.fat" DeleteRegKey HKCR "7-Zip.gz" DeleteRegKey HKCR "7-Zip.gzip" DeleteRegKey HKCR "7-Zip.hfs" @@ -519,16 +529,21 @@ Section "Uninstall" DeleteRegKey HKCR "7-Zip.lha" DeleteRegKey HKCR "7-Zip.lzh" DeleteRegKey HKCR "7-Zip.lzma" + DeleteRegKey HKCR "7-Zip.ntfs" DeleteRegKey HKCR "7-Zip.rar" DeleteRegKey HKCR "7-Zip.rpm" DeleteRegKey HKCR "7-Zip.split" + DeleteRegKey HKCR "7-Zip.squashfs" DeleteRegKey HKCR "7-Zip.swm" DeleteRegKey HKCR "7-Zip.tar" DeleteRegKey HKCR "7-Zip.taz" DeleteRegKey HKCR "7-Zip.tgz" DeleteRegKey HKCR "7-Zip.tpz" + DeleteRegKey HKCR "7-Zip.txz" + DeleteRegKey HKCR "7-Zip.vhd" DeleteRegKey HKCR "7-Zip.wim" DeleteRegKey HKCR "7-Zip.xar" + DeleteRegKey HKCR "7-Zip.xz" DeleteRegKey HKCR "7-Zip.z" DeleteRegKey HKCR "7-Zip.zip" diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index 984e6687..1d266498 100755 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ <?xml version="1.0"?> <?define VerMajor = "9" ?> -<?define VerMinor = "20" ?> +<?define VerMinor = "21" ?> <?define VerBuild = "00" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?> @@ -20,18 +20,21 @@ <?define Platforms = "x64" ?> <?define CpuPostfix = " (x64 edition)" ?> <?define Is64 = "yes" ?> + <?define NumBits = "64" ?> <?elseif $(var.MyCPU) = "ia64" ?> <?define CpuId = "3" ?> <?define PFilesFolder = "ProgramFiles64Folder" ?> <?define Platforms = "Intel64" ?> <?define CpuPostfix = " (ia64 edition)" ?> <?define Is64 = "yes" ?> + <?define NumBits = "64" ?> <?else ?> <?define CpuId = "1" ?> <?define PFilesFolder = "ProgramFilesFolder" ?> <?define Platforms = "Intel" ?> <?define CpuPostfix = "" ?> <?define Is64 = "no" ?> + <?define NumBits = "32" ?> <?endif ?> @@ -100,7 +103,10 @@ <Media Id="1" Cabinet="product.cab" EmbedCab="yes" CompressionLevel="high" /> <Property Id="INSTALLDIR"> - <RegistrySearch Id="My7zipPath" Type="raw" Root="HKCU" Key="Software\7-Zip" Name="Path" /> + <RegistrySearch Id="My7zipPathLM" Type="raw" Root="HKLM" Key="Software\7-Zip" Name="Path" /> + <RegistrySearch Id="My7zipPathLM2" Type="raw" Root="HKLM" Key="Software\7-Zip" Name="Path$(var.NumBits)" /> + <RegistrySearch Id="My7zipPath" Type="raw" Root="HKCU" Key="Software\7-Zip" Name="Path" /> + <RegistrySearch Id="My7zipPath2" Type="raw" Root="HKCU" Key="Software\7-Zip" Name="Path$(var.NumBits)" /> </Property> <Property Id="ALLUSERS">2</Property> @@ -116,13 +122,13 @@ <Directory Id="INSTALLDIR" Name="7-Zip"> <Component Id="InstallRegCU" Guid="$(var.CompInstallRegCU)" DiskId="1" Win64="$(var.Is64)"> - <Registry Id="MyInstallRegCU" Root="HKCU" Key="Software\7-Zip" Name="Path" - Action="write" Type="string" Value="[INSTALLDIR]" /> + <Registry Id="MyInstallRegCU" Root="HKCU" Key="Software\7-Zip" Name="Path" Action="write" Type="string" Value="[INSTALLDIR]" /> + <Registry Id="MyInstallRegCU2" Root="HKCU" Key="Software\7-Zip" Name="Path$(var.NumBits)" Action="write" Type="string" Value="[INSTALLDIR]" /> </Component> <Component Id="InstallRegLM" Guid="$(var.CompInstallRegLM)" DiskId="1" Win64="$(var.Is64)"> <Condition>Privileged</Condition> - <Registry Id="MyInstallRegLM" Root="HKLM" Key="Software\7-Zip" Name="Path" - Action="write" Type="string" Value="[INSTALLDIR]" /> + <Registry Id="MyInstallRegLM" Root="HKLM" Key="Software\7-Zip" Name="Path" Action="write" Type="string" Value="[INSTALLDIR]" /> + <Registry Id="MyInstallRegLM2" Root="HKLM" Key="Software\7-Zip" Name="Path$(var.NumBits)" Action="write" Type="string" Value="[INSTALLDIR]" /> </Component> @@ -174,6 +180,21 @@ </File> </Component> + <?if $(var.MyCPU) = "x64" ?> + + <Component Id="ShellExt32" Guid="$(var.CompShellExt)" DiskId="1" Win64="no"> + <File Id="_7zip32.dll" Name="7-zip32.dll" /> + <Registry Id="shellReg0_32" Action="write" Type="string" Root="HKCR" + Key="CLSID\$(var.ShellExtId)\InprocServer32" + Value="[INSTALLDIR]7-zip32.dll" /> + <Registry Id="shellReg1_32" Action="write" Type="string" Root="HKCR" + Key="CLSID\$(var.ShellExtId)\InprocServer32" + Name="ThreadingModel" + Value="Apartment" /> + </Component> + + <?endif ?> + <Component Id="ShellExt" Guid="$(var.CompShellExt)" DiskId="1" Win64="$(var.Is64)"> <File Id="_7zip.dll" Name="7-zip.dll" /> <Registry Id="shellReg0" Action="write" Type="string" Root="HKCR" @@ -232,6 +253,7 @@ <File Id="bn.txt" Name="bn.txt" /> <File Id="br.txt" Name="br.txt" /> <File Id="ca.txt" Name="ca.txt" /> + <File Id="co.txt" Name="co.txt" /> <File Id="cs.txt" Name="cs.txt" /> <File Id="cy.txt" Name="cy.txt" /> <File Id="da.txt" Name="da.txt" /> @@ -264,6 +286,8 @@ <File Id="ko.txt" Name="ko.txt" /> <File Id="ku.txt" Name="ku.txt" /> <File Id="ku_ckb.txt" Name="ku-ckb.txt" /> + <File Id="ky.txt" Name="ky.txt" /> + <File Id="lij.txt" Name="lij.txt" /> <File Id="lt.txt" Name="lt.txt" /> <File Id="lv.txt" Name="lv.txt" /> <File Id="mk.txt" Name="mk.txt" /> @@ -319,6 +343,9 @@ Absent="disallow" AllowAdvertise="no"> <ComponentRef Id="Fm" /> <ComponentRef Id="ShellExt" /> + <?if $(var.MyCPU) = "x64" ?> + <ComponentRef Id="ShellExt32" /> + <?endif ?> <ComponentRef Id="CmdLine" /> <ComponentRef Id="Gui" /> <ComponentRef Id="GuiSfx" /> diff --git a/DOC/history.txt b/DOC/history.txt index 05a9a216..64ce04ae 100755 --- a/DOC/history.txt +++ b/DOC/history.txt @@ -1,6 +1,12 @@ Sources history of the 7-Zip ---------------------------- +9.21 2011-04-11 +------------------------- +- New class FString for file names at file systems. +- Speed optimization in CRC code for big-endian CPUs. + + 9.18 2010-11-02 ------------------------- - New small SFX module for installers (C/Util/SfxSetup). diff --git a/DOC/lzma.txt b/DOC/lzma.txt index 65932323..ce1af3a2 100755 --- a/DOC/lzma.txt +++ b/DOC/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 9.20 +LZMA SDK 9.21 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -24,6 +24,12 @@ Some code in LZMA SDK is based on public domain code from another developers: 1) PPMd var.H (2001): Dmitry Shkarin 2) SHA-256: Wei Dai (Crypto++ library) +You can copy, modify, distribute and perform LZMA SDK code, even for commercial purposes, +all without asking permission. + +LZMA SDK code is compatible with open source licenses, for example, you can +include it to GNU GPL or GNU LGPL code. + LZMA SDK Contents ----------------- diff --git a/DOC/readme.txt b/DOC/readme.txt index aad46264..96e6b485 100755 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 9.20 Sources +7-Zip 9.21 Sources ------------------ 7-Zip is a file archiver for Windows. |