mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-01-31 04:24:11 -06:00
4.49 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
fd8b1d78b4
commit
7038848692
+50
-60
@@ -44,14 +44,13 @@ int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
|
|||||||
return (p->bufferBase != 0);
|
return (p->bufferBase != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer + p->pos; }
|
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||||
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[(size_t)p->pos + index]; }
|
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
|
||||||
|
|
||||||
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
||||||
|
|
||||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
|
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
|
||||||
{
|
{
|
||||||
p->buffer += subValue;
|
|
||||||
p->posLimit -= subValue;
|
p->posLimit -= subValue;
|
||||||
p->pos -= subValue;
|
p->pos -= subValue;
|
||||||
p->streamPos -= subValue;
|
p->streamPos -= subValue;
|
||||||
@@ -63,7 +62,7 @@ void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||||||
return;
|
return;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *dest = (p->buffer + p->pos + (p->streamPos - p->pos));
|
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||||
UInt32 numReadBytes;
|
UInt32 numReadBytes;
|
||||||
UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
|
UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
@@ -85,16 +84,15 @@ void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||||||
void MatchFinder_MoveBlock(CMatchFinder *p)
|
void MatchFinder_MoveBlock(CMatchFinder *p)
|
||||||
{
|
{
|
||||||
memmove(p->bufferBase,
|
memmove(p->bufferBase,
|
||||||
p->buffer + p->pos - p->keepSizeBefore,
|
p->buffer - p->keepSizeBefore,
|
||||||
p->streamPos - p->pos + p->keepSizeBefore);
|
p->streamPos - p->pos + p->keepSizeBefore);
|
||||||
p->buffer = p->bufferBase + p->keepSizeBefore - p->pos;
|
p->buffer = p->bufferBase + p->keepSizeBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MatchFinder_NeedMove(CMatchFinder *p)
|
int MatchFinder_NeedMove(CMatchFinder *p)
|
||||||
{
|
{
|
||||||
/* if (p->streamEndWasReached) return 0; */
|
/* if (p->streamEndWasReached) return 0; */
|
||||||
return ((size_t)(p->bufferBase + p->blockSize - (p->buffer + p->pos)) <= p->keepSizeAfter);
|
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
||||||
@@ -257,7 +255,7 @@ void MatchFinder_Init(CMatchFinder *p)
|
|||||||
for(i = 0; i < p->hashSizeSum; i++)
|
for(i = 0; i < p->hashSizeSum; i++)
|
||||||
p->hash[i] = kEmptyHashValue;
|
p->hash[i] = kEmptyHashValue;
|
||||||
p->cyclicBufferPos = 0;
|
p->cyclicBufferPos = 0;
|
||||||
p->buffer = p->bufferBase - p->cyclicBufferSize;
|
p->buffer = p->bufferBase;
|
||||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||||
p->result = SZ_OK;
|
p->result = SZ_OK;
|
||||||
p->streamEndWasReached = 0;
|
p->streamEndWasReached = 0;
|
||||||
@@ -302,7 +300,7 @@ void MatchFinder_CheckLimits(CMatchFinder *p)
|
|||||||
MatchFinder_SetLimits(p);
|
MatchFinder_SetLimits(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||||
UInt32 *distances, UInt32 maxLen)
|
UInt32 *distances, UInt32 maxLen)
|
||||||
{
|
{
|
||||||
@@ -313,8 +311,7 @@ UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const B
|
|||||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||||
return distances;
|
return distances;
|
||||||
{
|
{
|
||||||
const Byte *pb = buffer + curMatch;
|
const Byte *pb = cur - delta;
|
||||||
const Byte *cur = buffer + pos;
|
|
||||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||||
{
|
{
|
||||||
@@ -334,7 +331,7 @@ UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||||
UInt32 *distances, UInt32 maxLen)
|
UInt32 *distances, UInt32 maxLen)
|
||||||
{
|
{
|
||||||
@@ -351,8 +348,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
const Byte *pb = buffer + curMatch;
|
const Byte *pb = cur - delta;
|
||||||
const Byte *cur = buffer + pos;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
if (pb[len] == cur[len])
|
if (pb[len] == cur[len])
|
||||||
{
|
{
|
||||||
@@ -390,7 +386,7 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
|
||||||
{
|
{
|
||||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||||
@@ -406,8 +402,7 @@ void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *b
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
const Byte *pb = buffer + curMatch;
|
const Byte *pb = cur - delta;
|
||||||
const Byte *cur = buffer + pos;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
if (pb[len] == cur[len])
|
if (pb[len] == cur[len])
|
||||||
{
|
{
|
||||||
@@ -443,6 +438,7 @@ void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *b
|
|||||||
|
|
||||||
#define MOVE_POS \
|
#define MOVE_POS \
|
||||||
++p->cyclicBufferPos; \
|
++p->cyclicBufferPos; \
|
||||||
|
p->buffer++; \
|
||||||
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
||||||
|
|
||||||
#define MOVE_POS_RET MOVE_POS return offset;
|
#define MOVE_POS_RET MOVE_POS return offset;
|
||||||
@@ -452,18 +448,19 @@ void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
|||||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||||
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
||||||
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||||
cur = p->buffer + p->pos;
|
cur = p->buffer;
|
||||||
|
|
||||||
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
||||||
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
||||||
|
|
||||||
|
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
||||||
|
|
||||||
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
||||||
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, \
|
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
|
||||||
p->cyclicBufferSize, p->cutValue, distances + offset, maxLen) - distances); MOVE_POS_RET;
|
distances + offset, maxLen) - distances); MOVE_POS_RET;
|
||||||
|
|
||||||
#define SKIP_FOOTER \
|
#define SKIP_FOOTER \
|
||||||
SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son, \
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||||
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue); MOVE_POS;
|
|
||||||
|
|
||||||
UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
{
|
{
|
||||||
@@ -489,33 +486,31 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||||||
|
|
||||||
UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
{
|
{
|
||||||
UInt32 hash2Value, matchMinPos, curMatch2, maxLen, offset;
|
UInt32 hash2Value, delta2, maxLen, offset;
|
||||||
GET_MATCHES_HEADER(3)
|
GET_MATCHES_HEADER(3)
|
||||||
|
|
||||||
HASH3_CALC;
|
HASH3_CALC;
|
||||||
|
|
||||||
curMatch2 = p->hash[hash2Value];
|
delta2 = p->pos - p->hash[hash2Value];
|
||||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||||
|
|
||||||
p->hash[hash2Value] =
|
p->hash[hash2Value] =
|
||||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
matchMinPos = p->pos - p->cyclicBufferSize;
|
|
||||||
|
|
||||||
maxLen = 2;
|
maxLen = 2;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
{
|
{
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
|
if (cur[(size_t)maxLen - delta2] != cur[maxLen])
|
||||||
break;
|
break;
|
||||||
distances[0] = maxLen;
|
distances[0] = maxLen;
|
||||||
distances[1] = p->pos - curMatch2 - 1;
|
distances[1] = delta2 - 1;
|
||||||
offset = 2;
|
offset = 2;
|
||||||
if (maxLen == lenLimit)
|
if (maxLen == lenLimit)
|
||||||
{
|
{
|
||||||
SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||||
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue);
|
|
||||||
MOVE_POS_RET;
|
MOVE_POS_RET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,45 +519,43 @@ UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||||||
|
|
||||||
UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
{
|
{
|
||||||
UInt32 hash2Value, hash3Value, matchMinPos, curMatch2, curMatch3, maxLen, offset;
|
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||||
GET_MATCHES_HEADER(4)
|
GET_MATCHES_HEADER(4)
|
||||||
|
|
||||||
HASH4_CALC;
|
HASH4_CALC;
|
||||||
|
|
||||||
curMatch2 = p->hash[ hash2Value];
|
delta2 = p->pos - p->hash[ hash2Value];
|
||||||
curMatch3 = p->hash[kFix3HashSize + hash3Value];
|
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
|
||||||
p->hash[ hash2Value] =
|
p->hash[ hash2Value] =
|
||||||
p->hash[kFix3HashSize + hash3Value] =
|
p->hash[kFix3HashSize + hash3Value] =
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
matchMinPos = p->pos - p->cyclicBufferSize;
|
|
||||||
maxLen = 1;
|
maxLen = 1;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
{
|
{
|
||||||
distances[0] = maxLen = 2;
|
distances[0] = maxLen = 2;
|
||||||
distances[1] = p->pos - curMatch2 - 1;
|
distances[1] = delta2 - 1;
|
||||||
offset = 2;
|
offset = 2;
|
||||||
}
|
}
|
||||||
if (curMatch2 != curMatch3 && curMatch3 > matchMinPos && p->buffer[curMatch3] == cur[0])
|
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||||
{
|
{
|
||||||
maxLen = 3;
|
maxLen = 3;
|
||||||
distances[offset + 1] = p->pos - curMatch3 - 1;
|
distances[offset + 1] = delta3 - 1;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
curMatch2 = curMatch3;
|
delta2 = delta3;
|
||||||
}
|
}
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
{
|
{
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
|
if (cur[(size_t)maxLen - delta2] != cur[maxLen])
|
||||||
break;
|
break;
|
||||||
distances[offset - 2] = maxLen;
|
distances[offset - 2] = maxLen;
|
||||||
if (maxLen == lenLimit)
|
if (maxLen == lenLimit)
|
||||||
{
|
{
|
||||||
SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||||
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue);
|
|
||||||
MOVE_POS_RET;
|
MOVE_POS_RET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,39 +566,38 @@ UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||||||
|
|
||||||
UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
{
|
{
|
||||||
UInt32 hash2Value, hash3Value, matchMinPos, curMatch2, curMatch3, maxLen, offset;
|
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||||
GET_MATCHES_HEADER(4)
|
GET_MATCHES_HEADER(4)
|
||||||
|
|
||||||
HASH4_CALC;
|
HASH4_CALC;
|
||||||
|
|
||||||
curMatch2 = p->hash[ hash2Value];
|
delta2 = p->pos - p->hash[ hash2Value];
|
||||||
curMatch3 = p->hash[kFix3HashSize + hash3Value];
|
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
|
||||||
p->hash[ hash2Value] =
|
p->hash[ hash2Value] =
|
||||||
p->hash[kFix3HashSize + hash3Value] =
|
p->hash[kFix3HashSize + hash3Value] =
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
matchMinPos = p->pos - p->cyclicBufferSize;
|
|
||||||
maxLen = 1;
|
maxLen = 1;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
{
|
{
|
||||||
distances[0] = maxLen = 2;
|
distances[0] = maxLen = 2;
|
||||||
distances[1] = p->pos - curMatch2 - 1;
|
distances[1] = delta2 - 1;
|
||||||
offset = 2;
|
offset = 2;
|
||||||
}
|
}
|
||||||
if (curMatch2 != curMatch3 && curMatch3 > matchMinPos && p->buffer[curMatch3] == cur[0])
|
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||||
{
|
{
|
||||||
maxLen = 3;
|
maxLen = 3;
|
||||||
distances[offset + 1] = p->pos - curMatch3 - 1;
|
distances[offset + 1] = delta3 - 1;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
curMatch2 = curMatch3;
|
delta2 = delta3;
|
||||||
}
|
}
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
{
|
{
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
|
if (cur[(size_t)maxLen - delta2] != cur[maxLen])
|
||||||
break;
|
break;
|
||||||
distances[offset - 2] = maxLen;
|
distances[offset - 2] = maxLen;
|
||||||
if (maxLen == lenLimit)
|
if (maxLen == lenLimit)
|
||||||
@@ -616,8 +608,7 @@ UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||||||
}
|
}
|
||||||
if (maxLen < 3)
|
if (maxLen < 3)
|
||||||
maxLen = 3;
|
maxLen = 3;
|
||||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
|
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||||
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
|
||||||
distances + offset, maxLen) - (distances));
|
distances + offset, maxLen) - (distances));
|
||||||
MOVE_POS_RET
|
MOVE_POS_RET
|
||||||
}
|
}
|
||||||
@@ -629,8 +620,7 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||||||
HASH_ZIP_CALC;
|
HASH_ZIP_CALC;
|
||||||
curMatch = p->hash[hashValue];
|
curMatch = p->hash[hashValue];
|
||||||
p->hash[hashValue] = p->pos;
|
p->hash[hashValue] = p->pos;
|
||||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
|
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||||
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
|
||||||
distances, 2) - (distances));
|
distances, 2) - (distances));
|
||||||
MOVE_POS_RET
|
MOVE_POS_RET
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,9 @@ typedef struct _CMatchFinder
|
|||||||
HRes result;
|
HRes result;
|
||||||
} CMatchFinder;
|
} CMatchFinder;
|
||||||
|
|
||||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer + (p)->pos)
|
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(size_t)(p)->pos + (Int32)(index)])
|
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||||
|
|
||||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||||
|
|
||||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||||
|
|||||||
@@ -150,10 +150,10 @@ sometimes they use signed extending: (size_t)pos was compiled to "movsxd r10, ed
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEF_GetHeads(name, v) \
|
#define DEF_GetHeads(name, v) \
|
||||||
static void GetHeads ## name(const Byte *buffer, size_t pos, \
|
static void GetHeads ## name(const Byte *p, size_t pos, \
|
||||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
|
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
|
||||||
for (; numHeads != 0; numHeads--) { const Byte *p = buffer + (size_t)pos; \
|
for (; numHeads != 0; numHeads--) { \
|
||||||
const UInt32 value = (v); *heads++ = (UInt32)pos - hash[value]; hash[value] = (UInt32)(pos++); } }
|
const UInt32 value = (v); p++; *heads++ = (UInt32)pos - hash[value]; hash[value] = (UInt32)(pos++); } }
|
||||||
|
|
||||||
DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
|
DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
|
||||||
DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
||||||
@@ -222,6 +222,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
|||||||
heads[0] += num;
|
heads[0] += num;
|
||||||
}
|
}
|
||||||
mf->pos += num;
|
mf->pos += num;
|
||||||
|
mf->buffer += num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *buffer, CLzRef *son,
|
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||||
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
||||||
{
|
{
|
||||||
@@ -276,14 +277,14 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *buffer,
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
const Byte *pb = buffer + curMatch;
|
const Byte *pb = cur - delta;
|
||||||
const Byte *cur = buffer + pos;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
if (pb[len] == cur[len])
|
if (pb[len] == cur[len])
|
||||||
{
|
{
|
||||||
while(++len != lenLimit)
|
if (++len != lenLimit && pb[len] == cur[len])
|
||||||
if (pb[len] != cur[len])
|
while(++len != lenLimit)
|
||||||
break;
|
if (pb[len] != cur[len])
|
||||||
|
break;
|
||||||
if (maxLen < len)
|
if (maxLen < len)
|
||||||
{
|
{
|
||||||
*distances++ = maxLen = len;
|
*distances++ = maxLen = len;
|
||||||
@@ -314,6 +315,7 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *buffer,
|
|||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
_cyclicBufferPos++;
|
_cyclicBufferPos++;
|
||||||
|
cur++;
|
||||||
{
|
{
|
||||||
UInt32 num = (UInt32)(distances - _distances);
|
UInt32 num = (UInt32)(distances - _distances);
|
||||||
*_distances = num - 1;
|
*_distances = num - 1;
|
||||||
@@ -372,6 +374,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||||||
curPos += num;
|
curPos += num;
|
||||||
cyclicBufferPos++;
|
cyclicBufferPos++;
|
||||||
pos++;
|
pos++;
|
||||||
|
p->buffer++;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@@ -380,6 +383,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
||||||
p->hashBufPos += posRes - pos;
|
p->hashBufPos += posRes - pos;
|
||||||
cyclicBufferPos += posRes - pos;
|
cyclicBufferPos += posRes - pos;
|
||||||
|
p->buffer += posRes - pos;
|
||||||
pos = posRes;
|
pos = posRes;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -411,7 +415,6 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
|||||||
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
||||||
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
||||||
p->pos -= subValue;
|
p->pos -= subValue;
|
||||||
p->buffer += subValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sync->needStart)
|
if (!sync->needStart)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ typedef struct _CMatchFinderMt
|
|||||||
UInt32 matchMaxLen;
|
UInt32 matchMaxLen;
|
||||||
UInt32 numHashBytes;
|
UInt32 numHashBytes;
|
||||||
UInt32 pos;
|
UInt32 pos;
|
||||||
Byte *buffer; /* Pointer to virtual Buffer begin */
|
Byte *buffer;
|
||||||
UInt32 cyclicBufferPos;
|
UInt32 cyclicBufferPos;
|
||||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||||
UInt32 cutValue;
|
UInt32 cutValue;
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
|
|||||||
RINOK(_coders[i].Create());
|
RINOK(_coders[i].Create());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_streamBinders.Size() + 1 < _coders.Size())
|
_streamBinders.Clear();
|
||||||
|
for (i = 0; i + 1 < _coders.Size(); i++)
|
||||||
{
|
{
|
||||||
_streamBinders.Add(CStreamBinder());
|
_streamBinders.Add(CStreamBinder());
|
||||||
int i = _streamBinders.Size() - 1;
|
CStreamBinder &sb = _streamBinders[i];
|
||||||
CStreamBinder &sb = _streamBinders.Back();
|
|
||||||
RINOK(sb.CreateEvents());
|
RINOK(sb.CreateEvents());
|
||||||
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
|
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#ifndef __CODER_MIXER_MT_H
|
#ifndef __CODER_MIXER_MT_H
|
||||||
#define __CODER_MIXER_MT_H
|
#define __CODER_MIXER_MT_H
|
||||||
|
|
||||||
#include "../../../Common/Vector.h"
|
#include "../../../Common/MyVector.h"
|
||||||
#include "../../../Common/MyCom.h"
|
#include "../../../Common/MyCom.h"
|
||||||
#include "../../ICoder.h"
|
#include "../../ICoder.h"
|
||||||
#include "../../Common/StreamBinder.h"
|
#include "../../Common/StreamBinder.h"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "OutStreamWithCRC.h"
|
#include "OutStreamWithCRC.h"
|
||||||
|
|
||||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
{
|
{
|
||||||
UInt32 realProcessedSize;
|
UInt32 realProcessedSize;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
@@ -15,7 +15,7 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pr
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = _stream->Write(data, size, &realProcessedSize);
|
result = _stream->Write(data, size, &realProcessedSize);
|
||||||
if (_calculateCrc)
|
if (_calculate)
|
||||||
_crc = CrcUpdate(_crc, data, realProcessedSize);
|
_crc = CrcUpdate(_crc, data, realProcessedSize);
|
||||||
_size += realProcessedSize;
|
_size += realProcessedSize;
|
||||||
if(processedSize != NULL)
|
if(processedSize != NULL)
|
||||||
|
|||||||
@@ -15,27 +15,24 @@ class COutStreamWithCRC:
|
|||||||
public ISequentialOutStream,
|
public ISequentialOutStream,
|
||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
MY_UNKNOWN_IMP
|
|
||||||
|
|
||||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
|
||||||
private:
|
|
||||||
CMyComPtr<ISequentialOutStream> _stream;
|
CMyComPtr<ISequentialOutStream> _stream;
|
||||||
UInt64 _size;
|
UInt64 _size;
|
||||||
UInt32 _crc;
|
UInt32 _crc;
|
||||||
bool _calculateCrc;
|
bool _calculate;
|
||||||
public:
|
public:
|
||||||
|
MY_UNKNOWN_IMP
|
||||||
|
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||||
void Init(bool calculateCrc = true)
|
void ReleaseStream() { _stream.Release(); }
|
||||||
|
void Init(bool calculate = true)
|
||||||
{
|
{
|
||||||
_size = 0;
|
_size = 0;
|
||||||
_calculateCrc = calculateCrc;
|
_calculate = calculate;
|
||||||
_crc = CRC_INIT_VAL;
|
_crc = CRC_INIT_VAL;
|
||||||
}
|
}
|
||||||
void ReleaseStream() { _stream.Release(); }
|
void InitCRC() { _crc = CRC_INIT_VAL; }
|
||||||
UInt64 GetSize() const { return _size; }
|
UInt64 GetSize() const { return _size; }
|
||||||
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
||||||
void InitCRC() { _crc = CRC_INIT_VAL; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// OutStreamWithSha1.cpp
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "OutStreamWithSha1.h"
|
||||||
|
|
||||||
|
STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
|
{
|
||||||
|
UInt32 realProcessedSize;
|
||||||
|
HRESULT result;
|
||||||
|
if(!_stream)
|
||||||
|
{
|
||||||
|
realProcessedSize = size;
|
||||||
|
result = S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = _stream->Write(data, size, &realProcessedSize);
|
||||||
|
if (_calculate)
|
||||||
|
_sha.Update((const Byte *)data, realProcessedSize);
|
||||||
|
_size += realProcessedSize;
|
||||||
|
if(processedSize != NULL)
|
||||||
|
*processedSize = realProcessedSize;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Executable
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// OutStreamWithSha1.h
|
||||||
|
|
||||||
|
#ifndef __OUTSTREAMWITHSHA1_H
|
||||||
|
#define __OUTSTREAMWITHSHA1_H
|
||||||
|
|
||||||
|
#include "../../../Common/MyCom.h"
|
||||||
|
#include "../../IStream.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../Crypto/Hash/Sha1.h"
|
||||||
|
|
||||||
|
|
||||||
|
class COutStreamWithSha1:
|
||||||
|
public ISequentialOutStream,
|
||||||
|
public CMyUnknownImp
|
||||||
|
{
|
||||||
|
CMyComPtr<ISequentialOutStream> _stream;
|
||||||
|
UInt64 _size;
|
||||||
|
NCrypto::NSha1::CContext _sha;
|
||||||
|
bool _calculate;
|
||||||
|
public:
|
||||||
|
MY_UNKNOWN_IMP
|
||||||
|
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||||
|
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||||
|
void ReleaseStream() { _stream.Release(); }
|
||||||
|
void Init(bool calculate = true)
|
||||||
|
{
|
||||||
|
_size = 0;
|
||||||
|
_calculate = calculate;
|
||||||
|
_sha.Init();
|
||||||
|
}
|
||||||
|
void InitSha1() { _sha.Init(); }
|
||||||
|
UInt64 GetSize() const { return _size; }
|
||||||
|
void Final(Byte *digest) { _sha.Final(digest); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// StdAfx.h
|
||||||
|
|
||||||
|
#ifndef __STDAFX_H
|
||||||
|
#define __STDAFX_H
|
||||||
|
|
||||||
|
#include "../../../Common/MyWindows.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+477
@@ -0,0 +1,477 @@
|
|||||||
|
// WimHandler.cpp
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "Common/IntToString.h"
|
||||||
|
#include "Common/Defs.h"
|
||||||
|
#include "Common/ComTry.h"
|
||||||
|
|
||||||
|
#include "Windows/PropVariant.h"
|
||||||
|
|
||||||
|
#include "../../Common/StreamUtils.h"
|
||||||
|
#include "../../Common/ProgressUtils.h"
|
||||||
|
|
||||||
|
#include "WimHandler.h"
|
||||||
|
|
||||||
|
using namespace NWindows;
|
||||||
|
|
||||||
|
namespace NArchive {
|
||||||
|
namespace NWim {
|
||||||
|
|
||||||
|
#define WIM_DETAILS
|
||||||
|
|
||||||
|
#ifdef WIM_DETAILS
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kpidVolume = kpidUserDefined,
|
||||||
|
kpidOffset,
|
||||||
|
kpidLinks
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STATPROPSTG kProperties[] =
|
||||||
|
{
|
||||||
|
{ NULL, kpidPath, VT_BSTR},
|
||||||
|
{ NULL, kpidIsFolder, VT_BOOL},
|
||||||
|
{ NULL, kpidSize, VT_UI8},
|
||||||
|
{ NULL, kpidPackedSize, VT_UI8},
|
||||||
|
{ NULL, kpidAttributes, VT_UI8},
|
||||||
|
{ NULL, kpidMethod, VT_BSTR},
|
||||||
|
{ NULL, kpidCreationTime, VT_FILETIME},
|
||||||
|
{ NULL, kpidLastAccessTime, VT_FILETIME},
|
||||||
|
{ NULL, kpidLastWriteTime, VT_FILETIME}
|
||||||
|
|
||||||
|
#ifdef WIM_DETAILS
|
||||||
|
, { L"Volume", kpidVolume, VT_UI4}
|
||||||
|
, { L"Offset", kpidOffset, VT_UI8}
|
||||||
|
, { L"Links", kpidLinks, VT_UI4}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wchar_t *kStreamsNamePrefix = L"Files" WSTRING_PATH_SEPARATOR;
|
||||||
|
static const wchar_t *kMethodLZX = L"LZX";
|
||||||
|
static const wchar_t *kMethodCopy = L"Copy";
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
|
||||||
|
{
|
||||||
|
value->vt = VT_EMPTY;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
|
||||||
|
{
|
||||||
|
*numProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,
|
||||||
|
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||||
|
{
|
||||||
|
if(index >= sizeof(kProperties) / sizeof(kProperties[0]))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
const STATPROPSTG &srcItem = kProperties[index];
|
||||||
|
*propID = srcItem.propid;
|
||||||
|
*varType = srcItem.vt;
|
||||||
|
if (srcItem.lpwstrName == 0)
|
||||||
|
*name = 0;
|
||||||
|
else
|
||||||
|
*name = ::SysAllocString(srcItem.lpwstrName);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
|
||||||
|
{
|
||||||
|
*numProperties = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
|
||||||
|
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
NWindows::NCOM::CPropVariant propVariant;
|
||||||
|
if (index < (UInt32)m_Database.Items.Size())
|
||||||
|
{
|
||||||
|
const CItem &item = m_Database.Items[index];
|
||||||
|
const CStreamInfo *si = NULL;
|
||||||
|
if (item.StreamIndex >= 0)
|
||||||
|
si = &m_Database.Streams[item.StreamIndex];
|
||||||
|
|
||||||
|
switch(propID)
|
||||||
|
{
|
||||||
|
case kpidPath:
|
||||||
|
if (item.HasMetadata)
|
||||||
|
propVariant = item.Name;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wchar_t sz[32];
|
||||||
|
ConvertUInt64ToString(item.StreamIndex, sz);
|
||||||
|
UString s = sz;
|
||||||
|
while (s.Length() < m_NameLenForStreams)
|
||||||
|
s = L'0' + s;
|
||||||
|
s = UString(kStreamsNamePrefix) + s;
|
||||||
|
propVariant = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kpidIsFolder:
|
||||||
|
propVariant = item.IsDirectory();
|
||||||
|
break;
|
||||||
|
case kpidAttributes:
|
||||||
|
if (item.HasMetadata)
|
||||||
|
propVariant = item.Attributes;
|
||||||
|
break;
|
||||||
|
case kpidCreationTime:
|
||||||
|
if (item.HasMetadata)
|
||||||
|
propVariant = item.CreationTime;
|
||||||
|
break;
|
||||||
|
case kpidLastAccessTime:
|
||||||
|
if (item.HasMetadata)
|
||||||
|
propVariant = item.LastAccessTime;
|
||||||
|
break;
|
||||||
|
case kpidLastWriteTime:
|
||||||
|
if (item.HasMetadata)
|
||||||
|
propVariant = item.LastWriteTime;
|
||||||
|
break;
|
||||||
|
case kpidPackedSize:
|
||||||
|
if (si)
|
||||||
|
propVariant = si->Resource.PackSize;
|
||||||
|
else
|
||||||
|
propVariant = (UInt64)0;
|
||||||
|
break;
|
||||||
|
case kpidSize:
|
||||||
|
if (si)
|
||||||
|
propVariant = si->Resource.UnpackSize;
|
||||||
|
else
|
||||||
|
propVariant = (UInt64)0;
|
||||||
|
break;
|
||||||
|
case kpidMethod:
|
||||||
|
if (si)
|
||||||
|
if (si->Resource.IsCompressed())
|
||||||
|
propVariant = kMethodLZX;
|
||||||
|
else
|
||||||
|
propVariant = kMethodCopy;
|
||||||
|
break;
|
||||||
|
#ifdef WIM_DETAILS
|
||||||
|
case kpidVolume:
|
||||||
|
if (si)
|
||||||
|
propVariant = (UInt32)si->PartNumber;
|
||||||
|
break;
|
||||||
|
case kpidOffset:
|
||||||
|
if (si)
|
||||||
|
propVariant = (UInt64)si->Resource.Offset;
|
||||||
|
break;
|
||||||
|
case kpidLinks:
|
||||||
|
if (si)
|
||||||
|
propVariant = (UInt32)si->RefCount;
|
||||||
|
else
|
||||||
|
propVariant = (UInt64)0;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index -= m_Database.Items.Size();
|
||||||
|
{
|
||||||
|
switch(propID)
|
||||||
|
{
|
||||||
|
case kpidPath:
|
||||||
|
{
|
||||||
|
wchar_t sz[32];
|
||||||
|
ConvertUInt64ToString(m_Xmls[index].VolIndex, sz);
|
||||||
|
UString s = (UString)sz + L".xml";
|
||||||
|
propVariant = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kpidIsFolder:
|
||||||
|
propVariant = false;
|
||||||
|
break;
|
||||||
|
case kpidPackedSize:
|
||||||
|
case kpidSize:
|
||||||
|
propVariant = (UInt64)m_Xmls[index].Data.GetCapacity();
|
||||||
|
break;
|
||||||
|
case kpidMethod:
|
||||||
|
propVariant = L"Copy";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
propVariant.Detach(value);
|
||||||
|
return S_OK;
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
|
class CVolumeName
|
||||||
|
{
|
||||||
|
// UInt32 _volIndex;
|
||||||
|
UString _before;
|
||||||
|
UString _after;
|
||||||
|
public:
|
||||||
|
CVolumeName() {};
|
||||||
|
|
||||||
|
void InitName(const UString &name)
|
||||||
|
{
|
||||||
|
// _volIndex = 1;
|
||||||
|
int dotPos = name.ReverseFind('.');
|
||||||
|
if (dotPos < 0)
|
||||||
|
dotPos = name.Length();
|
||||||
|
_before = name.Left(dotPos);
|
||||||
|
_after = name.Mid(dotPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
UString GetNextName(UInt32 index)
|
||||||
|
{
|
||||||
|
wchar_t s[32];
|
||||||
|
ConvertUInt64ToString((index), s);
|
||||||
|
return _before + (UString)s + _after;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||||
|
const UInt64 * /* maxCheckStartPosition */,
|
||||||
|
IArchiveOpenCallback *openArchiveCallback)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
Close();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||||
|
|
||||||
|
CVolumeName seqName;
|
||||||
|
if (openArchiveCallback != NULL)
|
||||||
|
openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||||
|
|
||||||
|
UInt32 numVolumes = 1;
|
||||||
|
int firstVolumeIndex = -1;
|
||||||
|
for (UInt32 i = 1; i <= numVolumes; i++)
|
||||||
|
{
|
||||||
|
CMyComPtr<IInStream> curStream;
|
||||||
|
if (i != 1)
|
||||||
|
{
|
||||||
|
UString fullName = seqName.GetNextName(i);
|
||||||
|
HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
|
||||||
|
if (result == S_FALSE)
|
||||||
|
continue;
|
||||||
|
if (result != S_OK)
|
||||||
|
return result;
|
||||||
|
if (!curStream)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
curStream = inStream;
|
||||||
|
CHeader header;
|
||||||
|
HRESULT res = NWim::ReadHeader(curStream, header);
|
||||||
|
if (res != S_OK)
|
||||||
|
{
|
||||||
|
if (i == 1)
|
||||||
|
return res;
|
||||||
|
if (res == S_FALSE)
|
||||||
|
continue;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (firstVolumeIndex >= 0)
|
||||||
|
if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header))
|
||||||
|
break;
|
||||||
|
if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream)
|
||||||
|
break;
|
||||||
|
CXml xml;
|
||||||
|
xml.VolIndex = header.PartNumber;
|
||||||
|
res = OpenArchive(curStream, header, xml.Data, m_Database);
|
||||||
|
if (res != S_OK)
|
||||||
|
{
|
||||||
|
if (i == 1)
|
||||||
|
return res;
|
||||||
|
if (res == S_FALSE)
|
||||||
|
continue;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_Volumes.Size() <= header.PartNumber)
|
||||||
|
m_Volumes.Add(CVolume());
|
||||||
|
CVolume &volume = m_Volumes[header.PartNumber];
|
||||||
|
volume.Header = header;
|
||||||
|
volume.Stream = curStream;
|
||||||
|
|
||||||
|
firstVolumeIndex = header.PartNumber;
|
||||||
|
|
||||||
|
bool needAddXml = true;
|
||||||
|
if (m_Xmls.Size() != 0)
|
||||||
|
if (xml.Data == m_Xmls[0].Data)
|
||||||
|
needAddXml = false;
|
||||||
|
if (needAddXml)
|
||||||
|
m_Xmls.Add(xml);
|
||||||
|
|
||||||
|
if (i == 1)
|
||||||
|
{
|
||||||
|
if (header.PartNumber != 1)
|
||||||
|
break;
|
||||||
|
if (!openVolumeCallback)
|
||||||
|
break;
|
||||||
|
numVolumes = header.NumParts;
|
||||||
|
{
|
||||||
|
NCOM::CPropVariant propVariant;
|
||||||
|
RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));
|
||||||
|
if (propVariant.vt != VT_BSTR)
|
||||||
|
break;
|
||||||
|
seqName.InitName(propVariant.bstrVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RINOK(SortDatabase(m_Database));
|
||||||
|
|
||||||
|
wchar_t sz[32];
|
||||||
|
ConvertUInt64ToString(m_Database.Streams.Size(), sz);
|
||||||
|
m_NameLenForStreams = MyStringLen(sz);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Close()
|
||||||
|
{
|
||||||
|
m_Database.Clear();
|
||||||
|
m_Volumes.Clear();
|
||||||
|
m_Xmls.Clear();
|
||||||
|
m_NameLenForStreams = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||||
|
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
bool allFilesMode = (numItems == UInt32(-1));
|
||||||
|
|
||||||
|
if (allFilesMode)
|
||||||
|
numItems = m_Database.Items.Size() + m_Xmls.Size();
|
||||||
|
if (numItems == 0)
|
||||||
|
return S_OK;
|
||||||
|
bool testMode = (_aTestMode != 0);
|
||||||
|
|
||||||
|
UInt32 i;
|
||||||
|
UInt64 totalSize = 0;
|
||||||
|
for (i = 0; i < numItems; i++)
|
||||||
|
{
|
||||||
|
UInt32 index = allFilesMode ? i : indices[i];
|
||||||
|
if (index < (UInt32)m_Database.Items.Size())
|
||||||
|
{
|
||||||
|
int streamIndex = m_Database.Items[index].StreamIndex;
|
||||||
|
if (streamIndex >= 0)
|
||||||
|
{
|
||||||
|
const CStreamInfo &si = m_Database.Streams[streamIndex];
|
||||||
|
totalSize += si.Resource.UnpackSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
totalSize += m_Xmls[index - (UInt32)m_Database.Items.Size()].Data.GetCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
RINOK(extractCallback->SetTotal(totalSize));
|
||||||
|
|
||||||
|
UInt64 currentTotalSize = 0;
|
||||||
|
UInt64 currentItemSize = 0;
|
||||||
|
|
||||||
|
int prevSuccessStreamIndex = -1;
|
||||||
|
|
||||||
|
CUnpacker unpacker;
|
||||||
|
|
||||||
|
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||||
|
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||||
|
localProgressSpec->Init(extractCallback, false);
|
||||||
|
|
||||||
|
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||||
|
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||||
|
|
||||||
|
for (i = 0; i < numItems; currentTotalSize += currentItemSize)
|
||||||
|
{
|
||||||
|
currentItemSize = 0;
|
||||||
|
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
||||||
|
UInt32 index = allFilesMode ? i : indices[i];
|
||||||
|
i++;
|
||||||
|
Int32 askMode = testMode ?
|
||||||
|
NArchive::NExtract::NAskMode::kTest :
|
||||||
|
NArchive::NExtract::NAskMode::kExtract;
|
||||||
|
|
||||||
|
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||||
|
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||||
|
if (index >= (UInt32)m_Database.Items.Size())
|
||||||
|
{
|
||||||
|
if(!testMode && (!realOutStream))
|
||||||
|
continue;
|
||||||
|
RINOK(extractCallback->PrepareOperation(askMode));
|
||||||
|
const CByteBuffer &data = m_Xmls[index - (UInt32)m_Database.Items.Size()].Data;
|
||||||
|
currentItemSize = data.GetCapacity();
|
||||||
|
if (realOutStream)
|
||||||
|
{
|
||||||
|
RINOK(WriteStream(realOutStream, (const Byte *)data, (UInt32)data.GetCapacity(), NULL));
|
||||||
|
realOutStream.Release();
|
||||||
|
}
|
||||||
|
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CItem &item = m_Database.Items[index];
|
||||||
|
int streamIndex = item.StreamIndex;
|
||||||
|
if (streamIndex < 0)
|
||||||
|
{
|
||||||
|
if(!testMode && (!realOutStream))
|
||||||
|
continue;
|
||||||
|
RINOK(extractCallback->PrepareOperation(askMode));
|
||||||
|
realOutStream.Release();
|
||||||
|
RINOK(extractCallback->SetOperationResult(item.HasStream() ?
|
||||||
|
NArchive::NExtract::NOperationResult::kDataError :
|
||||||
|
NArchive::NExtract::NOperationResult::kOK));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CStreamInfo &si = m_Database.Streams[streamIndex];
|
||||||
|
currentItemSize = si.Resource.UnpackSize;
|
||||||
|
|
||||||
|
if(!testMode && (!realOutStream))
|
||||||
|
continue;
|
||||||
|
RINOK(extractCallback->PrepareOperation(askMode));
|
||||||
|
Int32 opRes = NArchive::NExtract::NOperationResult::kOK;
|
||||||
|
if (streamIndex != prevSuccessStreamIndex || realOutStream)
|
||||||
|
{
|
||||||
|
Byte digest[20];
|
||||||
|
localCompressProgressSpec->Init(progress, ¤tTotalSize, ¤tTotalSize);
|
||||||
|
HRESULT res = unpacker.Unpack(m_Volumes[si.PartNumber].Stream, si.Resource, realOutStream, compressProgress, digest);
|
||||||
|
if (res == S_OK)
|
||||||
|
{
|
||||||
|
if (memcmp(digest, si.Hash, kHashSize) == 0)
|
||||||
|
prevSuccessStreamIndex = streamIndex;
|
||||||
|
else
|
||||||
|
opRes = NArchive::NExtract::NOperationResult::kCRCError;
|
||||||
|
}
|
||||||
|
else if (res == S_FALSE)
|
||||||
|
opRes = NArchive::NExtract::NOperationResult::kDataError;
|
||||||
|
else
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
realOutStream.Release();
|
||||||
|
RINOK(extractCallback->SetOperationResult(opRes));
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||||
|
{
|
||||||
|
*numItems = m_Database.Items.Size() + m_Xmls.Size();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
Executable
+60
@@ -0,0 +1,60 @@
|
|||||||
|
// WimHandler.h
|
||||||
|
|
||||||
|
#ifndef __ARCHIVE_WIM_HANDLER_H
|
||||||
|
#define __ARCHIVE_WIM_HANDLER_H
|
||||||
|
|
||||||
|
#include "Common/MyCom.h"
|
||||||
|
#include "../IArchive.h"
|
||||||
|
#include "WimIn.h"
|
||||||
|
|
||||||
|
namespace NArchive {
|
||||||
|
namespace NWim {
|
||||||
|
|
||||||
|
struct CVolume
|
||||||
|
{
|
||||||
|
CHeader Header;
|
||||||
|
CMyComPtr<IInStream> Stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CXml
|
||||||
|
{
|
||||||
|
CByteBuffer Data;
|
||||||
|
UInt16 VolIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHandler:
|
||||||
|
public IInArchive,
|
||||||
|
public CMyUnknownImp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MY_UNKNOWN_IMP1(IInArchive)
|
||||||
|
|
||||||
|
STDMETHOD(Open)(IInStream *stream,
|
||||||
|
const UInt64 *maxCheckStartPosition,
|
||||||
|
IArchiveOpenCallback *openArchiveCallback);
|
||||||
|
STDMETHOD(Close)();
|
||||||
|
STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
|
||||||
|
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
||||||
|
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
|
||||||
|
Int32 testMode, IArchiveExtractCallback *extractCallback);
|
||||||
|
|
||||||
|
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
|
||||||
|
|
||||||
|
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties);
|
||||||
|
STDMETHOD(GetPropertyInfo)(UInt32 index,
|
||||||
|
BSTR *name, PROPID *propID, VARTYPE *varType);
|
||||||
|
|
||||||
|
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties);
|
||||||
|
STDMETHOD(GetArchivePropertyInfo)(UInt32 index,
|
||||||
|
BSTR *name, PROPID *propID, VARTYPE *varType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CDatabase m_Database;
|
||||||
|
CObjectVector<CVolume> m_Volumes;
|
||||||
|
CObjectVector<CXml> m_Xmls;
|
||||||
|
int m_NameLenForStreams;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+467
@@ -0,0 +1,467 @@
|
|||||||
|
// Archive/WimIn.cpp
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "Common/MyCom.h"
|
||||||
|
#include "Common/IntToString.h"
|
||||||
|
|
||||||
|
#include "../../Common/StreamUtils.h"
|
||||||
|
#include "../../Common/StreamObjects.h"
|
||||||
|
#include "../../Common/LimitedStreams.h"
|
||||||
|
|
||||||
|
#include "../Common/OutStreamWithSha1.h"
|
||||||
|
|
||||||
|
#include "WimIn.h"
|
||||||
|
|
||||||
|
namespace NArchive{
|
||||||
|
namespace NWim{
|
||||||
|
|
||||||
|
static const int kChunkSizeBits = 15;
|
||||||
|
static const UInt32 kChunkSize = (1 << kChunkSizeBits);
|
||||||
|
|
||||||
|
static HRESULT ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size)
|
||||||
|
{
|
||||||
|
UInt32 realProcessedSize;
|
||||||
|
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||||
|
return (realProcessedSize == size) ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
|
||||||
|
#define WIM_LITTLE_ENDIAN_UNALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIM_LITTLE_ENDIAN_UNALIGN
|
||||||
|
static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; }
|
||||||
|
static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; }
|
||||||
|
static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; }
|
||||||
|
#else
|
||||||
|
static UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); }
|
||||||
|
static UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); }
|
||||||
|
static UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
|
||||||
|
{
|
||||||
|
ft->dwLowDateTime = GetUInt32FromMem(p);
|
||||||
|
ft->dwHighDateTime = GetUInt32FromMem(p + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource,
|
||||||
|
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
|
||||||
|
{
|
||||||
|
RINOK(inStream->Seek(resource.Offset, STREAM_SEEK_SET, NULL));
|
||||||
|
|
||||||
|
CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream();
|
||||||
|
CMyComPtr<ISequentialInStream> limitedStream = limitedStreamSpec;
|
||||||
|
limitedStreamSpec->SetStream(inStream);
|
||||||
|
|
||||||
|
if (!copyCoder)
|
||||||
|
{
|
||||||
|
copyCoderSpec = new NCompress::CCopyCoder;
|
||||||
|
copyCoder = copyCoderSpec;
|
||||||
|
}
|
||||||
|
if (!resource.IsCompressed())
|
||||||
|
{
|
||||||
|
if (resource.PackSize != resource.UnpackSize)
|
||||||
|
return S_FALSE;
|
||||||
|
limitedStreamSpec->Init(resource.PackSize);
|
||||||
|
return copyCoder->Code(limitedStreamSpec, outStream, NULL, NULL, progress);
|
||||||
|
}
|
||||||
|
if (resource.UnpackSize == 0)
|
||||||
|
return S_OK;
|
||||||
|
UInt64 numChunks = (resource.UnpackSize + kChunkSize - 1) >> kChunkSizeBits;
|
||||||
|
unsigned entrySize = ((resource.UnpackSize > (UInt64)1 << 32) ? 8 : 4);
|
||||||
|
UInt64 sizesBufSize64 = entrySize * (numChunks - 1);
|
||||||
|
UInt32 sizesBufSize = (UInt32)sizesBufSize64;
|
||||||
|
if (sizesBufSize != sizesBufSize64)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
if (sizesBufSize > sizesBuf.GetCapacity())
|
||||||
|
{
|
||||||
|
sizesBuf.Free();
|
||||||
|
sizesBuf.SetCapacity(sizesBufSize);
|
||||||
|
}
|
||||||
|
RINOK(ReadBytes(inStream, (Byte *)sizesBuf, sizesBufSize));
|
||||||
|
const Byte *p = (const Byte *)sizesBuf;
|
||||||
|
|
||||||
|
if (!lzxDecoder)
|
||||||
|
{
|
||||||
|
lzxDecoderSpec = new NCompress::NLzx::CDecoder(true);
|
||||||
|
lzxDecoder = lzxDecoderSpec;
|
||||||
|
RINOK(lzxDecoderSpec->SetParams(kChunkSizeBits));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 baseOffset = resource.Offset + sizesBufSize64;
|
||||||
|
UInt64 outProcessed = 0;
|
||||||
|
for (UInt32 i = 0; i < (UInt32)numChunks; i++)
|
||||||
|
{
|
||||||
|
UInt64 offset = 0;
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
if (entrySize == 4)
|
||||||
|
offset = GetUInt32FromMem(p);
|
||||||
|
else
|
||||||
|
offset = GetUInt64FromMem(p);
|
||||||
|
p += entrySize;
|
||||||
|
}
|
||||||
|
UInt64 nextOffset = resource.PackSize - sizesBufSize64;
|
||||||
|
if (i + 1 < (UInt32)numChunks)
|
||||||
|
if (entrySize == 4)
|
||||||
|
nextOffset = GetUInt32FromMem(p);
|
||||||
|
else
|
||||||
|
nextOffset = GetUInt64FromMem(p);
|
||||||
|
if (nextOffset < offset)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
RINOK(inStream->Seek(baseOffset + offset, STREAM_SEEK_SET, NULL));
|
||||||
|
UInt64 inSize = nextOffset - offset;
|
||||||
|
limitedStreamSpec->Init(inSize);
|
||||||
|
|
||||||
|
if (progress)
|
||||||
|
{
|
||||||
|
RINOK(progress->SetRatioInfo(&offset, &outProcessed));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 outSize = kChunkSize;
|
||||||
|
if (outProcessed + outSize > resource.UnpackSize)
|
||||||
|
outSize = (UInt32)(resource.UnpackSize - outProcessed);
|
||||||
|
UInt64 outSize64 = outSize;
|
||||||
|
lzxDecoderSpec->SetKeepHistory(false, 0);
|
||||||
|
ICompressCoder *coder = (inSize == outSize) ? copyCoder : lzxDecoder;
|
||||||
|
RINOK(coder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));
|
||||||
|
outProcessed += outSize;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource,
|
||||||
|
ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)
|
||||||
|
{
|
||||||
|
COutStreamWithSha1 *shaStreamSpec = new COutStreamWithSha1();
|
||||||
|
CMyComPtr<ISequentialOutStream> shaStream = shaStreamSpec;
|
||||||
|
shaStreamSpec->SetStream(outStream);
|
||||||
|
shaStreamSpec->Init(digest != NULL);
|
||||||
|
HRESULT result = Unpack(inStream, resource, shaStream, progress);
|
||||||
|
if (digest)
|
||||||
|
shaStreamSpec->Final(digest);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT UnpackData(IInStream *inStream, const CResource &resource, CByteBuffer &buf, Byte *digest)
|
||||||
|
{
|
||||||
|
size_t size = (size_t)resource.UnpackSize;
|
||||||
|
if (size != resource.UnpackSize)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
buf.Free();
|
||||||
|
buf.SetCapacity(size);
|
||||||
|
|
||||||
|
CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2();
|
||||||
|
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
|
||||||
|
outStreamSpec->Init((Byte *)buf, size);
|
||||||
|
|
||||||
|
CUnpacker unpacker;
|
||||||
|
return unpacker.Unpack(inStream, resource, outStream, NULL, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const UInt32 kSignatureSize = 8;
|
||||||
|
static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
|
||||||
|
|
||||||
|
static void GetResource(const Byte *p, CResource &res)
|
||||||
|
{
|
||||||
|
res.Flags = p[7];
|
||||||
|
res.PackSize = GetUInt64FromMem(p) & (((UInt64)1 << 56) - 1);
|
||||||
|
res.Offset = GetUInt64FromMem(p + 8);
|
||||||
|
res.UnpackSize = GetUInt64FromMem(p + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetStream(const Byte *p, CStreamInfo &s)
|
||||||
|
{
|
||||||
|
GetResource(p, s.Resource);
|
||||||
|
s.PartNumber = GetUInt16FromMem(p + 24);
|
||||||
|
s.RefCount = GetUInt32FromMem(p + 26);
|
||||||
|
memcpy(s.Hash, p + 30, kHashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
|
||||||
|
const UString &prefix, CObjectVector<CItem> &items)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pos + 8 > size)
|
||||||
|
return S_FALSE;
|
||||||
|
const Byte *p = base + pos;
|
||||||
|
UInt64 length = GetUInt64FromMem(p);
|
||||||
|
if (length == 0)
|
||||||
|
return S_OK;
|
||||||
|
if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62))
|
||||||
|
return S_FALSE;
|
||||||
|
CItem item;
|
||||||
|
item.Attributes = GetUInt32FromMem(p + 8);
|
||||||
|
// item.SecurityId = GetUInt32FromMem(p + 0xC);
|
||||||
|
UInt64 subdirOffset = GetUInt64FromMem(p + 0x10);
|
||||||
|
GetFileTimeFromMem(p + 0x28, &item.CreationTime);
|
||||||
|
GetFileTimeFromMem(p + 0x30, &item.LastAccessTime);
|
||||||
|
GetFileTimeFromMem(p + 0x38, &item.LastWriteTime);
|
||||||
|
memcpy(item.Hash, p + 0x40, kHashSize);
|
||||||
|
|
||||||
|
// UInt16 shortNameLen = GetUInt16FromMem(p + 98);
|
||||||
|
UInt16 fileNameLen = GetUInt16FromMem(p + 100);
|
||||||
|
|
||||||
|
size_t tempPos = pos + 102;
|
||||||
|
if (tempPos + fileNameLen > size)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1);
|
||||||
|
MyStringCopy(sz, (const wchar_t *)prefix);
|
||||||
|
sz += prefix.Length();
|
||||||
|
for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2)
|
||||||
|
*sz++ = GetUInt16FromMem(base + tempPos + i);
|
||||||
|
*sz++ = '\0';
|
||||||
|
item.Name.ReleaseBuffer();
|
||||||
|
if (fileNameLen == 0 && item.IsDirectory() && !item.HasStream())
|
||||||
|
{
|
||||||
|
item.Attributes = 0x10; // some swm archives have system/hidden attributes for root
|
||||||
|
item.Name.Delete(item.Name.Length() - 1);
|
||||||
|
}
|
||||||
|
items.Add(item);
|
||||||
|
pos += (size_t)length;
|
||||||
|
if (item.IsDirectory() && (subdirOffset != 0))
|
||||||
|
{
|
||||||
|
if (subdirOffset >= size)
|
||||||
|
return S_FALSE;
|
||||||
|
RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT ParseDir(const Byte *base, size_t size,
|
||||||
|
const UString &prefix, CObjectVector<CItem> &items)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
if (pos + 8 > size)
|
||||||
|
return S_FALSE;
|
||||||
|
const Byte *p = base + pos;
|
||||||
|
UInt32 totalLength = GetUInt32FromMem(p);
|
||||||
|
// UInt32 numEntries = GetUInt32FromMem(p + 4);
|
||||||
|
pos += 8;
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
CRecordVector<UInt64> entryLens;
|
||||||
|
UInt64 sum = 0;
|
||||||
|
for (UInt32 i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
if (pos + 8 > size)
|
||||||
|
return S_FALSE;
|
||||||
|
UInt64 len = GetUInt64FromMem(p + pos);
|
||||||
|
entryLens.Add(len);
|
||||||
|
sum += len;
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
pos += sum; // skeep security descriptors
|
||||||
|
while ((pos & 7) != 0)
|
||||||
|
pos++;
|
||||||
|
if (pos != totalLength)
|
||||||
|
return S_FALSE;
|
||||||
|
*/
|
||||||
|
pos = totalLength;
|
||||||
|
}
|
||||||
|
return ParseDirItem(base, pos, size, prefix, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CompareHashRefs(const int *p1, const int *p2, void *param)
|
||||||
|
{
|
||||||
|
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
|
||||||
|
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
|
||||||
|
{
|
||||||
|
int res = MyCompare(p1->PartNumber, p2->PartNumber);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompareItems(void *const *a1, void *const *a2, void * /* param */)
|
||||||
|
{
|
||||||
|
const CItem &i1 = **((const CItem **)a1);
|
||||||
|
const CItem &i2 = **((const CItem **)a2);
|
||||||
|
|
||||||
|
if (i1.IsDirectory() != i2.IsDirectory())
|
||||||
|
return (i1.IsDirectory()) ? 1 : -1;
|
||||||
|
if (i1.IsDirectory())
|
||||||
|
return -MyStringCompareNoCase(i1.Name, i2.Name);
|
||||||
|
|
||||||
|
int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
return MyStringCompareNoCase(i1.Name, i2.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FindHash(const CRecordVector<CStreamInfo> &streams,
|
||||||
|
const CRecordVector<int> &sortedByHash, const Byte *hash)
|
||||||
|
{
|
||||||
|
int left = 0, right = streams.Size();
|
||||||
|
while (left != right)
|
||||||
|
{
|
||||||
|
int mid = (left + right) / 2;
|
||||||
|
int streamIndex = sortedByHash[mid];
|
||||||
|
UInt32 i;
|
||||||
|
const Byte *hash2 = streams[streamIndex].Hash;
|
||||||
|
for (i = 0; i < kHashSize; i++)
|
||||||
|
if (hash[i] != hash2[i])
|
||||||
|
break;
|
||||||
|
if (i == kHashSize)
|
||||||
|
return streamIndex;
|
||||||
|
if (hash[i] < hash2[i])
|
||||||
|
right = mid;
|
||||||
|
else
|
||||||
|
left = mid + 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT ReadHeader(IInStream *inStream, CHeader &h)
|
||||||
|
{
|
||||||
|
const UInt32 kHeaderSizeMax = 0xD0;
|
||||||
|
Byte p[kHeaderSizeMax];
|
||||||
|
RINOK(ReadBytes(inStream, p, kHeaderSizeMax));
|
||||||
|
UInt32 haderSize = GetUInt32FromMem(p + 8);
|
||||||
|
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
||||||
|
return S_FALSE;
|
||||||
|
if (haderSize < 0x74)
|
||||||
|
return S_FALSE;
|
||||||
|
h.Version = GetUInt32FromMem(p + 0x0C);
|
||||||
|
h.Flags = GetUInt32FromMem(p + 0x10);
|
||||||
|
if (!h.IsSupported())
|
||||||
|
return S_FALSE;
|
||||||
|
if (GetUInt32FromMem(p + 0x14) != kChunkSize)
|
||||||
|
return S_FALSE;
|
||||||
|
memcpy(h.Guid, p + 0x18, 16);
|
||||||
|
h.PartNumber = GetUInt16FromMem(p + 0x28);
|
||||||
|
h.NumParts = GetUInt16FromMem(p + 0x2A);
|
||||||
|
int offset = 0x2C;
|
||||||
|
if (h.IsNewVersion())
|
||||||
|
{
|
||||||
|
h.NumImages = GetUInt32FromMem(p + offset);
|
||||||
|
offset += 4;
|
||||||
|
}
|
||||||
|
GetResource(p + offset, h.OffsetResource);
|
||||||
|
GetResource(p + offset + 0x18, h.XmlResource);
|
||||||
|
GetResource(p + offset + 0x30, h.MetadataResource);
|
||||||
|
/*
|
||||||
|
if (h.IsNewVersion())
|
||||||
|
{
|
||||||
|
if (haderSize < 0xD0)
|
||||||
|
return S_FALSE;
|
||||||
|
GetResource(p + offset + 0x4C, h.IntegrityResource);
|
||||||
|
h.BootIndex = GetUInt32FromMem(p + 0x48);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
|
||||||
|
{
|
||||||
|
CByteBuffer offsetBuf;
|
||||||
|
RINOK(UnpackData(inStream, h.OffsetResource, offsetBuf, NULL));
|
||||||
|
for (size_t i = 0; i + kStreamInfoSize <= offsetBuf.GetCapacity(); i += kStreamInfoSize)
|
||||||
|
{
|
||||||
|
CStreamInfo s;
|
||||||
|
GetStream((const Byte *)offsetBuf + i, s);
|
||||||
|
if (s.PartNumber == h.PartNumber)
|
||||||
|
db.Streams.Add(s);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDatabase &db)
|
||||||
|
{
|
||||||
|
RINOK(UnpackData(inStream, h.XmlResource, xml, NULL));
|
||||||
|
|
||||||
|
RINOK(ReadStreams(inStream, h, db));
|
||||||
|
bool needBootMetadata = !h.MetadataResource.IsEmpty();
|
||||||
|
if (h.PartNumber == 1)
|
||||||
|
{
|
||||||
|
int imageIndex = 1;
|
||||||
|
for (int j = 0; j < db.Streams.Size(); j++)
|
||||||
|
{
|
||||||
|
// if (imageIndex > 1) break;
|
||||||
|
const CStreamInfo &si = db.Streams[j];
|
||||||
|
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
|
||||||
|
continue;
|
||||||
|
Byte hash[kHashSize];
|
||||||
|
CByteBuffer metadata;
|
||||||
|
RINOK(UnpackData(inStream, si.Resource, metadata, hash));
|
||||||
|
if (memcmp(hash, si.Hash, kHashSize) != 0)
|
||||||
|
return S_FALSE;
|
||||||
|
wchar_t sz[32];
|
||||||
|
ConvertUInt64ToString(imageIndex++, sz);
|
||||||
|
UString s = sz;
|
||||||
|
s += WCHAR_PATH_SEPARATOR;
|
||||||
|
RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
|
||||||
|
if (needBootMetadata)
|
||||||
|
if (h.MetadataResource.Offset == si.Resource.Offset)
|
||||||
|
needBootMetadata = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needBootMetadata)
|
||||||
|
{
|
||||||
|
CByteBuffer metadata;
|
||||||
|
RINOK(UnpackData(inStream, h.MetadataResource, metadata, NULL));
|
||||||
|
RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT SortDatabase(CDatabase &db)
|
||||||
|
{
|
||||||
|
db.Streams.Sort(CompareStreamsByPos, NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
CRecordVector<int> sortedByHash;
|
||||||
|
{
|
||||||
|
for (int j = 0; j < db.Streams.Size(); j++)
|
||||||
|
sortedByHash.Add(j);
|
||||||
|
sortedByHash.Sort(CompareHashRefs, &db.Streams);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < db.Items.Size(); i++)
|
||||||
|
{
|
||||||
|
CItem &item = db.Items[i];
|
||||||
|
item.StreamIndex = -1;
|
||||||
|
if (item.HasStream())
|
||||||
|
item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CRecordVector<bool> used;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < db.Streams.Size(); j++)
|
||||||
|
{
|
||||||
|
const CStreamInfo &s = db.Streams[j];
|
||||||
|
used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < db.Items.Size(); i++)
|
||||||
|
{
|
||||||
|
CItem &item = db.Items[i];
|
||||||
|
if (item.StreamIndex >= 0)
|
||||||
|
used[item.StreamIndex] = true;
|
||||||
|
}
|
||||||
|
for (j = 0; j < db.Streams.Size(); j++)
|
||||||
|
if (!used[j])
|
||||||
|
{
|
||||||
|
CItem item;
|
||||||
|
item.StreamIndex = j;
|
||||||
|
item.HasMetadata = false;
|
||||||
|
db.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Items.Sort(CompareItems, NULL);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
Executable
+139
@@ -0,0 +1,139 @@
|
|||||||
|
// Archive/WimIn.h
|
||||||
|
|
||||||
|
#ifndef __ARCHIVE_WIM_IN_H
|
||||||
|
#define __ARCHIVE_WIM_IN_H
|
||||||
|
|
||||||
|
#include "Common/MyString.h"
|
||||||
|
#include "Common/Buffer.h"
|
||||||
|
|
||||||
|
#include "../../Compress/Lzx/LzxDecoder.h"
|
||||||
|
#include "../../Compress/Copy/CopyCoder.h"
|
||||||
|
|
||||||
|
namespace NArchive {
|
||||||
|
namespace NWim {
|
||||||
|
|
||||||
|
namespace NResourceFlags
|
||||||
|
{
|
||||||
|
const Byte Compressed = 4;
|
||||||
|
const Byte kMetadata = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CResource
|
||||||
|
{
|
||||||
|
UInt64 PackSize;
|
||||||
|
UInt64 Offset;
|
||||||
|
UInt64 UnpackSize;
|
||||||
|
Byte Flags;
|
||||||
|
bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
|
||||||
|
bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
|
||||||
|
bool IsEmpty() const { return (UnpackSize == 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace NHeaderFlags
|
||||||
|
{
|
||||||
|
const UInt32 kCompression = 2;
|
||||||
|
const UInt32 kSpanned = 8;
|
||||||
|
const UInt32 kRpFix = 0x80;
|
||||||
|
const UInt32 kXPRESS = 0x20000;
|
||||||
|
const UInt32 kLZX = 0x40000;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CHeader
|
||||||
|
{
|
||||||
|
UInt32 Flags;
|
||||||
|
UInt32 Version;
|
||||||
|
// UInt32 ChunkSize;
|
||||||
|
UInt16 PartNumber;
|
||||||
|
UInt16 NumParts;
|
||||||
|
UInt32 NumImages;
|
||||||
|
Byte Guid[16];
|
||||||
|
CResource OffsetResource;
|
||||||
|
CResource XmlResource;
|
||||||
|
CResource MetadataResource;
|
||||||
|
/*
|
||||||
|
CResource IntegrityResource;
|
||||||
|
UInt32 BootIndex;
|
||||||
|
*/
|
||||||
|
bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }
|
||||||
|
bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0); }
|
||||||
|
bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
|
||||||
|
|
||||||
|
bool IsNewVersion()const { return (Version > 0x010C00); }
|
||||||
|
|
||||||
|
bool AreFromOnArchive(const CHeader &h)
|
||||||
|
{
|
||||||
|
return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const UInt32 kHashSize = 20;
|
||||||
|
const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize;
|
||||||
|
|
||||||
|
struct CStreamInfo
|
||||||
|
{
|
||||||
|
CResource Resource;
|
||||||
|
UInt16 PartNumber;
|
||||||
|
UInt32 RefCount;
|
||||||
|
BYTE Hash[kHashSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CItem
|
||||||
|
{
|
||||||
|
UString Name;
|
||||||
|
UInt32 Attributes;
|
||||||
|
// UInt32 SecurityId;
|
||||||
|
BYTE Hash[kHashSize];
|
||||||
|
FILETIME CreationTime;
|
||||||
|
FILETIME LastAccessTime;
|
||||||
|
FILETIME LastWriteTime;
|
||||||
|
// UInt32 ReparseTag;
|
||||||
|
// UInt64 HardLink;
|
||||||
|
// UInt16 NumStreams;
|
||||||
|
// UInt16 ShortNameLen;
|
||||||
|
int StreamIndex;
|
||||||
|
bool HasMetadata;
|
||||||
|
CItem(): HasMetadata(true), StreamIndex(-1) {}
|
||||||
|
bool IsDirectory() const { return HasMetadata && ((Attributes & 0x10) != 0); }
|
||||||
|
bool HasStream() const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kHashSize; i++)
|
||||||
|
if (Hash[i] != 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CDatabase
|
||||||
|
{
|
||||||
|
CRecordVector<CStreamInfo> Streams;
|
||||||
|
CObjectVector<CItem> Items;
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
Streams.Clear();
|
||||||
|
Items.Clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT ReadHeader(IInStream *inStream, CHeader &header);
|
||||||
|
HRESULT OpenArchive(IInStream *inStream, const CHeader &header, CByteBuffer &xml, CDatabase &database);
|
||||||
|
HRESULT SortDatabase(CDatabase &database);
|
||||||
|
|
||||||
|
class CUnpacker
|
||||||
|
{
|
||||||
|
NCompress::CCopyCoder *copyCoderSpec;
|
||||||
|
CMyComPtr<ICompressCoder> copyCoder;
|
||||||
|
|
||||||
|
NCompress::NLzx::CDecoder *lzxDecoderSpec;
|
||||||
|
CMyComPtr<ICompressCoder> lzxDecoder;
|
||||||
|
|
||||||
|
CByteBuffer sizesBuf;
|
||||||
|
HRESULT Unpack(IInStream *inStream, const CResource &res,
|
||||||
|
ISequentialOutStream *outStream, ICompressProgressInfo *progress);
|
||||||
|
public:
|
||||||
|
HRESULT Unpack(IInStream *inStream, const CResource &res,
|
||||||
|
ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest);
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WimRegister.cpp
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../Common/RegisterArc.h"
|
||||||
|
|
||||||
|
#include "WimHandler.h"
|
||||||
|
static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
|
||||||
|
|
||||||
|
static CArcInfo g_ArcInfo =
|
||||||
|
{ L"Wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, 0 };
|
||||||
|
|
||||||
|
REGISTER_ARC(Wim)
|
||||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@@ -130,6 +130,10 @@ SOURCE=.\StdAfx.h
|
|||||||
# PROP Default_Filter ""
|
# PROP Default_Filter ""
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\Buffer.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\CRC.cpp
|
SOURCE=..\..\..\Common\CRC.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -142,10 +146,18 @@ SOURCE=..\..\..\Common\IntToString.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\MyCom.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\MyException.h
|
SOURCE=..\..\..\Common\MyException.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\MyInitGuid.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\MyString.cpp
|
SOURCE=..\..\..\Common\MyString.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -154,6 +166,10 @@ SOURCE=..\..\..\Common\MyString.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\MyUnknown.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\MyVector.cpp
|
SOURCE=..\..\..\Common\MyVector.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -162,10 +178,18 @@ SOURCE=..\..\..\Common\MyVector.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\MyWindows.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\Common\NewHandler.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\Common\StringConvert.cpp
|
SOURCE=..\..\..\Common\StringConvert.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -1902,6 +1926,14 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Common\OutStreamWithSha1.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Common\OutStreamWithSha1.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\Archive\Common\ParseProperties.cpp
|
SOURCE=..\..\Archive\Common\ParseProperties.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -2349,6 +2381,30 @@ SOURCE=..\..\Archive\Zip\ZipUpdate.cpp
|
|||||||
SOURCE=..\..\Archive\Zip\ZipUpdate.h
|
SOURCE=..\..\Archive\Zip\ZipUpdate.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
|
# Begin Group "Wim"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\WimHandler.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\WimHandler.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\WimIn.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\WimIn.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\WimRegister.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\Archive\IArchive.h
|
SOURCE=..\..\Archive\IArchive.h
|
||||||
@@ -2420,6 +2476,10 @@ SOURCE=..\..\Archive\Tar\tar.ico
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Archive\Wim\wim.ico
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\Archive\Z\Z.ico
|
SOURCE=..\..\Archive\Z\Z.ico
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ AR_COMMON_OBJS = \
|
|||||||
$O\ItemNameUtils.obj \
|
$O\ItemNameUtils.obj \
|
||||||
$O\MultiStream.obj \
|
$O\MultiStream.obj \
|
||||||
$O\OutStreamWithCRC.obj \
|
$O\OutStreamWithCRC.obj \
|
||||||
|
$O\OutStreamWithSha1.obj \
|
||||||
$O\HandlerOut.obj \
|
$O\HandlerOut.obj \
|
||||||
$O\ParseProperties.obj \
|
$O\ParseProperties.obj \
|
||||||
|
|
||||||
@@ -174,6 +175,11 @@ TAR_OBJS = \
|
|||||||
$O\TarUpdate.obj \
|
$O\TarUpdate.obj \
|
||||||
$O\TarRegister.obj \
|
$O\TarRegister.obj \
|
||||||
|
|
||||||
|
WIM_OBJS = \
|
||||||
|
$O\WimHandler.obj \
|
||||||
|
$O\WimIn.obj \
|
||||||
|
$O\WimRegister.obj \
|
||||||
|
|
||||||
Z_OBJS = \
|
Z_OBJS = \
|
||||||
$O\ZHandler.obj \
|
$O\ZHandler.obj \
|
||||||
$O\ZRegister.obj \
|
$O\ZRegister.obj \
|
||||||
@@ -345,6 +351,7 @@ OBJS = \
|
|||||||
$(RPM_OBJS) \
|
$(RPM_OBJS) \
|
||||||
$(SPLIT_OBJS) \
|
$(SPLIT_OBJS) \
|
||||||
$(TAR_OBJS) \
|
$(TAR_OBJS) \
|
||||||
|
$(WIM_OBJS) \
|
||||||
$(Z_OBJS) \
|
$(Z_OBJS) \
|
||||||
$(ZIP_OBJS) \
|
$(ZIP_OBJS) \
|
||||||
$(BZIP2_OBJS) \
|
$(BZIP2_OBJS) \
|
||||||
@@ -426,6 +433,8 @@ $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp
|
|||||||
$(COMPL)
|
$(COMPL)
|
||||||
$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
|
$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
|
||||||
$(COMPL)
|
$(COMPL)
|
||||||
|
$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
|
||||||
|
$(COMPL)
|
||||||
$(Z_OBJS): ../../Archive/Z/$(*B).cpp
|
$(Z_OBJS): ../../Archive/Z/$(*B).cpp
|
||||||
$(COMPL)
|
$(COMPL)
|
||||||
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
|
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
|
|||||||
12 ICON "../../Archive/Cpio/cpio.ico"
|
12 ICON "../../Archive/Cpio/cpio.ico"
|
||||||
13 ICON "../../Archive/Tar/tar.ico"
|
13 ICON "../../Archive/Tar/tar.ico"
|
||||||
14 ICON "../../Archive/GZip/gz.ico"
|
14 ICON "../../Archive/GZip/gz.ico"
|
||||||
|
15 ICON "../../Archive/Wim/wim.ico"
|
||||||
|
|
||||||
|
|
||||||
STRINGTABLE
|
STRINGTABLE
|
||||||
BEGIN
|
BEGIN
|
||||||
100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14"
|
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 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15"
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -234,6 +234,12 @@ STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
|
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
|
||||||
|
const PROPVARIANT *properties, UInt32 numProperties)
|
||||||
|
{
|
||||||
|
return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||||
{
|
{
|
||||||
return _writeCoderProperties->WriteCoderProperties(outStream);
|
return _writeCoderProperties->WriteCoderProperties(outStream);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class CFilterCoder:
|
|||||||
public ICryptoSetPassword,
|
public ICryptoSetPassword,
|
||||||
#endif
|
#endif
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
|
public ICompressSetCoderProperties,
|
||||||
public ICompressWriteCoderProperties,
|
public ICompressWriteCoderProperties,
|
||||||
// public ICryptoResetSalt,
|
// public ICryptoResetSalt,
|
||||||
public ICryptoResetInitVector,
|
public ICryptoResetInitVector,
|
||||||
@@ -54,6 +55,7 @@ protected:
|
|||||||
|
|
||||||
CMyComPtr<ICryptoSetPassword> _setPassword;
|
CMyComPtr<ICryptoSetPassword> _setPassword;
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
|
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
|
||||||
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
|
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
|
||||||
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
|
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
|
||||||
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
|
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
|
||||||
@@ -85,6 +87,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
|
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
|
||||||
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
|
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
|
||||||
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
|
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
|
||||||
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
|
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
|
||||||
@@ -110,6 +113,8 @@ public:
|
|||||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||||
#endif
|
#endif
|
||||||
#ifndef EXTRACT_ONLY
|
#ifndef EXTRACT_ONLY
|
||||||
|
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
|
||||||
|
const PROPVARIANT *properties, UInt32 numProperties);
|
||||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||||
// STDMETHOD(ResetSalt)();
|
// STDMETHOD(ResetSalt)();
|
||||||
STDMETHOD(ResetInitVector)();
|
STDMETHOD(ResetInitVector)();
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
HRes AllocateList(int numItems)
|
HRes AllocateList(int numItems)
|
||||||
{
|
{
|
||||||
if (!CResourceList::AllocateList(numItems))
|
if (!CResourceList::AllocateList(numItems))
|
||||||
return false;
|
return E_OUTOFMEMORY;
|
||||||
Semaphore.Close();
|
Semaphore.Close();
|
||||||
return Semaphore.Create(numItems, numItems);
|
return Semaphore.Create(numItems, numItems);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ int main2(int n, const char *args[])
|
|||||||
g_IsNT = IsItWindowsNT();
|
g_IsNT = IsItWindowsNT();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "\nLZMA 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-24\n");
|
fprintf(stderr, "\nLZMA 4.49 Copyright (c) 1999-2007 Igor Pavlov 2007-07-05\n");
|
||||||
|
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ namespace NLzx {
|
|||||||
|
|
||||||
const int kLenIdNeedInit = -2;
|
const int kLenIdNeedInit = -2;
|
||||||
|
|
||||||
CDecoder::CDecoder():
|
CDecoder::CDecoder(bool wimMode):
|
||||||
_keepHistory(false),
|
_keepHistory(false),
|
||||||
m_AlignPos(0)
|
m_AlignPos(0),
|
||||||
|
_wimMode(wimMode)
|
||||||
{
|
{
|
||||||
m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;
|
m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;
|
||||||
m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;
|
m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;
|
||||||
@@ -96,12 +97,18 @@ bool CDecoder::ReadTables(void)
|
|||||||
int blockType = (int)ReadBits(kNumBlockTypeBits);
|
int blockType = (int)ReadBits(kNumBlockTypeBits);
|
||||||
if (blockType > kBlockTypeUncompressed)
|
if (blockType > kBlockTypeUncompressed)
|
||||||
return false;
|
return false;
|
||||||
m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
|
if (_wimMode)
|
||||||
|
if (ReadBits(1) == 1)
|
||||||
|
m_UnCompressedBlockSize = (1 << 15);
|
||||||
|
else
|
||||||
|
m_UnCompressedBlockSize = ReadBits(16);
|
||||||
|
else
|
||||||
|
m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
|
||||||
|
|
||||||
m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);
|
m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);
|
||||||
if (m_IsUncompressedBlock)
|
if (m_IsUncompressedBlock)
|
||||||
{
|
{
|
||||||
m_InBitStream.ReadBits(16 - m_InBitStream.GetBitPosition());
|
ReadBits(16 - m_InBitStream.GetBitPosition());
|
||||||
if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))
|
if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))
|
||||||
return false;
|
return false;
|
||||||
m_RepDistances[0]--;
|
m_RepDistances[0]--;
|
||||||
@@ -171,12 +178,16 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize)
|
|||||||
{
|
{
|
||||||
m_UnCompressedBlockSize = 0;
|
m_UnCompressedBlockSize = 0;
|
||||||
ClearPrevLevels();
|
ClearPrevLevels();
|
||||||
UInt32 i86TranslationSize = 0;
|
UInt32 i86TranslationSize = 12000000;
|
||||||
bool translationMode = (ReadBits(1) != 0);
|
bool translationMode = true;
|
||||||
if (translationMode)
|
if (!_wimMode)
|
||||||
{
|
{
|
||||||
i86TranslationSize = ReadBits(16) << 16;
|
translationMode = (ReadBits(1) != 0);
|
||||||
i86TranslationSize |= ReadBits(16);
|
if (translationMode)
|
||||||
|
{
|
||||||
|
i86TranslationSize = ReadBits(16) << 16;
|
||||||
|
i86TranslationSize |= ReadBits(16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
|
m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ class CDecoder :
|
|||||||
int _remainLen;
|
int _remainLen;
|
||||||
int m_AlignPos;
|
int m_AlignPos;
|
||||||
|
|
||||||
|
bool _wimMode;
|
||||||
|
|
||||||
UInt32 ReadBits(UInt32 numBits);
|
UInt32 ReadBits(UInt32 numBits);
|
||||||
bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols);
|
bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols);
|
||||||
bool ReadTables();
|
bool ReadTables();
|
||||||
@@ -151,7 +153,7 @@ class CDecoder :
|
|||||||
const UInt64 *inSize, const UInt64 *outSize,
|
const UInt64 *inSize, const UInt64 *outSize,
|
||||||
ICompressProgressInfo *progress);
|
ICompressProgressInfo *progress);
|
||||||
public:
|
public:
|
||||||
CDecoder();
|
CDecoder(bool wimMode = false);
|
||||||
|
|
||||||
MY_UNKNOWN_IMP
|
MY_UNKNOWN_IMP
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,24 @@
|
|||||||
|
|
||||||
#include "RandGen.h"
|
#include "RandGen.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#define USE_POSIX_TIME
|
||||||
|
#define USE_POSIX_TIME2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POSIX_TIME
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef USE_POSIX_TIME2
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is not very good random number generator.
|
// This is not very good random number generator.
|
||||||
// Please use it only for salt.
|
// Please use it only for salt.
|
||||||
// First genrated data block depends from timer.
|
// First generated data block depends from timer and processID.
|
||||||
// Other genrated data blocks depend from previous state
|
// Other generated data blocks depend from previous state
|
||||||
// Maybe it's possible to restore original timer vaue from generated value.
|
// Maybe it's possible to restore original timer value from generated value.
|
||||||
|
|
||||||
void CRandomGenerator::Init()
|
void CRandomGenerator::Init()
|
||||||
{
|
{
|
||||||
@@ -24,6 +37,11 @@ void CRandomGenerator::Init()
|
|||||||
hash.Update((const Byte *)&w, sizeof(w));
|
hash.Update((const Byte *)&w, sizeof(w));
|
||||||
w = ::GetCurrentThreadId();
|
w = ::GetCurrentThreadId();
|
||||||
hash.Update((const Byte *)&w, sizeof(w));
|
hash.Update((const Byte *)&w, sizeof(w));
|
||||||
|
#else
|
||||||
|
pid_t pid = getpid();
|
||||||
|
hash.Update((const Byte *)&pid, sizeof(pid));
|
||||||
|
pid = getppid();
|
||||||
|
hash.Update((const Byte *)&pid, sizeof(pid));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
@@ -34,6 +52,19 @@ void CRandomGenerator::Init()
|
|||||||
hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart));
|
hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POSIX_TIME
|
||||||
|
#ifdef USE_POSIX_TIME2
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
time_t v2 = time(NULL);
|
||||||
|
hash.Update((const Byte *)&v2, sizeof(v2));
|
||||||
|
#endif
|
||||||
|
|
||||||
DWORD tickCount = ::GetTickCount();
|
DWORD tickCount = ::GetTickCount();
|
||||||
hash.Update((const Byte *)&tickCount, sizeof(tickCount));
|
hash.Update((const Byte *)&tickCount, sizeof(tickCount));
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ Handler GUIDs:
|
|||||||
09 Nsis
|
09 Nsis
|
||||||
0A Lzma
|
0A Lzma
|
||||||
|
|
||||||
|
E6 Wim
|
||||||
E7 Iso
|
E7 Iso
|
||||||
E8 Bkf
|
E8 Bkf
|
||||||
E9 Chm
|
E9 Chm
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#define MY_VER_MAJOR 4
|
#define MY_VER_MAJOR 4
|
||||||
#define MY_VER_MINOR 48
|
#define MY_VER_MINOR 49
|
||||||
#define MY_VER_BUILD 0
|
#define MY_VER_BUILD 0
|
||||||
#define MY_VERSION "4.48 beta"
|
#define MY_VERSION "4.49 beta"
|
||||||
#define MY_7ZIP_VERSION "7-Zip 4.48 beta"
|
#define MY_7ZIP_VERSION "7-Zip 4.49 beta"
|
||||||
#define MY_DATE "2007-06-26"
|
#define MY_DATE "2007-07-11"
|
||||||
#define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov"
|
#define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov"
|
||||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE
|
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE
|
||||||
|
|||||||
@@ -3,6 +3,21 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "ExtractingFilePath.h"
|
#include "ExtractingFilePath.h"
|
||||||
|
|
||||||
|
static UString ReplaceIncorrectChars(const UString &s)
|
||||||
|
{
|
||||||
|
UString res;
|
||||||
|
for (int i = 0; i < s.Length(); i++)
|
||||||
|
{
|
||||||
|
wchar_t c = s[i];
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"')
|
||||||
|
c = '_';
|
||||||
|
#endif
|
||||||
|
res += c;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void ReplaceDisk(UString &s)
|
static void ReplaceDisk(UString &s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -58,7 +73,7 @@ UString GetCorrectPath(const UString &path)
|
|||||||
result.Replace(L"../", L"");
|
result.Replace(L"../", L"");
|
||||||
|
|
||||||
ReplaceDisk(result);
|
ReplaceDisk(result);
|
||||||
return result;
|
return ReplaceIncorrectChars(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeCorrectPath(UStringVector &pathParts)
|
void MakeCorrectPath(UStringVector &pathParts)
|
||||||
|
|||||||
@@ -28,15 +28,21 @@ static const UINT kIconTypesResId = 100;
|
|||||||
using namespace NWindows;
|
using namespace NWindows;
|
||||||
using namespace NFile;
|
using namespace NFile;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
extern HINSTANCE g_hInstance;
|
extern HINSTANCE g_hInstance;
|
||||||
|
#endif
|
||||||
|
|
||||||
static CSysString GetLibraryFolderPrefix()
|
static CSysString GetLibraryFolderPrefix()
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
TCHAR fullPath[MAX_PATH + 1];
|
TCHAR fullPath[MAX_PATH + 1];
|
||||||
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
|
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
|
||||||
CSysString path = fullPath;
|
CSysString path = fullPath;
|
||||||
int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
|
int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
|
||||||
return path.Left(pos + 1);
|
return path.Left(pos + 1);
|
||||||
|
#else
|
||||||
|
return CSysString(); // FIX IT
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define kCodecsFolderName TEXT("Codecs")
|
#define kCodecsFolderName TEXT("Codecs")
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ static const char kArchiveAttributeChar = 'A';
|
|||||||
|
|
||||||
static const char *kListing = "Listing archive: ";
|
static const char *kListing = "Listing archive: ";
|
||||||
static const wchar_t *kFilesMessage = L"files";
|
static const wchar_t *kFilesMessage = L"files";
|
||||||
|
static const wchar_t *kDirsMessage = L"folders";
|
||||||
|
|
||||||
static void GetAttributesString(DWORD wa, bool directory, char *s)
|
static void GetAttributesString(DWORD wa, bool directory, char *s)
|
||||||
{
|
{
|
||||||
@@ -118,7 +119,7 @@ CFieldInfoInit kStandardFieldTable[] =
|
|||||||
{ kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
|
{ kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
|
||||||
{ kpidSize, L"Size", kRight, kRight, 1, 12 },
|
{ kpidSize, L"Size", kRight, kRight, 1, 12 },
|
||||||
{ kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
|
{ kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
|
||||||
{ kpidPath, L"Name", kLeft, kLeft, 2, 12 }
|
{ kpidPath, L"Name", kLeft, kLeft, 2, 24 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void PrintSpaces(int numSpaces)
|
void PrintSpaces(int numSpaces)
|
||||||
@@ -162,8 +163,8 @@ public:
|
|||||||
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
|
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
|
||||||
UInt32 index,
|
UInt32 index,
|
||||||
bool techMode);
|
bool techMode);
|
||||||
HRESULT PrintSummaryInfo(UInt64 numFiles, const UInt64 *size,
|
HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
|
||||||
const UInt64 *compressedSize);
|
const UInt64 *size, const UInt64 *compressedSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
|
void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
|
||||||
@@ -354,7 +355,7 @@ void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
|
HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
|
||||||
const UInt64 *size, const UInt64 *compressedSize)
|
const UInt64 *size, const UInt64 *compressedSize)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _fields.Size(); i++)
|
for (int i = 0; i < _fields.Size(); i++)
|
||||||
@@ -373,6 +374,11 @@ HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
|
|||||||
UString temp = textString;
|
UString temp = textString;
|
||||||
temp += L" ";
|
temp += L" ";
|
||||||
temp += kFilesMessage;
|
temp += kFilesMessage;
|
||||||
|
temp += L", ";
|
||||||
|
ConvertUInt64ToString(numDirs, textString);
|
||||||
|
temp += textString;
|
||||||
|
temp += L" ";
|
||||||
|
temp += kDirsMessage;
|
||||||
PrintString(fieldInfo.TextAdjustment, 0, temp);
|
PrintString(fieldInfo.TextAdjustment, 0, temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -403,7 +409,7 @@ HRESULT ListArchives(
|
|||||||
if (!techMode)
|
if (!techMode)
|
||||||
fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
|
fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
|
||||||
|
|
||||||
UInt64 numFiles2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
|
UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
|
||||||
UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
|
UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
|
||||||
for (int i = 0; i < archivePaths.Size(); i++)
|
for (int i = 0; i < archivePaths.Size(); i++)
|
||||||
{
|
{
|
||||||
@@ -465,7 +471,7 @@ HRESULT ListArchives(
|
|||||||
{
|
{
|
||||||
RINOK(fieldPrinter.Init(archive));
|
RINOK(fieldPrinter.Init(archive));
|
||||||
}
|
}
|
||||||
UInt64 numFiles = 0, totalPackSize = 0, totalUnPackSize = 0;
|
UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
|
||||||
UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
|
UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
|
||||||
UInt32 numItems;
|
UInt32 numItems;
|
||||||
RINOK(archive->GetNumberOfItems(&numItems));
|
RINOK(archive->GetNumberOfItems(&numItems));
|
||||||
@@ -495,8 +501,11 @@ HRESULT ListArchives(
|
|||||||
totalPackSizePointer = &totalPackSize;
|
totalPackSizePointer = &totalPackSize;
|
||||||
|
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
|
|
||||||
numFiles++;
|
if (isFolder)
|
||||||
|
numDirs++;
|
||||||
|
else
|
||||||
|
numFiles++;
|
||||||
totalPackSize += packSize;
|
totalPackSize += packSize;
|
||||||
totalUnPackSize += unpackSize;
|
totalUnPackSize += unpackSize;
|
||||||
}
|
}
|
||||||
@@ -504,7 +513,7 @@ HRESULT ListArchives(
|
|||||||
{
|
{
|
||||||
fieldPrinter.PrintTitleLines();
|
fieldPrinter.PrintTitleLines();
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
fieldPrinter.PrintSummaryInfo(numFiles, totalUnPackSizePointer, totalPackSizePointer);
|
fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
}
|
}
|
||||||
if (totalPackSizePointer != 0)
|
if (totalPackSizePointer != 0)
|
||||||
@@ -518,13 +527,14 @@ HRESULT ListArchives(
|
|||||||
totalUnPackSize2 += totalUnPackSize;
|
totalUnPackSize2 += totalUnPackSize;
|
||||||
}
|
}
|
||||||
numFiles2 += numFiles;
|
numFiles2 += numFiles;
|
||||||
|
numDirs2 += numDirs;
|
||||||
}
|
}
|
||||||
if (enableHeaders && !techMode && archivePaths.Size() > 1)
|
if (enableHeaders && !techMode && archivePaths.Size() > 1)
|
||||||
{
|
{
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
fieldPrinter.PrintTitleLines();
|
fieldPrinter.PrintTitleLines();
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
fieldPrinter.PrintSummaryInfo(numFiles2, totalUnPackSizePointer2, totalPackSizePointer2);
|
fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
|
||||||
g_StdOut << endl;
|
g_StdOut << endl;
|
||||||
g_StdOut << "Archives: " << archivePaths.Size() << endl;
|
g_StdOut << "Archives: " << archivePaths.Size() << endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ STDMETHODIMP CExtractCallBackImp::SetCompleted(const UINT64 *completeValue)
|
|||||||
|
|
||||||
STDMETHODIMP CExtractCallBackImp::AskOverwrite(
|
STDMETHODIMP CExtractCallBackImp::AskOverwrite(
|
||||||
const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
|
const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
|
||||||
const wchar_t *newName, const FILETIME *aNewTime, const UINT64 *newSize,
|
const wchar_t *newName, const FILETIME *newTime, const UINT64 *newSize,
|
||||||
INT32 *answer)
|
INT32 *answer)
|
||||||
{
|
{
|
||||||
NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
|
NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
|
||||||
@@ -67,8 +67,9 @@ STDMETHODIMP CExtractCallBackImp::AskOverwrite(
|
|||||||
oldFileInfo.Size = *existSize;
|
oldFileInfo.Size = *existSize;
|
||||||
oldFileInfo.Name = GetSystemString(existName, m_CodePage);
|
oldFileInfo.Name = GetSystemString(existName, m_CodePage);
|
||||||
|
|
||||||
|
newFileInfo.TimeIsDefined = (newTime != 0);
|
||||||
newFileInfo.Time = *aNewTime;
|
if (newFileInfo.TimeIsDefined)
|
||||||
|
newFileInfo.Time = *newTime;
|
||||||
|
|
||||||
newFileInfo.SizeIsDefined = (newSize != NULL);
|
newFileInfo.SizeIsDefined = (newSize != NULL);
|
||||||
if (newFileInfo.SizeIsDefined)
|
if (newFileInfo.SizeIsDefined)
|
||||||
|
|||||||
@@ -42,14 +42,17 @@ void SetFileInfoStrings(const CFileInfo &fileInfo,
|
|||||||
fileInfoStrings.Size = "";
|
fileInfoStrings.Size = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
FILETIME localFileTime;
|
FILETIME localFileTime;
|
||||||
if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
|
fileInfoStrings.Time.Empty();
|
||||||
throw 4190402;
|
if (fileInfo.TimeIsDefined)
|
||||||
UString timeString = ConvertFileTimeToString(localFileTime);
|
{
|
||||||
|
if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
|
||||||
fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
|
throw 4190402;
|
||||||
fileInfoStrings.Time += " ";
|
UString timeString = ConvertFileTimeToString(localFileTime);
|
||||||
fileInfoStrings.Time += GetSystemString(timeString, CP_OEMCP);
|
fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
|
||||||
|
fileInfoStrings.Time += " ";
|
||||||
|
fileInfoStrings.Time += GetSystemString(timeString, CP_OEMCP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo)
|
NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace NOverwriteDialog {
|
|||||||
struct CFileInfo
|
struct CFileInfo
|
||||||
{
|
{
|
||||||
bool SizeIsDefined;
|
bool SizeIsDefined;
|
||||||
|
bool TimeIsDefined;
|
||||||
UINT64 Size;
|
UINT64 Size;
|
||||||
FILETIME Time;
|
FILETIME Time;
|
||||||
CSysString Name;
|
CSysString Name;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Plugin.h"
|
#include "Plugin.h"
|
||||||
|
|
||||||
|
#include "Common/Wildcard.h"
|
||||||
#include "Common/StringConvert.h"
|
#include "Common/StringConvert.h"
|
||||||
|
|
||||||
#include "Windows/FileDir.h"
|
#include "Windows/FileDir.h"
|
||||||
@@ -318,6 +319,80 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
|
|||||||
return NFileOperationReturnCode::kSuccess;
|
return NFileOperationReturnCode::kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace NPathType
|
||||||
|
{
|
||||||
|
enum EEnum
|
||||||
|
{
|
||||||
|
kLocal,
|
||||||
|
kUNC
|
||||||
|
};
|
||||||
|
EEnum GetPathType(const UString &path);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CParsedPath
|
||||||
|
{
|
||||||
|
UString Prefix; // Disk or UNC with slash
|
||||||
|
UStringVector PathParts;
|
||||||
|
void ParsePath(const UString &path);
|
||||||
|
UString MergePath() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wchar_t kDirDelimiter = WCHAR_PATH_SEPARATOR;
|
||||||
|
static const wchar_t kDiskDelimiter = L':';
|
||||||
|
|
||||||
|
namespace NPathType
|
||||||
|
{
|
||||||
|
EEnum GetPathType(const UString &path)
|
||||||
|
{
|
||||||
|
if (path.Length() <= 2)
|
||||||
|
return kLocal;
|
||||||
|
if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)
|
||||||
|
return kUNC;
|
||||||
|
return kLocal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CParsedPath::ParsePath(const UString &path)
|
||||||
|
{
|
||||||
|
int curPos = 0;
|
||||||
|
switch (NPathType::GetPathType(path))
|
||||||
|
{
|
||||||
|
case NPathType::kLocal:
|
||||||
|
{
|
||||||
|
int posDiskDelimiter = path.Find(kDiskDelimiter);
|
||||||
|
if(posDiskDelimiter >= 0)
|
||||||
|
{
|
||||||
|
curPos = posDiskDelimiter + 1;
|
||||||
|
if (path.Length() > curPos)
|
||||||
|
if(path[curPos] == kDirDelimiter)
|
||||||
|
curPos++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NPathType::kUNC:
|
||||||
|
{
|
||||||
|
int curPos = path.Find(kDirDelimiter, 2);
|
||||||
|
if(curPos < 0)
|
||||||
|
curPos = path.Length();
|
||||||
|
else
|
||||||
|
curPos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Prefix = path.Left(curPos);
|
||||||
|
SplitPathToParts(path.Mid(curPos), PathParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
UString CParsedPath::MergePath() const
|
||||||
|
{
|
||||||
|
UString result = Prefix;
|
||||||
|
for(int i = 0; i < PathParts.Size(); i++)
|
||||||
|
{
|
||||||
|
if (i != 0)
|
||||||
|
result += kDirDelimiter;
|
||||||
|
result += PathParts[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -375,7 +450,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
|
|||||||
|
|
||||||
UString resultPath;
|
UString resultPath;
|
||||||
{
|
{
|
||||||
NName::CParsedPath parsedPath;
|
CParsedPath parsedPath;
|
||||||
parsedPath.ParsePath(fileNames.Front());
|
parsedPath.ParsePath(fileNames.Front());
|
||||||
if(parsedPath.PathParts.Size() == 0)
|
if(parsedPath.PathParts.Size() == 0)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|||||||
+1
-1
@@ -10,13 +10,13 @@ template <class T> class CBuffer
|
|||||||
protected:
|
protected:
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
T *_items;
|
T *_items;
|
||||||
|
public:
|
||||||
void Free()
|
void Free()
|
||||||
{
|
{
|
||||||
delete []_items;
|
delete []_items;
|
||||||
_items = 0;
|
_items = 0;
|
||||||
_capacity = 0;
|
_capacity = 0;
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
CBuffer(): _capacity(0), _items(0) {};
|
CBuffer(): _capacity(0), _items(0) {};
|
||||||
CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }
|
CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }
|
||||||
CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); }
|
CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)
|
|||||||
{
|
{
|
||||||
if (base < 2 || base > 36)
|
if (base < 2 || base > 36)
|
||||||
{
|
{
|
||||||
*s = L'\0';
|
*s = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char temp[72];
|
char temp[72];
|
||||||
|
|||||||
@@ -9,13 +9,6 @@ namespace NWindows {
|
|||||||
namespace NFile {
|
namespace NFile {
|
||||||
namespace NName {
|
namespace NName {
|
||||||
|
|
||||||
static const wchar_t kDiskDelimiter = L':';
|
|
||||||
|
|
||||||
/*
|
|
||||||
static bool IsCharAPrefixDelimiter(wchar_t c)
|
|
||||||
{ return (c == kDirDelimiter || c == kDiskDelimiter); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
void NormalizeDirPathPrefix(CSysString &dirPath)
|
void NormalizeDirPathPrefix(CSysString &dirPath)
|
||||||
{
|
{
|
||||||
if (dirPath.IsEmpty())
|
if (dirPath.IsEmpty())
|
||||||
@@ -34,59 +27,7 @@ void NormalizeDirPathPrefix(UString &dirPath)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace NPathType
|
#ifdef _WIN32
|
||||||
{
|
|
||||||
EEnum GetPathType(const UString &path)
|
|
||||||
{
|
|
||||||
if (path.Length() <= 2)
|
|
||||||
return kLocal;
|
|
||||||
if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)
|
|
||||||
return kUNC;
|
|
||||||
return kLocal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParsedPath::ParsePath(const UString &path)
|
|
||||||
{
|
|
||||||
int curPos = 0;
|
|
||||||
switch (NPathType::GetPathType(path))
|
|
||||||
{
|
|
||||||
case NPathType::kLocal:
|
|
||||||
{
|
|
||||||
int posDiskDelimiter = path.Find(kDiskDelimiter);
|
|
||||||
if(posDiskDelimiter >= 0)
|
|
||||||
{
|
|
||||||
curPos = posDiskDelimiter + 1;
|
|
||||||
if (path.Length() > curPos)
|
|
||||||
if(path[curPos] == kDirDelimiter)
|
|
||||||
curPos++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NPathType::kUNC:
|
|
||||||
{
|
|
||||||
int curPos = path.Find(kDirDelimiter, 2);
|
|
||||||
if(curPos < 0)
|
|
||||||
curPos = path.Length();
|
|
||||||
else
|
|
||||||
curPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Prefix = path.Left(curPos);
|
|
||||||
SplitPathToParts(path.Mid(curPos), PathParts);
|
|
||||||
}
|
|
||||||
|
|
||||||
UString CParsedPath::MergePath() const
|
|
||||||
{
|
|
||||||
UString result = Prefix;
|
|
||||||
for(int i = 0; i < PathParts.Size(); i++)
|
|
||||||
{
|
|
||||||
if (i != 0)
|
|
||||||
result += kDirDelimiter;
|
|
||||||
result += PathParts[i];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wchar_t kExtensionDelimiter = L'.';
|
const wchar_t kExtensionDelimiter = L'.';
|
||||||
|
|
||||||
@@ -108,4 +49,6 @@ void SplitNameToPureNameAndExtension(const UString &fullName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|||||||
+2
-18
@@ -17,26 +17,10 @@ void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with
|
|||||||
void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'
|
void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace NPathType
|
#ifdef _WIN32
|
||||||
{
|
|
||||||
enum EEnum
|
|
||||||
{
|
|
||||||
kLocal,
|
|
||||||
kUNC
|
|
||||||
};
|
|
||||||
EEnum GetPathType(const UString &path);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CParsedPath
|
|
||||||
{
|
|
||||||
UString Prefix; // Disk or UNC with slash
|
|
||||||
UStringVector PathParts;
|
|
||||||
void ParsePath(const UString &path);
|
|
||||||
UString MergePath() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SplitNameToPureNameAndExtension(const UString &fullName,
|
void SplitNameToPureNameAndExtension(const UString &fullName,
|
||||||
UString &pureName, UString &extensionDelimiter, UString &extension);
|
UString &pureName, UString &extensionDelimiter, UString &extension);
|
||||||
|
#endif
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
;Defines
|
;Defines
|
||||||
|
|
||||||
!define VERSION_MAJOR 4
|
!define VERSION_MAJOR 4
|
||||||
!define VERSION_MINOR 48
|
!define VERSION_MINOR 49
|
||||||
!define VERSION_POSTFIX_FULL " beta"
|
!define VERSION_POSTFIX_FULL " beta"
|
||||||
!ifdef WIN64
|
!ifdef WIN64
|
||||||
!ifdef IA64
|
!ifdef IA64
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<?define VerMajor = "4" ?>
|
<?define VerMajor = "4" ?>
|
||||||
<?define VerMinor = "48" ?>
|
<?define VerMinor = "49" ?>
|
||||||
<?define VerBuild = "00" ?>
|
<?define VerBuild = "00" ?>
|
||||||
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
||||||
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
|
<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
|
||||||
|
|||||||
+3
-4
@@ -1,4 +1,4 @@
|
|||||||
LZMA SDK 4.46
|
LZMA SDK 4.49
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
LZMA SDK Copyright (C) 1999-2007 Igor Pavlov
|
LZMA SDK Copyright (C) 1999-2007 Igor Pavlov
|
||||||
@@ -178,10 +178,9 @@ CPP -- CPP files
|
|||||||
Common - common files for archive handling
|
Common - common files for archive handling
|
||||||
7z - 7z C++ Encoder/Decoder
|
7z - 7z C++ Encoder/Decoder
|
||||||
|
|
||||||
Bundle - Modules that are bundles of other modules
|
Bundles - Modules that are bundles of other modules
|
||||||
|
|
||||||
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
|
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
|
||||||
|
|
||||||
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
|
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
|
||||||
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
|
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
7-Zip 4.47 Sources
|
7-Zip 4.49 Sources
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
7-Zip is a file archiver for Windows 95/98/ME/NT/2000/2003/XP/Vista.
|
7-Zip is a file archiver for Windows 95/98/ME/NT/2000/2003/XP/Vista.
|
||||||
|
|||||||
Reference in New Issue
Block a user